我正在尝试为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
,不存在吗?
请解释,并提供解决方法。我不介意在构建路径上进行脚本化程序集修复的额外步骤。
为了重复步骤,汇编源如下:
.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人员修复了潜在的问题。现在这不应该出现,至少在这个特定的背景下不会出现。
答案 0 :(得分:1)
Lame解决方法:我扫描程序集,对于目标标签超过32000行的每个j
,我替换为以下内容:
la $t9, TargetLabel
jr $t9
至少汇编程序不再抱怨了。我仍然需要找到关于j
/ b
替换的引用。
编辑:la
是作为宏实现的。汇编程序在PIC模式下用以下内容替换它:
lw $t9, CurrentFunctionsBase($gp)
addiu $t9, $t9, OffsetWithinFunction
如果偏移很大,可能不止于此。所以它是PIC友好的。