gpt4 book ai didi

linux - 主要和堆栈对齐

转载 作者:太空狗 更新时间:2023-10-29 11:29:17 25 4
gpt4 key购买 nike

我有一个打印文本和 float 的函数。这是一个不使用 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 来执行此操作。

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 之前从堆栈指针中减去八个字节,然后在堆栈指针中添加八个字节,否则会出现段错误。

查看堆栈指针,我发现在不使用 main 的情况下,它是 16 字节对齐的,但使用 main 时,它只是八字节对齐的。必须减去和添加 8 个字节的事实表明它始终是 8 字节对齐的,而不是 16 字节对齐的(除非我误解了什么)。为什么是这样?我认为对于 x86_64 代码,我们可以假设堆栈是 16 字节对齐的(至少对于我认为包括 main 的标准库函数调用)。

最佳答案

根据 ABI,堆栈指针 + 8 应在进入函数时保持 16 字节对齐。您必须减去 8 的原因是 call 本身将 8 个字节的返回地址放在堆栈上,从而违反了此约束。基本上你必须确保总堆栈指针移动是 16 的倍数,包括返回地址。因此栈指针需要移动16+8的倍数,为返回地址留出空间。

至于_start,我认为您也不能指望它在没有手动对齐的情况下工作。碰巧的是,在您的情况下,由于堆栈中已经存在的东西,它可以正常工作。

关于linux - 主要和堆栈对齐,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26866723/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com