在无库依赖的macOS上编译汇编程序遇错,求解决方案
macOS下纯汇编程序编译运行问题解决
问题背景
我在documents/assembly目录下的文件结构如下:
test.s(来自Linux教程,使用Linux系统调用号)
.global _start .text _start: mov $60, %rax # exit mov $0, %rdi # return code 0 syscall
compile.bash
as -o test.o test.s && ld -e _start -o test.s test.o && chmod 777 test.o && (./test ; echo $?)
运行compile.bash时出现错误:
ld: dynamic executables or dylibs must link with libSystem.dylib for architecture x86_64
尝试运行test.o时提示:
bash: ./test.o: cannot execute binary file
系统为macOS Monterey 12.5.1(21G83),使用GNU汇编器(as)而非教程中的gcc,修改编译命令后出现大量错误,预期运行后输出0但未实现。
编者注:x86-64 macOS与x86-64 Linux的系统调用号不同,即使编译成功运行也可能出现段错误或总线错误,这是另一个问题。建议后续读者选择匹配自身OS、CPU架构及模式(32/64位)的教程。
解决步骤
1. 修正编译命令的低级错误
你的compile.bash里把ld的输出文件名写错了——写成了test.s(和源文件重名),应该改成test,否则后续运行./test会找不到正确的可执行文件。
2. 解决macOS链接依赖问题
macOS的ld要求动态可执行文件必须链接libSystem.dylib,直接裸链接会报错,有两种解决方式:
方式一:用gcc替代ld完成链接(推荐)
GCC会自动处理macOS的系统库依赖,加上-nostdlib参数可以避免链接不必要的标准库,刚好适配纯汇编系统调用的场景:
as -o test.o test.s && gcc -nostdlib -e _start -o test test.o && ./test ; echo $?
方式二:手动用ld链接系统库
如果坚持要用ld,需要显式指定链接libSystem.dylib并指定SDK路径:
as -o test.o test.s && ld -e _start -o test test.o -lSystem -syslibroot $(xcrun --show-sdk-path) && ./test ; echo $?
3. 修正系统调用号
Linux的exit系统调用号是60,但macOS x86_64下,系统调用号需要加上前缀0x2000000,exit的完整调用号是0x2000001。修改test.s:
.global _start .text _start: mov $0x2000001, %rax # macOS exit系统调用号 mov $0, %rdi # 返回码0 syscall
4. 关于test.o无法执行的说明
test.o是目标文件,不是可执行程序,必须经过链接步骤生成test后才能运行,直接执行test.o必然报错。
内容的提问来源于stack exchange,提问作者AdamGewely
相关产品推荐
相关产品推荐

