MIPS汇编程序用PIC抱怨“分支超出范围”

时间:2013-12-06 18:48:52

标签: assembly android-ndk mips

我正在尝试为Android / MIPSEL32构建一个汇编源文件。这是weird Pascal compiler issue的测试用例;但是这个bug毕竟可能是汇编程序。

MIPS汇编程序如何在PIC​​模式下实现j命令?我有一个j - to-label语句,其中标签距离当前指令184200字节;在PIC模式下组装时,汇编器出错:

 a.s:67: Error: Branch out of range

我信赖的MIPS手册说j采用绝对偏移量,应用于256 MB的块中。整个代码块的大小远小于256 MB。我不明白这个j有什么问题。当编译PIC时,它按预期工作。为什么要谈论一个分支? MIPS上的分支和跳转明显不同。

在这种情况下,PC相对偏移量为18位。不禁注意到它刚刚高于b的限制。汇编程序会在PIC模式下悄悄地将j转换为b吗?将汇编程序级命令实现为与底层架构命令同名的宏并不是闻所未闻。但是在函数序言中有一个set .nomacro,不存在吗?

请解释,并提供解决方法。我不介意在构建路径上进行脚本化程序集修复的额外步骤。

讨论了类似的问题hereherehere

为了重复步骤,汇编源如下:

.section .text.n_main
.balign 4
.globl  PASCALMAIN
.type   PASCALMAIN,@function
PASCALMAIN:
.globl  main
.type   main,@function
main:
.ent main
.set    nomips16
.frame  $sp,112,$ra
.mask   0xC0010000,-40
.fmask  0x00000000,0
.set    noreorder
.cpload $t9
.set    nomacro
addiu   $sp,$sp,-112
sw  $ra,72($sp)
sw  $fp,68($sp)
addiu   $fp,$sp,112
.cprestore  104
sw  $s0,64($sp)
lw  $t9,%call16(FPC_INITIALIZEUNITS)($gp)
jalr    $t9
nop
lw  $gp,104($sp)
lw  $t9,%call16(fpc_get_input)($gp)
jalr    $t9
nop
lw  $gp,104($sp)
move    $s0,$v0
lw  $a1,%got(U_$P$A_$$_S)($gp)
addiu   $a1,$a1,%lo(U_$P$A_$$_S)
move    $a0,$s0
addiu   $a2,$zero,255
lw  $t9,%call16(fpc_read_text_shortstr)($gp)
jalr    $t9
nop
lw  $gp,104($sp)
lw  $t9,%call16(FPC_IOCHECK)($gp)
jalr    $t9
nop
lw  $gp,104($sp)
move    $a0,$s0
lw  $t9,%call16(fpc_readln_end)($gp)
jalr    $t9
nop
lw  $gp,104($sp)
lw  $t9,%call16(FPC_IOCHECK)($gp)
jalr    $t9
nop
lw  $gp,104($sp)
lw  $v0,%got(U_$P$A_$$_I)($gp)
sw  $zero,%lo(U_$P$A_$$_I)($v0)
lw  $v0,%got(U_$P$A_$$_S)($gp)
lbu $v0,%lo(U_$P$A_$$_S)($v0)
beq $v0,$zero,.Lj15
nop
# fixup_jmps, A_BA changed into A_J
j   .Lj16
nop
.Lj15:
##### Then there's the following fragment, repeated 9210 times:
lw  $v0,%got(U_$P$A_$$_I)($gp)
lw  $v1,%lo(U_$P$A_$$_I)($v0)
addiu   $v1,$v1,1
lw  $v0,%got(U_$P$A_$$_I)($gp)
sw  $v1,%lo(U_$P$A_$$_I)($v0)
##### End of repeating fragment
.Lj16:
lw  $t9,%call16(FPC_DO_EXIT)($gp)
jalr    $t9
nop
lw  $gp,104($sp)
lw  $s0,64($sp)
lw  $fp,68($sp)
lw  $ra,72($sp)
jr  $ra
addiu   $sp,$sp,112
.set    macro
.set    reorder
.end main

汇编程序invokation命令是:

mipsel-linux-android-as.exe -mabi=32 -march=mips32 -W -EL -KPIC -o a.o a.s
编辑:Free Pascal人员修复了潜在的问题。现在这不应该出现,至少在这个特定的背景下不会出现。

1 个答案:

答案 0 :(得分:1)

编辑:Free Pascal人已经解决了这个问题,谢谢他们。对于这种特殊情况,下面的解决方法不再是必要的,但可能对受影响的其他人感兴趣。


Lame解决方法:我扫描程序集,对于目标标签超过32000行的每个j,我替换为以下内容:

la $t9, TargetLabel
jr $t9

至少汇编程序不再抱怨了。我仍然需要找到关于j / b替换的引用。

编辑:la是作为宏实现的。汇编程序在PIC模式下用以下内容替换它:

lw $t9, CurrentFunctionsBase($gp)
addiu $t9, $t9, OffsetWithinFunction

如果偏移很大,可能不止于此。所以它是PIC友好的。