我正在为 Pentium 编写 64 位汇编代码。我正在使用 Microsoft Visual C/C++ 和 MASM。在汇编代码中,我编写了以下代码片段来调用
printf
:
push rcx
push rdx
push rdi
push rsi
lea rcx,string1
call printf
pop rsi
pop rdi
pop rdx
pop rcx
其中 string1 定义为:
string1 db "start of func", 10, 0
。
我预计前四条指令会在堆栈上保存四个寄存器。也就是说,保存的寄存器的值将由四个
pop
指令恢复。然而,寄存器值没有被正确恢复。我找到了这个视频:
该视频表示,在调用
printf
之前,您需要在堆栈上为这些值分配 32 个字节。因此,我写了这段代码:
push rcx
push rdx
push rdi
push rsi
sub rsp,20
lea rcx,string1
call printf
add rsp,20h
pop rsi
pop rdi
pop rdx
pop rcx
这段代码有效并且对我来说有一定意义。当我查看 C 编译器生成的代码时,它没有在堆栈上分配任何额外的空间并且它可以工作。因此,我不明白为什么需要在堆栈上分配额外的空间。请告诉我我缺少什么。
从您在
rcx
中传递值的事实来看,您似乎正在使用 Windows 调用约定,而不是除 microsoft 之外的每个人都使用的“标准”调用约定。
对于 Windows x64 调用约定,当调用 varargs 函数(
printf
)时,您必须在返回地址上方的堆栈上分配 32 字节的“影子”空间。