调用函数后,我应该弹出NASM函数自变量吗? [英] NASM should I pop function argument after calling a function?
问题描述
假设我有一个像这样的nasm功能:
Let's say I have a nasm function like this:
inc:
mov rax,[rsp + 8]
add [rax],BYTE 1
ret
我这样调用此函数:
push some_var
call inc
我想通过堆栈将参数传递给函数,所以我按下 some_var
然后调用我的函数.在函数中,我的项目在堆栈上排在第二位,因此我将其视为: mov rax,[rsp + 8]
I want to pass an argument to the function through the stack, so I push some_var
and then call my function. In the function my item is second on the stack so I take it like: mov rax,[rsp+8]
我的问题是:调用函数后,我应该以某种方式从堆栈中弹出参数吗?如果是这样,我可以以某种方式将其从堆栈中删除,我的意思是弹出它,但不进行注册?(因为我不再需要该参数了.)
My question is: after calling function should I somehow pop my argument from the stack? If so, can I somehow delete it from the stack, I mean pop it, but not to register? (Because I don't need this argument anymore.)
更新:我发现我可以简单地 add rsp,8
,这就是我可以从堆栈中删除项目的方法.但这是好习惯吗?要在调用函数后从堆栈中删除参数?
UPDATE: I found that I can simply add rsp,8
and that's how I can remove item from stack. But is that good practice? To remove the argument from the stack after calling function?
推荐答案
最佳做法是在寄存器中传递args,例如编译器使用的标准x86-64调用约定.例如x86-64系统V在寄存器中传递了前6个整数/指针args,因此您的功能将是添加字节[rdi],1
/ ret
,并且不需要任何清理.
呼叫者只需要 mov edi,some_var
或 lea rdi,[rel some_var]
.
Best practice is to pass args in registers like the standard x86-64 calling conventions that compilers use. e.g. x86-64 System V passes the first 6 integer/pointer args in registers, so your function would be
add byte [rdi], 1
/ ret
, and not need any cleanup.
The caller would only need mov edi, some_var
or lea rdi, [rel some_var]
.
(Basics of user-space function calling documented in What are the calling conventions for UNIX & Linux system calls on i386 and x86-64 even though the title mentions system calls. Full details in https://github.com/hjl-tools/x86-psABI/wiki/X86-psABI. It's also handy to actually look at what compilers do for simple C functions: see How to remove "noise" from GCC/clang assembly output?)
如果 do 需要传递堆栈arg,则将其弹出到诸如 pop rcx
之类的虚拟寄存器中实际上比 add rsp,8
,原因与为什么编译器有时会使用虚拟 push
保留一个qword堆栈插槽/按16:重新对齐堆栈的原因类似:
If you do need to pass a stack arg, popping it into a dummy register like pop rcx
can actually be more efficient than add rsp, 8
, for similar reasons to why compilers sometimes use a dummy push
to reserve one qword stack slot / re-align the stack by 16: Why does this function push RAX to the stack as the first operation? But if you have more than 1 stack arg for the caller to clean up, use
add rsp, 8 * n
where n
is the number of stack slots.
还可以使用 ret 8
让被调用方清理堆栈.但这使您失去了让调用方离开分配的堆栈空间并进行 mov
存储到其中的机会,例如为另一个 call
做准备.
It's also possible to have the callee clean the stack by using ret 8
. But that defeats the chance for you to have the caller leave the stack space allocated and do mov
stores into it, e.g. in preparation for another call
.
这篇关于调用函数后,我应该弹出NASM函数自变量吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!