在Apply M1的Aarch64汇编上,当将
EXC_BAD_ACCESS
与LDP
32位寄存器一起使用时,我收到w
错误。当我使用 x
64 位寄存器时,不会发生同样的问题。
使用
x
的示例效果很好:
.global _start
_start:
mov x0, #1 // arg1
mov x1, #2 // arg2
stp x0, x1, [sp, #-16]! // push these values to the stack before we branch to another location.
bl add_nums
mov x2, x0 // save x0 to w2, so we don't lose once we restore the original x0 from stack
ldp x0, x1, [sp], #16 // pop off x0, x1 with the values they were before going into add_numbs
// Exit program
mov x0, 0 // 0 status code
mov x16, 1
svc 0
add_nums:
// stores the result back to x0, that is why we need to store the original
// x0 on _start into the stack, so we could restore it later.
add x0, x0, x1
ret
有问题的代码。与上一个相同,我只是使用
w
而不是 x
寄存器更新了所有内容,并且堆栈点中修改的范围也是大小的一半:
_start:
mov w0, #1 // arg1
mov w2, #2 // arg2
stp w0, w2, [sp, #-8]! // push these values to the stack before we branch to another location.
bl add_nums
mov w2, w0 // save w0 to w2, so we don't lose once we restore the original w0 from stack
ldp w0, w2, [sp], #8 // pop off w0, w2 with the values they were before going into add_numbs
// Exit program
mov x0, 0 // 0 status code
mov x16, 1
svc 0
add_nums:
// stores the result back to w0, that is why we need to store the original
// w0 on _start into the stack, so we could restore it later.
add w0, w0, w2
ret
完整的错误是:
线程#1,队列='com.apple.main-thread',停止原因= EXC_BAD_ACCESS(代码= 259,地址= 0x16fdfe948)
显然A64应该支持
LDP
和w
寄存器https://developer.arm.com/documentation/dui0801/l/A64-Data-Transfer-Instructions/LDP--A64-?lang=en。
感谢 Jester 和 Frank 的评论,现在它变得有意义了。
对于 AArch64,每当使用 sp 访问内存时,sp 都必须是 16 字节对齐。这是由 AArch64 硬件强制执行的 - 参考。
这意味着对于 AArch64,即使存储的数据小于该值,堆栈点也必须始终是 16 字节的倍数。否则就会出现那种错误
EXC_BAD_ACCESS
。