Assert A20

ShiftLeft 0 Tallied Votes 276 Views Share

For those interested in operating system development, this snippet tests status of A20. It is the line that allows memory beyond 1 meg to be addressed, otherwise it will just wrap around which some applications and versions of DOS depend on.

My bootloader MBR1_44 has switched system to protected (32 bit) mode at this point.

Written for FASM 1.71.17

; =============================================================================================
; MBR1_44 has passed a flat memory model for a full 4 gig and registers in following state;

;       EBP -> Points to 192 byte scratch area just above stack
;       ESP -> Points to 64k stack that was initialized to -1's

;                  CS -> Code segment
;        DS - ES - SS -> Data Segment
;             FS - GS -> NULL
; ---------------------------------------------------------------------------------------------


    ; Now we can turn A20 on. Point to a pair of locations where wrap around can be determined.

        mov     esi, 0x7d2c             ; Point to any volatile place in boot sector
        mov     edi, esi
        bts     edi, 20                 ; Point to same address in next meg of memory

    ; Procedure will set of 4 colors.

    ;    (1) Green, A20 was already on
    ;    (2) Yellow, Fast A20 gate succeeded, but took ECX times
    ;    (3) Brown, A20 activated using fast method
    ;    (4) Red, couldn't turn on A20 so alternate method must be implemented

        mov     dl, GREEN               ; Assume A20 is already.
        or      ecx, -1                 ; Large retry count, but probably won't be needed.

    ; Will loop back to here until retry count in ECX is exhausted.

        push    esi
        push    edi
        lodsd                           ; Read dword from boot sector
        not     eax                     ; Invert 32 bits
        stosd                           ; Write back
        cmp     [esi - 4], eax          ; Are they the same
        pop     esi
        pop     edi
        jnz     .Ok                     ; ZF = 1, A20 is already on. Probably in BOCHS.

    ; Set color to YELLOW indicating gate was not active, but this method succeeded.

        mov     dl, YELLOW
        in      al, A20_GATE
        or      al, 2
        out     A20_GATE, al
        dec     ecx
        jnz     .Retry

    ; *** TO DO ***
    ; This is where an alternate method would be implemented, but all my test computers
    ; succeeded with this method, so I'll assume most others will work too.

        mov     dl, RED                 ; All methods will fall through to here if they fail.
        jmp     @F

   .Ok: inc     ecx                     ; Bump ECX. It will be NULL if gate was already on
        jz      @F

    ; We will always get to this point unless in BOCHS or another emulator where A20 is
    ; already on. If method only needed to be used once, color will not be changed

        not     ecx                     ; Indicates actual number of retries
        or      ecx, ecx
        jz      @F                      ; Don't change if we only tried Fast A20 gate once.

        mov     dl, BROWN               ; Indicates there were retrys with fast method

    @@: mov     [A20_STATUS], dl        ; Write status of operation to scatch area