2

我有一个家庭作业问题。

我有一个BNE指令0x88888888,我需要告诉什么是合法的跳转范围。

我的理论是偏移量告诉我我可以去:

  • 从 0x8888888 - 4 * 2 15
  • 至 0x88888888 + 4 * (2 15 -1)

我真的不明白为什么以及如何工作,有人可以解释一下吗?

4

2 回答 2

2

查找显示指令编码的指令参考,例如http://en.wikipedia.org/wiki/MIPS_architecture

000100ss sssttttt CCCCCCCC CCCCCCCC

s 和 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,因此要向后退三并到达 0x2030,您需要位于 0x203C,比编码指令提前一个。0xFFFB 4+1 = 5,返回 5 条指令,这意味着你从 0x2044 开始,分支后的指令用 0xFFFB 编码。

其他指令集就没有那么简单了。Arm 相当简单,无论是 arm 还是 thumb 模式,您都假设从包含指令开头的地址开始有两条指令,因此在 thumb 模式下 4 个字节,arm 模式下 8 个字节。即使是主要是 32 位指令的 thumb2,从程序员的角度来看,程序计数器也提前 2 条指令。

可变字长指令集,不像 arm、mips 等那样有规律。尽管实际地址被预取,但硬件使用固定规则,就像它使用 thumb2 一样。或者您必须从指令的大小中知道程序计数器的位置并使用该引用。请注意,当您执行时,程序计数器可能在这些处理器上的第一次切割正好在前面的一两条指令处,但是埋在其中的许多(arm,mips)中的流水线预取地址可能是规则的,但更远,或者当您使用分支预测进行超标量,提取可以在任何地方,甚至可以触及硬件中的寄存器(良好的硬件设计不会在简单的读取时修改任何内容,只会写入,您不会读取值并自动递增硬件指针,例如,

于 2012-05-20T22:56:50.967 回答
0

这个 SPIM 参考说:

分支指令使用带符号的 16 位偏移字段;因此它们可以向前跳转 2 15 -1 条指令(不是字节)或向后跳转 2 15条指令。

由于指令似乎总是 4 个字节宽,因此您的推理似乎是正确的,但您已经交换了符号。

最大向后分支(向低地址)是 2 15 -1 指令,即 32767 条指令或 131068 字节,因此您可以达到0x88888888 - 131068 = 8886888c.

同样,最大前向分支会将您带到0x88888888 + 131072 = 0x888a8888.

于 2012-05-20T12:38:11.587 回答