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

nasm编译32位汇编链接报R_386_16重定位截断错误排查

错误原因

你遇到的relocation truncated to fit: R_386_16 against '.bss'是32位x86汇编开发中的典型重定位错误,核心触发原因有两个:

  1. 在32位保护模式下,程序各段(包括.bss段)的内存地址是32位宽,你在传参时错误地将.bss段中r变量的32位内存地址当作16位值压栈,链接阶段无法将超出16位表示范围(0~65535)的32位地址截断为16位,直接抛出重定位错误。
  2. 代码中混用16位、32位压栈操作,不仅导致栈不对齐,还使得Fun.asm中定义的栈帧偏移全部计算错误,即使绕过链接错误,程序运行时也会出现内存访问越界、计算结果错误的问题。
修复步骤
  • 修正App.asm中的传参逻辑,统一压入32位值,避免16位地址重定位,同时修正printw的参数(原代码传的是r的地址,不是r存储的值):
    把原_start段的代码替换为以下内容:
    _start:
        push    V               ; 压入数组V的32位首地址,占4字节
        push    dword n         ; 压入数组长度n(编译期常量),占4字节
        movsx   edx, word [d]   ; 将16位变量d符号扩展为32位,避免越界读
        push    edx             ; 压入d的值,占4字节
        push    r               ; 压入结果变量r的32位地址,占4字节
        call    fun
        add     esp, 16         ; 手动平衡栈,清理4个共16字节的参数
        printw  word [r]        ; 打印r变量中存储的16位计算结果
        exit    0
    
  • 修正Fun.asm中的栈帧偏移定义,匹配新的32位传参栈布局:
    把Fun.asm开头的常量偏移替换为以下内容:
    section .data
        VV  equ 20  ; 数组V首地址在栈中的ebp偏移
        nn  equ 16  ; 数组长度n在栈中的ebp偏移
        dv  equ 12  ; 变量d的值在栈中的ebp偏移
        rr  equ 8   ; 结果变量r的地址在栈中的ebp偏移
    
  • 修正Fun.asm的返回指令,避免重复平衡栈,同时给内存操作加上宽度修饰避免汇编器歧义:
    1. 把函数末尾的ret 14改为ret(栈已经在调用方通过add esp,16平衡,不需要ret自动清理参数)
    2. 把两处写结果的操作加上word宽度修饰:
      • 把mov [ebp+rr], dx改为mov word [ebp+rr], dx
      • 把sub [ebp+rr], dx改为sub word [ebp+rr], dx
  • 重新执行编译链接命令即可正常生成可执行文件:
    nasm -f elf32 App.asm
    ld -m elf_i386 App.o /usr/local/bin/utils.o -o App
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 17:21:22