调用函数后,我应该弹出NASM函数自变量吗? [英] NASM should I pop function argument after calling a function?

查看:55
本文介绍了调用函数后,我应该弹出NASM函数自变量吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个像这样的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].

(如何从GCC/clang程序集输出中消除噪音"?)

(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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆