Bootloader栈操作问题求助:push/pop导致打印异常原因解析
为什么Bootloader里的push+call+pop栈操作会导致乱码?
核心原因:忽略了call指令的自动栈行为
x86实模式下,call指令执行时会自动把当前指令的下一条指令地址(返回地址)压入栈,再跳转到目标函数。你的代码没考虑这个机制,导致pop bx拿到的不是字符串地址,而是返回地址,最终打印指令字节出现乱码。
代码栈流程拆解
咱们一步步捋栈的变化:
- 栈初始化:
mov bp, 0x7c00、mov sp, bp,此时栈顶指针sp指向0x7c00(实模式栈向下生长,压栈时sp会递减)。 - 压入字符串地址:
push message把message的16位地址压栈,sp减2变为0x7BFE,栈顶现在是message的地址。 - 执行call指令:
call printstring触发CPU先把call指令的下一条指令地址(也就是printstring标签的起始地址)压入栈,sp再减2变为0x7BFC,栈顶换成了这个返回地址。
printstring函数的错误操作
进入printstring后,第一条指令pop bx弹出的是栈顶的返回地址,而非你预期的message地址:
- 后续用
mov al, [bx]取的是printstring函数第一条指令的机器码(pop bx对应字节0x5B),调用int 0x10打印自然是乱码。 - 最后执行
ret时,会弹出栈里剩下的message地址作为返回地址,CPU跳转到字符串内存执行,这属于非法指令操作,会引发后续错误。
正确的传参方式参考
如果要传递字符串地址,更稳妥的方式是直接用寄存器:
mov bx, message call printstring
如果一定要用栈传参,应该通过基址指针bp访问栈参数:
push message call printstring printstring: push bp mov bp, sp mov bx, [bp+2] ; bp+2的位置是push的message地址,bp位置是返回地址 ; 打印逻辑... pop bp ret
内容的提问来源于stack exchange,提问作者jonasbrocas
相关产品推荐
相关产品推荐

