我正在尝试用汇编语言写控制台。我最终使用了Windows API WriteFile函数。它工作得很好,但我遇到了一个奇怪的怪癖。如果我没有将rbx寄存器设置为[rsp],WriteFile不会返回并给出错误代码0xC0000005,这是一个访问冲突错误。它仍然正确地写入控制台,我觉得很奇怪。这不是一个问题,我可以包括一行,没有问题。但这让我很困扰,因为我不明白为什么会有这种行为。
如果有帮助的话,我使用NASM和GCC来编译我的程序。
以下是上下文的完整代码:
bits 64
default rel
extern GetStdHandle
extern WriteFile
extern ExitProcess
section .data
buffer db 0
section .text
print:
push rbp
mov rbp, rsp
add rsp, 8
mov rcx, -11
call GetStdHandle
mov rcx, rax
mov rax, 0x61616161
mov [buffer], rax
mov rdx, buffer
mov r8, 4
mov rbx, [rsp]
call WriteFile
mov rsp, rbp
pop rbp
ret
global main
main:
call print
mov rcx, 0
call ExitProcess
我尝试移动函数的内容来替换call print
,在这种情况下,即使没有mov rbx, [rsp]
也可以工作。我还尝试将rbx寄存器设置为其他值,但[rsp]似乎是唯一有效的。
1条答案
按热度按时间ki0zmccv1#
Windows调用约定要求调用方在返回地址上方的堆栈上提供32字节的可用空间,以供调用的函数使用。由于未提供此空间,因此WriteFile函数将覆盖调用方堆栈的部分。特别是,它使用rbx中的值来替换返回地址。使用返回地址加载rbx可以掩盖这个错误。
要修复它,请将
add rsp, 8
更改为sub rsp, 32
。(当然,删除更改rbx的指令。函数不能改变rbx而不保留其值。)