我很难理解为什么这个 x86 汇编代码在 OSX 上使用 gcc 4.2.1 (llvm) 编译得很好,但是在运行可执行文件时会出现分段错误:
.globl _main
_main:
push %rbp
mov %rsp, %rbp
mov $1, %rbx
push %rbx
lea L_.str0(%rip), %rdi
mov %rbx, %rsi
call _printf
pop %rbx
pop %rbp
ret
.section __TEXT,__cstring,cstring_literals
L_.str0:
.asciz "%d \000"
Run Code Online (Sandbox Code Playgroud)
我观察到,如果该pop %rbx
行在 之前移动call _printf
,则程序可以正常工作。但是为什么它会以原始形式失败呢?
这个问题的详细回答如下:How to print argv[0] in NASM? 以及Mac 上的 x86 程序集。在 MacOSX 上编程程序集时,它本质上是一个问题。
总结一下:
printf
)之前堆栈指针是 16 的倍数。一个简单的解决方案是在调用之前对齐堆栈指针(即,按照 Sys V 要求对齐到 16 字节的倍数),并在调用之后恢复它:
.globl _main
_main:
push %rbp
mov %rsp, %rbp
mov $1, %rbx
lea L_.str0(%rip), %rdi
mov %rbx, %rsi
push %rbx
mov %rsp, %rax ; Save copy of the stack pointer (SP)
and $-16, %rsp ; Align the SP to the nearest multiple of 16.
sub $8, %rsp ; Pad the SP by 8 bytes so that when we ...
push %rax ; push the saved SP (=8 bytes on a 64-bit OS),
; we remain aligned to 16 bytes (8+8 = 16).
call _printf
pop %rax ; retrieve the saved SP
mov %rax, %rsp ; restore SP using saved value.
pop %rbx
pop %rbp
ret
.section __TEXT,__cstring,cstring_literals
L_.str0:
.asciz "%d \000"
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
836 次 |
最近记录: |