主栈对齐 [英] main and stack alignment

查看:85
本文介绍了主栈对齐的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个打印文本和浮点数的功能.这是一个不使用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屋!

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