Почему NASM не инициализирует значение регистра должным образом? - PullRequest
0 голосов
/ 06 апреля 2019

Я хочу сделать драйвер, который печатает строку на экране без BIOS (в защищенном режиме).Я использую QEMU (используя qemu-system-x64_86) и NASM.

Я пытаюсь переместить адрес 0xb8000 в ebx, но что-то идет не так, вот код этапа второго загрузчика, где яя пытаюсь переключиться на PM и вызвать мою функцию драйвера:

bits 16
org 0x7e00

jmp main

%include "./lib/gdt.inc"
%include "./lib/driver_print_string.asm"    ; THE function


main:
    cli                       ; disable interrupts
    xor ax, ax                ; null segments
    mov ds, ax
    mov es, ax
    mov ss, ax
    mov sp, 0x07c0            ; the stack is under 0x7c00
    sti                       ; enable interrupts

call installGDT           ; installing GDT!!!

; ENTERING PM MODE!
cli
mov eax, cr0
or eax, 1
mov cr0, eax

jmp 0x8:final_stage


; =============================================================
; FINAL STAGE!
bits 32

final_stage:
    cli

    mov ax, 0x10
    mov ds, ax
    mov es, ax
    mov ss, ax

    mov esp, 0x07c0

dr_calling:
    mov esi, sty

    call print_string_esi


jmp $


sty: db "The driver is working!", 0

times 512 - ($ - $$) db 0

gdt.inc:

bits 16

installGDT:
    cli
    pusha
    lgdt [toc]
    sti
    popa
    ret

;*******************************************
; Global Descriptor Table (GDT)
;*******************************************

gdt_data:
    dd 0                ; null descriptor
    dd 0

; gdt code:             ; code descriptor
    dw 0FFFFh           ; limit low
    dw 0                ; base low
    db 0                ; base middle
    db 10011010b            ; access
    db 11001111b            ; granularity
    db 0                ; base high

; gdt data:             ; data descriptor
    dw 0FFFFh           ; limit low (Same as code)
    dw 0                ; base low
    db 0                ; base middle
    db 10010010b            ; access
    db 11001111b            ; granularity
    db 0                ; base high

end_of_gdt:
toc:
    dw end_of_gdt - gdt_data - 1    ; limit (Size of GDT)
    dd gdt_data             ; base of GDT

И driver_print_string.asm:

print_string_esi:
    mov ebx, 0xb8000

    mov byte [ebx], 'x'
    mov byte [ebx+1], 0x7       

    jmp $

Но ничегоработает.Если я написал «информационные регистры» в командной строке QEMU, это показывает, что EBX = 00008000, но почему это не b8000?Если я выполнил эту измененную функцию dr_calling:

dr_calling:
    mov esi, sty
    mov ebx, 0xb8000

    mov byte [ebx], 'x'
    mov byte [ebx+1], 0x7

    jmp $

все работает, и QEMU показывает, что EBX = 000b8000.Как я могу это исправить?

1 Ответ

1 голос
/ 06 апреля 2019

Поскольку driver_print_string.asm включен после bits 16 в начале, он будет скомпилирован как 16-битный код с 32-битной адресацией. но вы называете это из 32-битного кода ниже. если вы включите его, он будет скомпилирован как 32-битный код. просто включите эту функцию где-то ниже bits 32

...