You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apple Silicon(aarch64 macOS)汇编创建Socket时Bus error问题排查

问题分析与修复

核心错误原因:未对齐访问+存储大小不匹配

Bus error: 10 在Apple Silicon的ARM64架构下,最常见的触发原因是64位数据访问未按8字节对齐,或者访问的内存区域大小不足以容纳要存储的数据。你的代码里同时存在这两个问题:

  1. SOCK_ID存储容量不足:
    Socket返回的文件描述符(x0寄存器)是64位整数,但你用.byte 0只分配了1字节存储空间,执行STR x0, [x3]时会尝试写入8字节,直接越界访问内存触发错误。

  2. 地址未对齐:
    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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 12:35:15