【发布时间】:2017-07-12 16:13:30
【问题描述】:
我正在使用一个简单的程序集 sn-p 来使用 BIOS 作为引导加载程序的一部分将字符打印到屏幕上。这是引导加载程序代码。
[org 0x7c00]
[bits 16]
%include "a20_check.asm"
mov ah, 0x0e
mov al, 'H'
int 0x10
times 510 - ($-$$) db 0
dw 0xaa55
这是 a20_check.asm 函数的代码,取自 osdev.org。
[bits 16]
; Returns: 0 in ax if the a20 line is disabled (memory wraps around)
; 1 in ax if the a20 line is enabled (memory does not wrap around)
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
问题似乎出在最后一个标签中,check_a20__exit。如果我注释掉ret,那么字符就会打印到屏幕上。否则不打印。
谁能给我解释一下这个问题?
【问题讨论】:
-
也许你应该在 "mov ax, 1" 之后写一个跳转代码,它跳转到 "check_a20__exit" 最后一行之外的代码 我的理论是你的代码没有从该行跳转到 "check_a20__exit" “je check_a20__exit”这导致“je check_a20__exit”之后的代码被执行,它也执行“check_a20__exit”,因为“check_a20__exit”只是一个标签,而不是c ++中的函数。因此,我们在没有先前匹配跳转的情况下调用了 ret 语句。在“je check_a20__exit”指令之前检查零标志的值。
-
运行此代码的硬件环境是什么? "mov ax,0" 试图通过使累加器寄存器为零来设置零标志。
-
代码正在使用 i386 架构的 qemu 仿真运行。
-
@SahilSingh : MOV 指令不会改变标志。
-
@SahilSingh
je check_a20__exit的标志由cmp byte [es:di], 0xFF设置。 “A20”的代码并非微不足道,除非你真的很了解这些东西,否则不要试图猜测它是如何工作的。顺便说一句,axinit to 0/1 可以用无分支方式重写:sbb ax,axinc ax
标签: assembly x86 bootloader bios x86-16