Android NDK编译ARM64汇编程序遇_start重复及main未定义错误求助
ARM64汇编Hello World编译错误分析与解决
错误原因拆解
1. 重复符号_start错误
使用clang编译时,默认会链接标准C库的启动代码,这套代码中已经定义了程序入口符号_start。你的汇编代码中又手动定义了_start,导致链接器检测到重复符号冲突。
2. 未定义符号main错误
当你把_start改为start1后,标准C库的启动代码仍然会尝试调用程序的main函数作为入口(这是C程序的默认约定),但你的汇编代码中并没有定义main,因此链接器报未定义符号错误。
两种解决方案
方案一:不依赖标准C库,自定义完整入口
直接编写包含系统调用的独立汇编程序,编译时禁用标准库链接:
- 修正后的汇编代码(
hello64bit.s):
.global _start _start: // 系统调用:write(1, msg, len) mov x0, #1 // 文件描述符:stdout ldr x1, =msg // 字符串地址 ldr x2, =len // 字符串长度 mov x8, #64 // Android ARM64 系统调用号:write=64 svc #0 // 触发系统调用 // 系统调用:exit(0) mov x0, #0 // 退出码:0 mov x8, #93 // Android ARM64 系统调用号:exit=93 svc #0 msg: .ascii "Hello, World!\n" len = . - msg // 计算字符串长度
- 正确编译命令:
./aarch64-linux-android27-clang -nostdlib -o hello64 hello64bit.s
-nostdlib:告诉编译器不链接标准C库及其启动代码,避免_start冲突-o hello64:生成可执行文件(你之前写的hello64.o是目标文件,不是可执行程序)
方案二:适配标准C库的入口约定
将汇编程序的入口改为main,符合C程序的默认入口规则,无需禁用标准库:
- 修正后的汇编代码(
hello64bit.s):
.global main main: // 系统调用:write(1, msg, len) mov x0, #1 ldr x1, =msg ldr x2, =len mov x8, #64 svc #0 mov x0, #0 // 返回0表示程序正常结束 ret // 返回到标准库启动代码,完成退出 msg: .ascii "Hello, World!\n" len = . - msg
- 编译命令:
./aarch64-linux-android27-clang -o hello64 hello64bit.s
此时clang会自动链接标准C库的启动代码,它会调用你定义的main函数,最终完成程序退出。
内容的提问来源于stack exchange,提问作者Thermal_insulator
相关产品推荐
相关产品推荐

