【发布时间】:2019-04-06 20:05:24
【问题描述】:
我想制作一个在没有 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。我该如何解决?
【问题讨论】:
-
我怀疑 print_string_esi 被汇编为 16 位代码,但以 32 位模式执行。如果是这样,汇编器将插入一个操作数大小前缀(以在 16 位模式下访问 ebx),但在 32 位模式下执行时会导致它作为 16 位指令执行。
标签: assembly operating-system nasm