我有一个家庭作业的问题。
我在BNE
处有一条0x88888888
指令,我需要说出合法的跳跃范围。
我的理论是偏移量告诉我可以去:
我真的不明白为什么以及如何运作,有人可以解释一下吗?
答案 0 :(得分:2)
查找显示指令编码的指令参考,例如http://en.wikipedia.org/wiki/MIPS_architecture
000100ss sssttttt CCCCCCCC CCCCCCCC
和t保持被比较的寄存器,5位,每个寄存器0 - 31。低16位是指令单位的偏移量。
从程序员的角度来看,(对于mips)假设程序计数器提前1个指令,4个字节。因此,对于地址0x88888888,使用地址0x88888888 + 4 = 0x8888888C进行计算。
指令编码使用二进制补码,因此最大正向分支是0x7FFF指令,其为0x7FFF<< 2 = 0x1FFFC字节。当符号扩展为0xFFFF8000指令时,最大反向分支为0x8000,字节为0xFFFF8000<< 2 = 0xFFFE000
0x8888888C + 0x0001FFC = 0x888A8888
0x8888888C + 0xFFFE000 = 0x88868888
程序计数器调整非常简单,可以从工作汇编程序生成的工作代码的反汇编中找出。 (加上指令参考至少足以看到你必须使用的位数)。
00002030 <back>:
2034:
2038: 1443fffd bne v0,v1,2030 <back>
203c: 00000000 nop
2040: 1443fffb bne v0,v1,2030 <back>
2044: 00000000 nop
2048: 1443fff9 bne v0,v1,2030 <back>
204c: 00000000 nop
2050: 14430003 bne v0,v1,2060 <fore>
2054: 00000000 nop
2058: 14430001 bne v0,v1,2060 <fore>
205c: 00000000 nop
00002060 <fore>:
0x1443FFFD和0x1443FFFB相隔8个字节,相隔两个指令。指令中的偏移之间的差异是2的计数,因此意味着编码是以指令/字为单位而不是字节或半字。前向引用更容易先做0x2060 - 0x2050是0x10字节,这是4条指令。偏移量为3条指令,0x2060减去3条指令是0x2054,在执行bne之后的下一条指令(很有意义,流水线或不是pc通常至少在下一条指令执行时,并且当你用pc执行数学时,pc已经完成了向前推进)。这可以通过其他三个分支进行验证。 0x2058表示如果不相等则分支一个指令头,这意味着pc为0x205C,一个提前。 0xFFFD,反转并加1 = 2 + 1 = 3所以要向后移3并到达0x2030,你需要在0x203C,比编码指令提前一个。 0xFFFB 4 + 1 = 5,返回5条指令,表示从0x2044开始,该分支用0xFFFB编码后的指令。
其他指令集并不那么简单。 Arm是相当简单的,无论是手臂还是拇指模式,你都假设两个指令位于包含指令开头的地址之前,因此在拇指模式下4个字节,arm模式为8个字节。甚至thumb2主要是32位指令,程序员从程序员的角度来看是2指令。
可变字长指令集,它不像arm,mips等那样规则。硬件使用固定规则,就像使用thumb2一样,尽管实际地址是预取的。或者您必须从程序计数器所在指令的大小知道并使用该引用。请注意,这些处理器的第一次切割可能是程序计数器在执行时前面有一两条指令,但是在其中许多(arm,mips)中埋没的流水线预取地址可能是常规的但更远,或者当你去超标量分支预测,提取可以在任何地方,甚至触摸硬件中的寄存器(良好的硬件设计不会修改任何简单的读取,只写,你不读取值和自动增加硬件指针,例如,至少对于pci(e)可以在许多处理器上使用的硬件。
答案 1 :(得分:0)
分支指令使用带符号的16位偏移字段;因此,它们可以向后跳过2个 15 -1指令(非字节)或2个 15 指令。
由于指令似乎总是4个字节宽,因此您的推理显示正确,但您已经交换了符号。
最大后向分支(朝向较低地址)是2 15 -1指令,即32767指令或131068字节,因此您可以到达0x88888888 - 131068 = 8886888c
。
同样,最大前向分支会将您带到0x88888888 + 131072 = 0x888a8888
。