【发布时间】:2017-08-08 09:40:25
【问题描述】:
我是一个初学者,出于某种原因,从堆栈中推入和弹出并不适合我。我的引导程序:
org 0x7c00
bits 16
jmp main
print:
pop bx
mov al, [bx]
mov ah, 0eh
int 10h
ret
main:
mov bx, msg
push bx
call print
cli
hlt
msg: db 'Hello World!', 0
times 510 - ($-$$) db 0
dw 0xAA55
我相信这应该做的是,将地址msg 从bx 压入堆栈,然后将其检索到bx。然而,情况似乎并非如此。 'H' 不会被打印出来。而是打印 '-'。如果我使用msg 作为有效地址,它就可以工作。
编辑:正如 Duncan 指出的,call 指令将返回地址压入堆栈顶部,这使得上述程序使用该返回地址进行 BIOS 中断!我现在把pop的返回地址改成dx然后把pop改成bx,完成后使用bx和jmp的值改成dx!
org 0x7c00
bits 16
jmp main
print:
pop dx
pop bx
mov al, [bx]
mov ah, 0eh
int 10h
jmp dx
main:
mov bx, msg
push bx
call print
cli
hlt
msg: db 'Hello World!', 0
times 510 - ($-$$) db 0
dw 0xAA55
【问题讨论】:
-
当然还有
dx是否保留在int 10h调用上的问题。 -
那个“修复”是不合理的复杂 IMO。而且脆弱..如果有的话,您可以在
pop bx之后立即执行push dx,然后使用ret,因此您无需担心dx,但如果您坚持通过堆栈传递参数,您应该宁可做冗长的push bpmov bp,spnaive-C 堆栈框架的事情(然后mov bx,[bp+4]是第一个参数),因为这对于任何有经验的 ASM 程序员来说都很容易阅读,所以以后会更容易帮助你.