我对分支指令如何转换为机器代码感到困惑。我在我的书中读到,如果相等指令是分支指令,那么分支的格式如下:
操作码reg1 reg2地址+偏移量 6 5 5 16
在我的教科书中,有一个问题,我被显示一个程序,我被告知加载在0x4321ABC8,看起来像这样:
L1: sw $t0,3000($t1)
addi $s1,$t1,-6
beq $t0,$t1,L1
如您所见,第3行代码是相同的分支。
我正在尝试将此程序转换为二进制(或十六进制)。 在分支上,如果是相同的指令,我不明白究竟是什么,我应该进入地址+偏移字段。
首先我认为答案是......
基地址(0x4321ABC8),
加上程序计数器所在基数指令数的4倍(4 * 2 = 8),
然后减去四个偏移量,这将是原始基地址0x4321ABC8。
这个问题是0x4321ABC8是一个太大而不适合指令的16位偏移空间的数字。
那么我认为答案只是包括偏移量(这将是-8),但如果是这种情况,我不知道为什么书中的问题会费心去告诉我程序加载到0x4321ABC8。
非常感谢任何帮助!
答案 0 :(得分:3)
实际上,偏移量被编码为字数(或指令,如果您愿意),因此您不需要乘以字大小(4个字节)。此外,此偏移量相对于已更新的PC
,即以下指令的地址。因此,您的偏移量为-3
。
但这不是整个故事。 MIPS 确实有分支延迟槽,但它们通常对程序员隐藏。如果可以在不改变代码含义的情况下执行此操作,汇编程序可能会尝试填充这些内容。如果将示例提供给实际汇编程序(在本例中为gas
),它会将addi $s1,$t1,-6
移动到分支的延迟槽中,因为该条目的结果未在条件中使用:
00000000 <L1>:
0: ad280bb8 sw t0,3000(t1)
4: 1109fffe beq t0,t1,0 <L1>
8: 2131fffa addi s1,t1,-6
在此交换顺序中,编码的偏移量为-2
,您也可以从fffe
值中看到。
PS:如果你正在使用SPIM
,请注意它已知道偏移编码的一个一个问题。也就是说,它使用当前指令的地址而不是下一个指令的地址。