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

拆分SuperH汇编代码至多文件时遇分支/PC相对寻址错误求助

SuperH汇编分支位移溢出问题解决

问题根源

SuperH的bra/bsr属于12位PC相对短分支指令,仅能覆盖±4096字节的地址范围(指令4字节对齐,12位有符号位移×4)。当跨文件调用子程序时,汇编阶段无法确定目标符号的最终地址,无法保证其落在短分支范围内,因此直接触发“displacement overflows 12-bit field”错误;而单文件.include合并大代码后,部分子程序距离调用点超出短分支范围,就会出现“pcrel too far”错误。

具体修正方法

  1. 替换短分支为长分支指令
    跨文件或远距离调用时,直接使用长分支指令代替短分支:

    • 用jsr替代bsr:jsr是24位PC相对长调用指令,支持全地址空间范围的调用,无需担心位移溢出。
    • 用jmp替代bra:如果是无返回的跳转,jmp长跳转指令同样支持全地址范围。
  2. 正确使用寄存器间接分支
    若需通过寄存器加载地址调用,不要用bsrf(它仍是PC相对短分支),改用寄存器间接调用/跳转指令:

    ; 加载外部子程序地址到寄存器
    mov.l  #external_sub, r1
    ; 调用寄存器指向的子程序
    jsr    @r1
    ; 跳转(无返回)
    ; jmp    @r1
    

    注意:子程序文件中必须用.global external_sub声明符号为全局可见,main文件可通过.extern external_sub显式声明外部符号。

  3. 采用多文件汇编+链接的正确流程

    • 拆分每个子程序为独立文件,例如sub.s:
      .global my_sub
      my_sub:
          ; 子程序代码
          rts
          nop
      
    • 单独汇编每个文件为目标文件:
      sh-elf-as -o main.o main.s
      sh-elf-as -o sub.o sub.s
      
    • 链接所有目标文件生成可执行程序:
      sh-elf-ld -o my_program main.o sub.o
      

    链接器会自动处理地址分配,长分支指令可适配任意距离的调用。

错误点总结

  • 用bsr/bra调用外部子程序:汇编阶段无法确定目标地址范围,短分支指令直接报错,必须换长分支。
  • 误用bsrf:该指令为条件短分支,仍依赖PC相对位移,无法解决远距离调用问题,需改用寄存器间接的jsr @Rn/jmp @Rn。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 12:41:27