NASM 我应该在调用函数后弹出函数参数吗?

ziy*_*uxe 4 assembly callstack x86-64 nasm calling-convention

假设我有一个像这样的 nasm 函数:

inc:
    mov rax,[rsp + 8]
    add [rax],BYTE 1
    ret
Run Code Online (Sandbox Code Playgroud)

我这样调用这个函数:

push some_var
call inc
Run Code Online (Sandbox Code Playgroud)

我想通过堆栈将参数传递给函数,因此我压入some_var然后调用我的函数。在函数中,我的项目位于堆栈中的第二个,因此我将其视为:mov rax,[rsp+8]

我的问题是:调用函数后我应该以某种方式从堆栈中弹出我的参数吗?如果是这样,我可以以某种方式从堆栈中删除它,我的意思是弹出它,但不注册?(因为我不再需要这个论点了。)

更新:我发现我可以简单地add rsp,8从堆栈中删除项目。但这是好的做法吗?调用函数后从堆栈中删除参数?

Pet*_*des 5

最佳实践是在寄存器中传递参数,就像编译器使用的标准 x86-64 调用约定一样。例如,x86-64 System V 在寄存器中传递前 6 个整数/指针参数,因此您的函数将是
add byte [rdi], 1/ ret,并且不需要任何清理。
调用者只需要mov edi, some_varor lea rdi, [rel some_var]

(用户空间函数调用的基础知识记录在 i386 和 x86-64 上 UNIX & Linux 系统调用的调用约定是什么中,即使标题提到了系统调用。完整详细信息请参见https://github.com/hjl-tools/ x86-psABI/wiki/X86-psABI。实际查看编译器对简单 C 函数执行的操作也很方便:请参阅如何从 GCC/clang 程序集输出中删除“噪音”?

如果您确实需要传递堆栈参数,则将其弹出到虚拟寄存器中pop rcx实际上比有效add rsp, 8,原因与编译器有时使用虚拟寄存器push保留一个 qword 堆栈槽/将堆栈重新对齐 16 的原因类似:为什么该函数是否将 RAX 压入堆栈作为第一个操作? 但是,如果有超过 1 个堆栈参数供调用者清理,请使用
add rsp, 8 * nwheren是堆栈槽数。

也可以让被调用者使用 来清理堆栈ret 8。但这就失去了让调用者保留分配的堆栈空间并mov在其中进行存储的机会,例如为另一个call.


归档时间:

查看次数:

1212 次

最近记录:

5 年,11 月 前