【发布时间】:2017-09-07 08:32:44
【问题描述】:
我知道 OS X 是 16 字节堆栈对齐,但我真的不明白为什么它会在这里导致错误。
我在这里所做的只是将一个对象大小(为 24)传递给 %rdi,然后调用 malloc。这个错误是否意味着我必须要求 32 个字节?
错误信息是:
libdyld.dylib`stack_not_16_byte_aligned_error: -> 0x7fffc12da2fa : movdqa %xmm0, (%rsp) 0x7fffc12da2ff : int3
libdyld.dylib`_dyld_func_lookup: 0x7fffc12da300 : pushq %rbp 0x7fffc12da301 : 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
【问题讨论】:
-
在 64 位代码 CALL 之前的点 RSP 必须能被 16 整除。在堆栈上并将控制传输到例程,堆栈变得错位 8 个字节(现在返回堆栈上的值)。
pushq %rbp在堆栈上放置了额外的 8 个字节,因此堆栈现在与 16 字节边界对齐。然后您执行subq $8, %rsp,这意味着 RSP 现在再次错位 8。然后你用未对齐的堆栈调用malloc。而不是subq $8, %rsp尝试subq $16, %rsp保持 16 字节对齐。 -
@MichaelPetch 嘿,迈克尔,非常感谢您的回答,它真的帮了我很大的忙。您是否介意以实际答案的形式发表您的评论,以便更明显地为其他遇到此问题的人解决此问题?如果您不想这样做,我可以这样做:)
-
如果你愿意,你可以拿走你发现的东西并自己回答你的问题。