Как вы включаете A20 в Nasm? - PullRequest
0 голосов
/ 30 января 2019

Я пытаюсь перейти в длинный режим в моем загрузчике, и теперь я нахожусь на первой части с включением линии a20, но я столкнулся с проблемой, и это то, что мой код, который я сделал, только что сделал экран полностьючерный и число, которое должно сказать, что это сработало, даже не показывало

Я пробовал много разных функций a20 в интернете, но у меня пока ничего не получалось.

Код дляфункции:

check_a20:
    pushf
    push ds
    push es
    push di
    push si
    cli
    xor ax, ax ; ax = 0
    mov es, ax
    not ax ; ax = 0xFFFF
    mov ds, ax
    mov di, 0x0500
    mov si, 0x0510
    mov al, byte [es:di]
    push ax
    mov al, byte [ds:si]
    push ax
    mov byte [es:di], 0x00
    mov byte [ds:si], 0xFF
    cmp byte [es:di], 0xFF
    pop ax
    mov byte [ds:si], al
    pop ax
    mov byte [es:di], al
    mov ax, 0
    je check_a20_exit
    mov ax, 1
    check_a20_exit:
    pop si
    pop di
    pop es
    pop ds
    popf
ret

seta20: ;Enable the a20 line if it worked then ax = 1 else 0
    pusha
    call check_a20 ;Check a20
    cmp ax, 1
    je .end ;If it worked then end function else:
    .keyboard: ;Test the 8042 keyboard controller
        call .empty_8042
        mov al, 0xd1 ;command write
        out 0x64, al
        call .empty_8042
        mov al, 0xdf ; A20 on
        out 0x60, al
        call .empty_8042 ;wait
    .empty_8042: ;For the 8042 function over this
        in al, 0x64
        test al, 2
        jnz .empty_8042
    ret
    call check_a20  ;Check a20
    cmp ax, 1
    je .end ;If it worked then end function else:
    .fasta20:
    in al, 0x92
    or al, 2
    out 0x92, al
    .end:
    popa
    call check_a20
ret

И после этих функций у меня была функция печати топора в шестнадцатеричном виде:

main:

    ;Stack, video and other setups(not important)

    call seta20 ;Set a20

    mov dl, 00h ;Set cursor for a print a20 check
    mov dh, 01h 
    mov bh, 00h
    mov ah, 02h
    int 10h

    call check_a20 ;Check a20
    mov dl, al
    mov bl, 02h
    call printhex ;Print dl

    jmp $   ;Infinite loop

printhex: ;print hex input(dl=value, bl=color) 8 bit
    pusha
    mov dh, 0x00
    mov ch, dl ;unshifted (for next hex)
    shr dl, 4 ; get high 4 bits(HEX)
    cmp dl, 9
    jna .1to9 
    .atof: ;if the number is a to f
        add dl, 55
        jmp .next
    .1to9:
        add dl, 48 ;add 48 to make it into a number
    .next:
        mov ah, 0Eh ;print char mode
        mov bh, 0
        mov al, dl
        int 10h ;Print 1st number of the two
    shl ch, 4
    mov dl, ch
    shr dl, 4 ; get high 4 bits(HEX)
    cmp dl, 9
    jna .1to92 
    .atof2: ;if the number is a to f
        add dl, 55
        jmp .print2
    .1to92:
        add dl, 48 ;add 48 to make it into a number
    .print2:
        mov ah, 0Eh ;print char mode
        mov bh, 0
        mov al, dl
        int 10h ;Print 1st number of the two
     popa
ret

Я уже знал, что моя функция для печати результатов работает, потому что я проверилэто так много раз, но должно получиться, что он напечатает шестнадцатеричное число с моей функцией printhex16, которая была у меня

1 Ответ

0 голосов
/ 31 января 2019

Методология вашего кода A20 выглядит хорошо, но, похоже, у вас есть ошибка в том, как вы ее реализовали.У вас есть этот код для seta20:

seta20: ;Enable the a20 line if it worked then ax = 1 else 0
    pusha
    call check_a20 ;Check a20
    cmp ax, 1
    je .end ;If it worked then end function else:
    .keyboard: ;Test the 8042 keyboard controller
        call .empty_8042
        mov al, 0xd1 ;command write
        out 0x64, al
        call .empty_8042
        mov al, 0xdf ; A20 on
        out 0x60, al
        call .empty_8042 ;wait
    .empty_8042: ;For the 8042 function over this
        in al, 0x64
        test al, 2
        jnz .empty_8042
    ret
    call check_a20  ;Check a20
    cmp ax, 1
    je .end ;If it worked then end function else:
    .fasta20:
    in al, 0x92
    or al, 2
    out 0x92, al
    .end:
    popa
    call check_a20
ret

Проблема заключается в том, что вы поместили функцию в другую и непреднамеренно допустили попадание вашего кода в функцию.В частности, эти строки кода являются проблемой:

        out 0x60, al
        call .empty_8042 ;wait
    .empty_8042: ;For the 8042 function over this
        in al, 0x64
        test al, 2
        jnz .empty_8042
        ret
    call check_a20  ;Check a20

call .empty_8042 вызовет функцию .empty_8042, 8042 будет сброшен;ret вернется к инструкции после call .empty_8042 и затем начнет выполнение кода в .empty_8042.Проблема во второй раз, когда он не вызывается как функция, поэтому нет правильного адреса возврата.Когда он достигнет ret, он попытается вернуться к любому значению на вершине стека.Это может привести к зависанию вашего кода, перезагрузке системы или другим непредвиденным действиям.

Быстрое исправление заключается в размещении инструкции JMP для пропуска кода в .empty_8042.Примерно так:

        out 0x60, al
        call .empty_8042 ;wait
        jmp .skip_function
    .empty_8042: ;For the 8042 function over this
        in al, 0x64
        test al, 2
        jnz .empty_8042
        ret
.skip_function:
    call check_a20  ;Check a20

Было бы предпочтительнее отделить функцию .empty_8042 от функции seta20, чтобы вам не пришлось излишне перепрыгивать через .empty_8042.Ваш код может выглядеть так:

empty_8042:
    in al, 0x64
    test al, 2
    jnz empty_8042
    ret

seta20: ;Enable the a20 line if it worked then ax = 1 else 0
    pusha
    call check_a20 ;Check a20
    cmp ax, 1
    je .end ;If it worked then end function else:
    .keyboard: ;Test the 8042 keyboard controller
        call empty_8042
        mov al, 0xd1 ;command write
        out 0x64, al
        call empty_8042
        mov al, 0xdf ; A20 on
        out 0x60, al
        call empty_8042 ;wait

    call check_a20  ;Check a20
    cmp ax, 1
    je .end ;If it worked then end function else:
    .fasta20:
    in al, 0x92
    or al, 2
    out 0x92, al
    .end:
    popa
    call check_a20
    ret
...