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

使用GCC编译汇编代码遇_start重复定义及R_X86_64_32重定位错误

这两个错误其实都是GCC默认行为和你的汇编代码预期不匹配导致的,咱们一个个拆解解决:

1. 解决multiple definition of _start错误

问题根源

GCC编译时默认会链接C标准库的启动代码(比如Scrt1.o),这套启动代码已经定义了_start作为程序的入口点;而你的汇编代码里又自己定义了_start,直接导致符号重复定义冲突。

两种解决思路

思路一:让GCC跳过C运行时启动代码

如果你不需要C标准库的初始化逻辑(比如环境变量、标准IO的初始化),可以直接告诉GCC不要链接CRT(C运行时),这样就不会有自带的_start和你写的冲突了。编译命令改成:

gcc -nostdlib cpuid.s -o cpuid

思路二:把汇编入口改成main,适配GCC默认流程

如果希望保留C运行时的功能,只需要把汇编里的_start换成main,让GCC的启动代码自动调用你的main函数。比如:
原汇编开头:

.global _start
_start:
    # 你的代码逻辑

修改后:

.global main
main:
    # 你的代码逻辑
    # 注意:用main作为入口时,最后需要通过exit系统调用返回,保证程序正常退出
    mov $60, %rax   # x86_64下exit系统调用号为60
    xor %rdi, %rdi  # 返回值设为0
    syscall

然后用原本的命令编译即可:

gcc cpuid.s -o cpuid

2. 解决relocation R_X86_64_32 against .data错误

问题根源

x86_64系统下,GCC默认会生成位置无关可执行文件(PIE)——这种模式要求程序能加载到任意内存地址,而你汇编里用了32位绝对地址访问.data段,不符合PIE的位置无关要求,因此触发重定位错误。

两种解决思路

思路一:禁用PIE编译

直接告诉GCC生成传统的非位置无关可执行文件,这样32位绝对寻址就能正常使用了。结合之前的场景,命令如下:

  • 用-nostdlib的场景:
gcc -nostdlib -no-pie cpuid.s -o cpuid
  • 用main作为入口的场景:
gcc -no-pie cpuid.s -o cpuid

思路二:修改汇编代码,使用64位位置无关寻址

如果想保留PIE的安全特性,可以把汇编里访问.data的代码改成RIP相对寻址(x86_64下位置无关代码的标准写法)。比如:
原代码(32位绝对寻址,报错):

mov $my_data, %rax

修改后(RIP相对寻址):

lea my_data(%rip), %rax

如果是直接读取数据到寄存器:
原代码:

mov my_data, %eax

修改后:

mov my_data(%rip), %eax

修改完成后,用默认GCC命令编译就不会报错了:

gcc cpuid.s -o cpuid

总结选择

根据你的需求组合方案即可:

  • 完全自定义程序入口、不需要C运行时:gcc -nostdlib -no-pie cpuid.s -o cpuid
  • 适配C运行时、不想改汇编入口:修改汇编为main入口 + gcc -no-pie cpuid.s -o cpuid
  • 想保留PIE特性:修改汇编为RIP相对寻址 + gcc cpuid.s -o cpuid

内容的提问来源于stack exchange,提问作者Miracle Huang

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 12:26:48