Apple Silicon(aarch64 macOS)汇编创建Socket时Bus error问题排查
问题分析与修复
核心错误原因:未对齐访问+存储大小不匹配
Bus error: 10 在Apple Silicon的ARM64架构下,最常见的触发原因是64位数据访问未按8字节对齐,或者访问的内存区域大小不足以容纳要存储的数据。你的代码里同时存在这两个问题:
SOCK_ID存储容量不足:
Socket返回的文件描述符(x0寄存器)是64位整数,但你用.byte 0只分配了1字节存储空间,执行STR x0, [x3]时会尝试写入8字节,直接越界访问内存触发错误。地址未对齐:
ARM64要求64位数据的存储/加载地址必须是8字节对齐。你把SOCK_ID放在.text段之前且未设置对齐属性,其地址大概率不满足8字节对齐要求,进一步触发对齐错误。
修复步骤
1. 修正SOCK_ID的定义与存储
将SOCK_ID改为64位存储,并放到数据段(.data),同时确保8字节对齐:
.data .align 8 SOCK_ID: .quad 0 // 64位整数存储,匹配x0的64位数据宽度
2. 修正macOS ARM64系统调用号
macOS的ARM64系统调用号需要加上0x2000000前缀,你当前使用的是Linux的系统调用号,会导致调用失败:
.equ SYS_write, 0x2000004 // macOS ARM64 write系统调用号 .equ SYS_exit, 0x2000001 // macOS ARM64 exit系统调用号 .equ SYS_socket, 0x20000C4 // macOS ARM64 socket系统调用号
3. 修正_exit函数的系统调用指令
_exit函数中SVC SYS_exit的写法错误,macOS ARM64下SVC固定传#0,系统调用号放在x16寄存器中:
_exit: MOV x0, #0x00 // 返回码0 MOV x16, SYS_exit // 正确的exit系统调用号 SVC #0 // 触发系统调用 RET
修复后的完整汇编代码
.equ SYS_write, 0x2000004 .equ SYS_exit, 0x2000001 .equ SYS_socket, 0x20000C4 .data .align 8 SOCK_ID: .quad 0 .text .global _main .align 8 // 确保入口地址对齐 _main: // write(1, msg, msg_len); MOV x0, #1 // 1 = 标准输出 ADR x1, msg // 字符串地址 MOV x2, msg_len // 字符串长度 BL write // 调用write函数 // socket(int domain, int type, int protocol); BL socket // 调用socket函数 ADR x3, SOCK_ID STR x0, [x3] // 安全存储64位socket fd BL _exit // 退出程序 socket: MOV x0, PF_INET6 MOV x1, SOCK_STREAM MOV x2, protocol MOV x16, SYS_socket // macOS ARM64 socket系统调用号 SVC #0 // 调用内核创建socket RET write: MOV x16, SYS_write // macOS ARM64 write系统调用号 SVC #0 // 调用内核输出字符串 RET _exit: MOV x0, #0x00 // 返回码0 MOV x16, SYS_exit // 正确的exit系统调用号 SVC #0 // 触发系统调用 RET // Misc Variables msg: .asciz "Starting Program!\n" msg_len = (. - msg) // Socket Variables PF_INET6 = 30 SOCK_STREAM = 1 protocol = 1
验证修复
重新编译运行:
make clean all run
程序会正常输出Starting Program!,socket文件描述符会被正确存储到SOCK_ID中,不再出现Bus error。
内容的提问来源于stack exchange,提问作者Saurav Maheshkar
相关产品推荐
相关产品推荐

