Z b*_*son 2 linux assembly gcc x86-64 nasm
我有一个打印文本和浮点数的功能.这是一个不使用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
Run Code Online (Sandbox Code Playgroud)
我像这样组装和链接
nasm -felf64 hello.asm
ld hello.o -dynamic-linker /lib64/ld-linux-x86-64.so.2 -lc -melf_x86_64
Run Code Online (Sandbox Code Playgroud)
这很好.但是,现在我想用这个来做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
Run Code Online (Sandbox Code Playgroud)
我像这样装配和链接
nasm -felf64 hello_main.asm
gcc hello_main.o
Run Code Online (Sandbox Code Playgroud)
这也运行良好.但是,我必须在调用之前从堆栈指针中减去8个字节printf
,然后在堆栈指针之后添加8个字节,否则会出现分段错误.
看看堆栈指针,我看到它没有使用main
它的16字节对齐,但main
它只有8字节对齐.必须减去并添加8个字节的事实表明,它始终是8字节对齐而且从不16字节对齐(除非我误解了某些内容).为什么是这样?我认为使用x86_64代码我们可以假设堆栈是16字节对齐的(至少对于我认为包括的标准库函数调用main
).
根据ABI,在进入函数时,堆栈指针+ 8应保持16字节对齐.你必须减去8的原因是它call
本身在堆栈上放置了8个字节的返回地址,从而违反了这个约束.基本上你必须确保总堆栈指针移动是16的倍数,包括返回地址.因此,堆栈指针需要移动16 + 8的倍数才能为返回地址留出空间.
至于_start
,我不认为你可以依赖它而不需要手动对齐.只是碰巧在你的情况下,由于堆栈上已经存在的东西,它才起作用.
归档时间: |
|
查看次数: |
1245 次 |
最近记录: |