主栈对齐 [英] main and stack alignment
问题描述
我有一个打印文本和浮点数的功能.这是一个不使用main的版本
I have a function which prints text and a floating point number. Here is a version which does not use main
extern printf
extern _exit
section .data
hello: db 'Hello world! %f',10,0
pi: dq 3.14159
section .text
global _start
_start:
xor eax, eax
lea rdi, [rel hello]
movsd xmm0, [rel pi]
mov eax, 1
call printf
mov rax, 0
jmp _exit
我这样组装并链接
nasm -felf64 hello.asm
ld hello.o -dynamic-linker /lib64/ld-linux-x86-64.so.2 -lc -melf_x86_64
运行正常.但是,现在我想使用main
来做到这一点.
This runs fine. However, now I want to do this using main
.
global main
extern printf
section .data
hello: db 'Hello world! %f',10,0
pi: dq 3.14159
section .text
main:
sub rsp, 8
xor eax, eax
lea rdi, [rel hello]
movsd xmm0, [rel pi]
mov eax, 1
call printf
mov rax, 0
add rsp, 8
ret
我这样组装和链接
nasm -felf64 hello_main.asm
gcc hello_main.o
这也很好.但是,在调用printf
之前,我必须从堆栈指针中减去8个字节,然后在出现分段错误之后,再向堆栈指针中添加8个字节.
This runs fine as well. However, I had to subtract eight bytes from the stack pointer before calling printf
and then add eight bytes to the stack pointer after otherwise I get a segmentation fault.
看看堆栈指针,我看到不使用main
时它是16字节对齐的,但是使用main
时它只是8字节对齐的.必须减去和增加八个字节的事实表明,它始终是8字节对齐的,而从来没有16字节对齐的(除非我误解了).为什么是这样?我以为x86_64代码可以假定堆栈是16字节对齐的(至少对于我认为包括main
的标准库函数调用而言).
Looking at the stack pointer I see that without using main
it's 16-byte aligned but with main
it's only eight byte aligned. The fact that eight bytes has to be subtracted and added says that it's always 8-byte aligned and never 16-byte aligned (unless I misunderstand something). Why is this? I thought with x86_64 code we could assume that the stack is 16-byte aligned (at least for standard library function calls which I would think includes main
).
推荐答案
根据ABI,堆栈指针+ 8在进入函数时应保持16字节对齐.您必须减去8的原因是call
本身在堆栈上放置了8个字节的返回地址,从而违反了此约束.基本上,您必须确保堆栈指针的总移动量是16的倍数,包括返回地址.因此,堆栈指针需要移动16 + 8的倍数,以便为返回地址留出空间.
According to the ABI, the stack pointer + 8 should be kept 16 byte aligned upon entry to functions. The reason you have to subtract 8 is that call
itself places 8 bytes of return address on the stack, thereby violating this constraint. Basically you have to make sure the total stack pointer movement is a multiple of 16, including the return address. Thus the stack pointer needs to be moved by multiple of 16 + 8 to leave room for the return address.
至于_start
,我认为您也可以依靠它而无需手动对齐.碰巧的是,由于堆栈中已经有东西,因此在您的情况下它可以正常工作.
As for _start
, I don't think you can rely on it working without manual alignment either. It just so happens that in your case it works due to the things already on the stack.
这篇关于主栈对齐的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!