Macos 带pop/push-in x86/OSX的SEGFULT

Macos 带pop/push-in x86/OSX的SEGFULT,macos,assembly,Macos,Assembly,我很难理解为什么这段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

我很难理解为什么这段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"

我观察到,如果
pop%rbx
行在
call\u printf
之前移动,则程序工作正常。但为什么它会以最初的形式失败呢?

这个问题的详细答案是:和。在MacOSX上编程程序集时,这基本上是一个难题

总结如下:

  • 此seg故障是由于堆栈未对准造成的
  • 这仅在使用System V调用约定(包括MacOSX,但不包括Linux)的操作系统上发生,该约定坚持在进行函数调用之前堆栈指针为16的倍数(例如to
    printf
一个简单的解决方案是在调用之前对齐堆栈指针(即,根据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"

你需要对齐堆栈…@macmake是正确的,我相信-我编译并运行了你的代码,崩溃日志甚至说这是堆栈未对齐(不是16字节对齐)。@PaulR-谢谢。有没有办法通过指令来实现这一点?或者我必须喷洒代码才能手动对齐?同一问题可能重复。。。在我刚刚提到的帖子上看到我的答案,了解如何做到这一点。