Apple Silicon平台使用GCC链接汇编代码失败问题求助
问题原因与解决方案
一、问题根源
你用nasm -fmacho64生成的是x86_64架构的目标文件,但你的Apple Silicon是arm64架构,gcc默认以arm64模式编译链接,两者架构不匹配,所以链接时出现"building for macOS-arm64 but attempting to link with file built for unknown-x86_64"的错误;同时因为找不到arm64版本的_main符号,最终导致链接失败。
之前用ld能运行,是因为你调用的ld可能是Rosetta转译的x86_64版本,或是手动指定了x86_64的链接库,因此能兼容x86_64的目标文件。
二、解决方案
1. 适配arm64架构,用gcc链接无标准库的程序
你需要编写arm64架构的汇编代码,并用nasm生成对应架构的目标文件:
arm64版Hello World汇编代码(直接调用系统调用)
section .data message: db "Hello, world!", 10 section .text global _main _main: ; write系统调用:arm64 macOS中调用号为4 mov x0, 1 ; 文件描述符1=标准输出 adrp x1, message ; 加载message的高地址部分 add x1, x1, :lo12:message ; 拼接低12位地址,得到完整的message地址 mov x2, 14 ; 字符串长度 mov x16, 4 ; arm64 macOS write系统调用号 svc 0x80 ; 触发系统调用 ; exit系统调用:arm64 macOS中调用号为1 mov x0, 0 ; 退出码0 mov x16, 1 svc 0x80
编译链接命令
- 用nasm生成arm64目标文件:
nasm -fmacho-arm64 hello_arm64.asm -o hello_arm64.o - 用gcc链接:
gcc hello_arm64.o -o hello_arm64
运行./hello_arm64即可正常输出内容。
2. 调用C标准库puts的arm64汇编程序
arm64的函数调用约定是:前8个参数用x0-x7寄存器传递,返回值存在x0。以下是调用puts的示例代码:
section .data message: db "Hello, world!", 0 ; C标准库字符串需要以0结尾 section .text global _main extern _puts ; 声明外部函数puts _main: adrp x0, message add x0, x0, :lo12:message ; 将message地址放到x0(第一个参数) bl _puts ; 调用puts函数 ; 返回0给操作系统 mov x0, 0 ret
编译链接命令
- 编译:
nasm -fmacho-arm64 puts_arm64.asm -o puts_arm64.o - 用gcc链接(自动处理C标准库依赖):
gcc puts_arm64.o -o puts_arm64
运行后会输出"Hello, world!"。
额外说明
如果确实需要编译x86_64程序,可以在gcc命令中加上-arch x86_64,同时保持nasm的-fmacho64参数:
nasm -fmacho64 hello.asm -o hello_x86.o gcc -arch x86_64 hello_x86.o -o hello_x86
这种方式会通过Rosetta转译运行x86_64程序,但性能不如原生arm64高效。
内容的提问来源于stack exchange,提问作者casimir
相关产品推荐
相关产品推荐

