【问题标题】:calculating offset计算偏移量
【发布时间】:2012-05-20 10:06:43
【问题描述】:

我有一个作业问题。

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

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

  • 从 0x8888888 - 4 * 215
  • 到 0x88888888 + 4 * (215-1)

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

【问题讨论】:

  • 您忘记告诉我们您使用的是什么指令集。不同的 CPU 有不同的可用指令集。
  • 我们没有告诉任何关于它的事情,它可以连接到我们使用的程序吗? spim模拟器和modelsim?
  • 是的,SPIM 是 MIPS 指令集的模拟器。我不知道任何细节,但已将标签添加到您的问题中。希望其他人过来,知道细节。

标签: assembly mips spim


【解决方案1】:

查找显示指令编码的指令参考,例如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

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)中的流水线预取地址可能是规则的,但更远,或者当您使用分支预测进行超标量,提取可以在任何地方,甚至可以触及硬件中的寄存器(良好的硬件设计不会在简单的读取时修改任何内容,只会写入,您不会读取值并自动递增硬件指针,例如,至少用于可在许多处理器上使用的 pci(e) 硬件)。

【讨论】:

  • 感谢所有的解释,但仍有一些我不明白的地方,你为什么要在第 9 行进行 2 位偏移?
  • 左移 2 与乘以 4 相同。每条指令有 4 个字节,因此要将指令单位转换为字节单位,您将指令数乘以 4 以获得字节数。同样,除以四(算术右移)得到从字节到指令数。
  • 只看地址,一条指令在地址0x2000,下一条在地址0x2004,0x2008等等。每条指令 4 个字节。如果我有 60 英寸,那是多少英尺?除以 12, 5 英尺。如果我有 3 英尺,那是多少英寸?乘以 12, 36 英寸。在 32 位固定指令长度处理器上提前 5 条指令。 32 位,每字节 8 位是 32/8 = 4 字节。 5 条指令乘以 4 为 20 个字节。
  • 如果我想将 0.123 转换为百分比,我除以 100 右 PER CENT 表示每(除)分 (100) 除以 100,因此 0.123 是 12.3%。或将其视为移动 2,乘以数字系统中的基数平方是向左移动 2,将十进制数乘以 100,您向左移动 2 个位置 3 次 100 是 300,用零填充空白. 4000 除以 10 是右移 1 = 400。更改为基数 2,除以系统中的基数的 2 次方是右移 2。0b1000 / 四 = 0b10, 0b011 * 八 = 0b011000 一个移位三个的左边。
【解决方案2】:

This SPIM reference 说:

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

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

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

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

【讨论】:

    猜你喜欢
    • 2018-04-13
    • 1970-01-01
    • 2013-08-24
    • 2021-04-10
    • 2021-10-14
    • 2018-08-27
    • 2018-03-31
    • 2011-06-20
    • 1970-01-01
    相关资源
    最近更新 更多