Should %rsp be aligned to 16-byte boundary before calling a function in NASM?

社会主义新天地 提交于 2021-02-16 20:20:22

问题


I saw the following rules from NASM's document:

The stack pointer %rsp must be aligned to a 16-byte boundary before making a call. Fine, but the process of making a call pushes the return address (8 bytes) on the stack, so when a function gets control, %rsp is not aligned. You have to make that extra space yourself, by pushing something or subtracting 8 from %rsp.

And I have a snippet of NASM assembly code as below:

The %rsp should be at the boundary of 8-bytes before I call the function "inc" in "_start" which violates the rules described in NASM's document. But actually, everything is going on well. So, how can I understand this?

I built this under Ubuntu 20.04 LTS (x86_64).

global _start

section .data
init:
    db 0x2

section .rodata
codes: 
    db '0123456789abcdef'

section .text
inc:
    mov rax, [rsp+8]  ; read param from the stack;
    add rax, 0x1
    ret

print:
    lea rsi, [codes + rax]
    mov rax, 1
    mov rdi, 1
    mov rdx, 1
    syscall
    ret

_start:
    ; enable AC check;
    pushf
    or dword [rsp], 1<<18
    popf

    mov rdi, [init]  ; move the first 8 bytes of init to %rdi;
    push rdi  ; %rsp -> 8 bytes;
    call inc
    pop r11  ; clean stack by the caller;
    call print

    mov rax, 60
    xor rdi, rdi
    syscall

回答1:


The ABI is a set of rules for how functions should behave to be interoperable with each other. Each of the rules on one side are paired with allowed assumptions on the other. In this case, the rule about stack alignment for the caller is an allowed assumption about stack alignment for the callee. Since your inc function doesn't depend on 16-byte stack alignment, it's fine to call that particular function with a stack that's only 8-byte aligned.

If you're wondering why it didn't break when you enabled AC, that's because you're only loading 8-byte values from the stack, and the stack is still 8-byte aligned. If you did sub rsp, 4 or something to break 8-byte alignment too, then you would get a bus error.

Where the ABI becomes important is when the situation isn't one function you wrote yourself in assembly calling another function you wrote yourself in assembly. A function in someone else's library (including the C standard library), or one that you compiled from C instead of writing in assembly, is within its rights to do movaps [rsp - 24], xmm0 or something, which would break if you didn't properly align the stack before calling it.

Side note: the ABI also says how you're supposed to pass parameters (the calling convention), but you're just kind of passing them wherever. Again, fine from your own assembly, but they'll definitely break if you try to call them from C.



来源:https://stackoverflow.com/questions/62714764/should-rsp-be-aligned-to-16-byte-boundary-before-calling-a-function-in-nasm

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