我正在尝试为Android/MIPSEL32构建一个程序集源文件。这是一个奇怪的Pascal编译器问题的测试用例;但是这个错误可能是在汇编程序中。
MIPS汇编程序如何在PIC模式下实现j
命令?我有一个j
-to-label语句,其中标签距离当前指令184200字节;在PIC模式下组装时,组装程序出错:
a.s:67: Error: Branch out of range
我可靠的MIPS手册说j
采用绝对偏移,应用于256-MB块内。整个代码块的大小远小于256MB。我看不出这个j
有什么问题。当不是为PIC编译时,它会按预期工作。为什么要谈论分支?分支和跳转在MIPS上是明显不同的。
在这种情况下,PC相对偏移量将是18比特长。忍不住注意到它刚刚超过b
的限制。汇编程序会在PIC模式下悄悄地将j
转换为b
吗?汇编程序级命令被实现为与底层体系结构命令同名的宏,这并非闻所未闻。但是函数序言中有一个set .nomacro
,不是吗?
请解释一下,也许可以提供一个变通办法。我不介意在构建路径上增加一个脚本程序集修复步骤。
这里,这里,这里也讨论了类似的问题。
为了重新编程步骤,装配源如下所示:
.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
汇编程序调用命令为:
mipsel-linux-android-as.exe -mabi=32 -march=mips32 -W -EL -KPIC -o a.o a.s
编辑:自由Pascal的人已经解决了根本问题。现在不应该出现这种情况,至少在这种特殊情况下不会出现。
EDIT:Free Pascal团队已经解决了这个问题,我要感谢他们。对于这种特殊情况,下面的解决方法不再是必要的,但其他受影响的人可能会感兴趣。
Lame解决方法:我扫描组件,对于目标标签超过32000行的每个j
,我用以下内容替换:
la $t9, TargetLabel
jr $t9
至少装配工不再抱怨了。关于CCD_ 10/CCD_。
EDIT:la
实现为宏。在PIC模式下,汇编程序将其替换为以下内容:
lw $t9, CurrentFunctionsBase($gp)
addiu $t9, $t9, OffsetWithinFunction
如果偏移量很大,可能会更多。所以它对PIC很友好。