为什么此汇编代码无法打印到 VGA 文本模式显存?

Why does this assembly code not working to print to VGA text mode video memory?

我有以下汇编代码。我正在尝试创建一个小型引导加载程序以进入 32 位保护模式。进入保护模式后,我需要打印到 VGA 文本模式视频内存 (0xb8000) 以进行测试。我的代码不起作用。我从网络上的各种资源中找到了代码,并了解到大多数代码都有类似的代码可以正常工作,比如这个例子: 。我的代码不起作用:

bits 16

mov ah, 0x00  ;Set up video mode
mov al, 0x03
int 0x10

gdt_start:
        dq 0x0
gdt_code:
        dw 0xFFFF
        dw 0x0
        db 0x0
        db 10011010b
        db 11001111b
        db 0x0
gdt_data:
        dw 0xFFFF
        dw 0x0
        db 0x0
        db 10010010b
        db 11001111b
        db 0x0  

gdtr:
        dw 24
        dd gdt_start

lgdt [gdtr]

cli

mov eax, cr0
or al, 1
mov cr0, eax

jmp 0x08:protectedMode 

bits 32

protectedMode:
    mov ax, 0x10
    mov ds, ax
    mov es, ax 
    mov fs, ax
    mov gs, ax
    mov ss, ax

    mov word [0xb8000], 0x0769 

times 510 - ($-$$) db 0
dw 0xaa55

我用以下代码编译代码:

nasm -fbin boot.asm -oboot.bin

和 运行 结果为:

qemu-system-x86_64 -fda boot.bin

它什么也没做。

当我反汇编代码时:

ndisasm boot.bin

它输出以下结果:

为什么追加零之前的指令

mov dword [di], 0xb8000

应该是

mov word [0xb8000], 0x0769

当你有这个数据块时:

gdt_start:
        dq 0x0
gdt_code:
        dw 0xFFFF
        dw 0x0
        db 0x0
        db 10011010b
        db 11001111b
        db 0x0
gdt_data:
        dw 0xFFFF
        dw 0x0
        db 0x0
        db 10010010b
        db 11001111b
        db 0x0  

gdtr:
        dw 24
        dd gdt_start

它位于执行路径中。此数据将作为代码由处理器作为 int 0x10 之后的下一条指令执行。在 mov word [0xb8000], 0x0769.

之后将其下移

您还需要在执行该指令后添加一个无限循环,以防止执行下降到后面的任何垃圾(GDT table 如果您将其放在那里)。

永远记住汇编是非常底层的。无论您在代码中坚持什么,无论是否实际有意义的指令,如果处理器到达它,都将被视为代码。它不会跳过数据,也不会在您编写的最后一条指令后停止。


至于指令反汇编错误的原因,反汇编程序不知道什么时候切换到32位模式。它只是一个反汇编器,而不是一个模拟器,所以它看不到在 32 位模式下获取 CPU 执行该部分的 far jmp 的效果。

你可以在 32 位模式下反汇编整个东西,然后(在反汇编之前发生一些混乱之后恰好与实际指令边界同步)它反汇编成你想要的:

ndisasm -b 32 boot.bin
...                 ;; some earlier mess of 16-bit code disassembled as 32
0000003B  8ED8              mov ds,eax
0000003D  8EC0              mov es,eax
0000003F  8EE0              mov fs,eax
00000041  8EE8              mov gs,eax
00000043  8ED0              mov ss,eax
00000045  66C70500800B0069  mov word [dword 0xb8000],0x769   ; correct disassembly
         -07
0000004E  0000              add [eax],al
00000050  0000              add [eax],al