NASM should I pop function argument after calling a function?

女生的网名这么多〃 提交于 2021-02-05 06:51:29

问题


Let's say I have a nasm function like this:

inc:
    mov rax,[rsp + 8]
    add [rax],BYTE 1
    ret

And I am calling this function like this:

push some_var
call inc

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.)

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?


回答1:


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?)

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.

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.




回答2:


I listed some ways to remove things from the stack in this answer: Can I POP a value from the stack, but put it nowhere in NASM Assembly?, to summarise:

  • add rsp, x

  • lea rsp, [rsp + x]

  • mov rsp, rbp (also part of leave)

  • lea rsp, [rbp - x]

  • popping into otherwise unused registers

Other than that, whether you should remove parameters from the stack in the caller is determined by whether your calling convention mandates caller clean-up or the opposite, callee cleanup. Callee cleanup is done by specifying the number of bytes to remove from the stack as an immediate operand to the retn instruction. For example:

    ...
    ; caller code
    push rax
    push rdi
    call testfunction
    ...


    ; function code
testfunction:
    push rbp
    mov rbp, rsp
    mov rcx, qword [rbp + 16]
    ...
    mov rsp, rbp
    pop rbp
    retn 16


来源:https://stackoverflow.com/questions/60830765/nasm-should-i-pop-function-argument-after-calling-a-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!