OS X - x64:堆栈不是 16 字节对齐错误

齐天大*_*天大圣 5 macos assembly x86-64

我知道 OS X 是 16 字节堆栈对齐,但我真的不明白为什么它会在这里导致错误。

我在这里所做的只是将一个对象大小(即 24)传递给 %rdi,然后调用 malloc。这个错误是否意味着我必须要求 32 个字节?

错误信息是:

libdyld.dylib`stack_not_16_byte_aligned_error: -> 0x7fffc12da2fa <+0>: movdqa %xmm0, (%rsp) 0x7fffc12da2ff <+5>: int3

libdyld.dylib`_dyld_func_lookup: 0x7fffc12da300 <+0>: pushq %rbp 0x7fffc12da301 <+1>: movq %rsp, %rbp

这是代码:

Object_copy:
    pushq %rbp
    movq %rbp, %rsp

    subq $8, %rsp
    movq %rdi, 8(%rsp)          # save self address
    movq obj_size(%rdi), %rax   # get object size
    imul $8, %rax          
    movq %rax, %rdi 
    callq _malloc             <------------------- error in this call

    # rsi old object address
    # rax new object address
    # rdi object size, mutiple of 8

    # rcx temp reg

    # copy object tag
    movq 0(%rsi), %rcx
    movq %rcx, 0(%rax)

    # set rdx to counter, starting from 8
    movq $8, %rdx

    # add 8 to object size, since we are starting from 8
    addq $8, %rdi

    start_loop:
        cmpq %rdx, %rdi
        jle end_loop

        movq (%rdx, %rsi, 1), %rcx
        movq %rcx, (%rdx, %rax, 1)

        addq $8, %rdx
        jmp start_loop

    end_loop:
        leave 
        ret



Main_protoObj:
    .quad    5                          ; object tag
    .quad    3                          ; object size
    .quad    Main_dispatch_table        ; dispatch table

_main:
    leaq Main_protoObj(%rip), %rdi
    callq Object_copy                # copy main proto object
    subq $8, %rsp                    # save the main object on the stack
    movq %rax, 8(%rsp)
    movq %rax, %rdi                 # set rdi point to SELF
    callq Main_init
    callq Main_main

    addq $8, %rsp                    # restore stack

    leaq _term_msg(%rip), %rax
    callq _print_string
Run Code Online (Sandbox Code Playgroud)

Nic*_*ber 4

就像你说的,MacOS X 有 16 字节堆栈对齐,这意味着机器期望堆栈上的每个变量从当前堆栈指针的 16 倍数的字节开始。

当堆栈未对齐时,这意味着我们开始尝试从 16 字节窗口的中间读取变量,并且通常会出现分段错误。

在代码中调用例程之前,您需要确保堆栈正确对齐;在这种情况下,意味着基址指针寄存器可以被 16 整除。

subq $8, %rsp               # stack is misaligned by 8 bytes
movq %rdi, 8(%rsp)          #
movq obj_size(%rdi), %rax   #
imul $8, %rax               #
movq %rax, %rdi             #
callq _malloc               # stack is still misaligned when this is called
Run Code Online (Sandbox Code Playgroud)

要解决此问题,您可以subq使用%rsp16 之类的值而不是 8。

subq $16, %rsp               # stack is still aligned
movq %rdi, 16(%rsp)          #
...                          #
callq _malloc                # stack is still aligned when this is called, good
Run Code Online (Sandbox Code Playgroud)