如何计算跳转目标地址和分支目标地址?

发布于 2024-11-27 22:02:04 字数 73 浏览 4 评论 0原文

我是汇编语言新手。我正在阅读有关 MIPS 架构的内容,但我对跳转目标地址和分支目标地址指令以及如何计算它们中的每一个指令感到困惑。

I am new to Assembly language. I was reading about the MIPS architecture and I am stuck with the Jump Target Address and Branch Target Address instructions and how to calculate each of them.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

你丑哭了我 2024-12-04 22:02:04

在下面的图表和文本中,PC 是分支指令本身的地址。 PC+4 是分支指令本身的结束,也是下一条指令的开始(MIPS 中使用延迟槽的分支延迟槽)。

除了在绝对跳转图中,我们实际上取的是跳转后指令地址的高 4 位。仅在 256 MiB 区域的末尾有所不同。这些图在所谓的 PC 方面彼此不一致,或者可能是通过简化创建的,因为 PC+4 具有与 PC 相同的前 4 位。

1.分支地址计算

在MIPS中,分支指令只有16位偏移量来确定下一条指令。我们需要一个寄存器添加到这个 16 位值来确定下一条指令,这个寄存器实际上是由架构隐含的。它是 PC 寄存器,因为 PC 在取周期期间被更新(PC+4),因此它保存下一条指令的地址。

我们还将分支距离限制为 -2^15 到 +2^15 - 1 指令。然而,这不是真正的问题,因为无论如何大多数分支机构都是本地的。

一步一步来:

  • 16 位偏移值进行符号扩展以保留其值。
  • 将结果值乘以 4。其背后的原因是,如果我们要分支某个地址,并且 PC 已经是字对齐的,那么立即值也必须是字对齐的。然而,使立即字对齐是没有意义的,因为我们会通过强制低两位为 00 来浪费它们。
  • 现在我们有一个 32 位相对偏移量。将此值添加到 PC + 4,这就是您的分支机构地址。

分支地址计算


2.跳转地址计算

对于跳转指令,MIPS 只有 26 位来确定跳转位置。跳转是相对于 MIPS 中的 PC 而言的。与分支一样,立即跳转值需要字对齐;因此,我们需要将 26 位地址乘以 4。

再次一步一步:

  • 将 26 位值乘以 4。
  • 由于我们相对于 PC+4 值进行跳转,因此将 PC+4 值的前四位连接到跳转地址的左侧。
  • 结果地址是跳转值。

换句话说,将PC+4的低28位替换为所取指令的低26位左移2位。

在此处输入图像描述

跳转在包含分支延迟槽的区域内是绝对的,不一定是分支本身。 在上图中,PC 在跳转计算之前已经前进到分支延迟槽。(在经典 RISC 5 级流水线中,BD 在跳转解码的同一周期中获取,因此PC+4 下一个指令地址已经可用于跳转和分支,并且相对于跳转自己的地址进行计算将需要额外的工作来保存该地址。)

来源:比尔肯特大学 CS 224 课程幻灯片

In the diagrams and text below, PC is the address of the branch instruction itself. PC+4 is the end of the branch instruction itself, and the start of the next instruction (the branch delay slot in a MIPS that uses delay slots).

Except in the absolute jump diagram where we actually take the high 4 bits of the address of the instruction following the jump. That's only different at the end of a 256 MiB region. The diagrams are inconsistent with each other in what they call PC, or perhaps were created with the simplification that PC+4 has the same top 4 bits as PC.

1. Branch Address Calculation

In MIPS branch instruction has only 16 bits offset to determine next instruction. We need a register added to this 16 bit value to determine next instruction and this register is actually implied by architecture. It is PC register since PC gets updated (PC+4) during the fetch cycle so that it holds the address of the next instruction.

We also limit the branch distance to -2^15 to +2^15 - 1 instructions. However, this is not real issue since most branches are local anyway.

So step by step :

  • Sign extend the 16 bit offset value to preserve its value.
  • Multiply resulting value with 4. The reason behind this is that If we are going to branch some address, and PC is already word aligned, then the immediate value has to be word-aligned as well. However, it makes no sense to make the immediate word-aligned because we would be wasting low two bits by forcing them to be 00.
  • Now we have a 32 bit relative offset. Add this value to PC + 4 and that is your branch address.

Branch address calculation


2. Jump Address Calculation

For Jump instruction MIPS has only 26 bits to determine Jump location. Jumps are relative to PC in MIPS. Like branch, immediate jump value needs to be word-aligned; therefore, we need to multiply 26 bit address with four.

Again step by step:

  • Multiply 26 bit value with 4.
  • Since we are jumping relative to PC+4 value, concatenate first four bits of PC+4 value to left of our jump address.
  • Resulting address is the jump value.

In other words, replace the lower 28 bits of the PC + 4 with the lower 26 bits of the fetched instruction shifted left by 2 bits.

enter image description here

Jumps are absolute within the region containing the branch-delay slot, not necessarily the branch itself. In the diagram above, PC has already advanced to the branch delay slot before the jump calculation. (In a classic-RISC 5 stage pipeline, the BD was fetched in the same cycle the jump is decoded, so that PC+4 next instruction address is already available for jumps as well as branches, and calculating relative to the jump's own address would have required extra work to save that address.)

Source: Bilkent University CS 224 Course Slides

青衫负雪 2024-12-04 22:02:04

通常您不必担心计算它们,因为您的汇编器(或链接器)将进行正确的计算。假设您有一个小函数:


func:
  slti $t0, $a0, 2
  beq $t0, $zero, cont
  ori $v0, $zero, 1
  jr $ra
cont:
  ...
  jal func
  ... 

当将上述代码转换为二进制指令流时,汇编器(或链接器,如果您首先组装成目标文件)将确定该函数将驻留在内存中的位置(让我们忽略与位置无关的代码)目前)。它将驻留在内存中的位置通常在 ABI 中指定,或者如果您使用的是模拟器(例如 SPIM 加载 0x400000 - 请注意该链接还包含对该过程的良好解释)。

假设我们讨论的是 SPIM 情况,并且我们的函数首先位于内存中,则 slti 指令将驻留在 0x400000 处,beq 位于 <代码>0x400004等等。现在我们快到了!对于beq指令,分支目标地址cont0x400010)查看MIPS 指令参考 我们看到它被编码为 16 位带符号的直系亲属到下一条指令(除以 4,因为无论如何所有指令都必须驻留在 4 字节对齐的地址上)。

即:

Current address of instruction + 4 = 0x400004 + 4 = 0x400008
Branch target = 0x400010
Difference = 0x400010 - 0x400008 = 0x8
To encode = Difference / 4 = 0x8 / 4 = 0x2 = 0b10

beq $t0, $zero, cont 的编码

0001 00ss ssst tttt iiii iiii iiii iiii
---------------------------------------
0001 0001 0000 0000 0000 0000 0000 0010

如您所见,您可以分支到 -0x1fffc .. 0x20000 字节内。如果由于某种原因,您需要跳得更远,您可以使用蹦床(无条件跳转到给定限制内的真实目标)。

与分支目标地址不同,跳转目标地址是使用绝对地址(再次除以 4)进行编码的。由于指令编码使用 6 位操作码,因此只留下 26 位用于地址(实际上是 28 位,因为最后 2 位将为 0),因此在形成地址时使用 PC 寄存器的 4 位最高有效位(除非您打算跨越 256 MB 边界,否则这并不重要)。

返回到上面的示例,jal func 的编码是:

Destination address = absolute address of func = 0x400000
Divided by 4 = 0x400000 / 4 = 0x100000
Lower 26 bits = 0x100000 & 0x03ffffff = 0x100000 = 0b100000000000000000000

0000 11ii iiii iiii iiii iiii iiii iiii
---------------------------------------
0000 1100 0001 0000 0000 0000 0000 0000

您可以使用此 在线 MIPS 汇编器 我遇到过(注意它不支持所有操作码,例如 slti,所以我只是将其更改为 slt 这里):

00400000: <func>    ; <input:0> func:
00400000: 0000002a  ; <input:1> slt $t0, $a0, 2
00400004: 11000002  ; <input:2> beq $t0, $zero, cont
00400008: 34020001  ; <input:3> ori $v0, $zero, 1
0040000c: 03e00008  ; <input:4> jr $ra
00400010: <cont>    ; <input:5> cont:
00400010: 0c100000  ; <input:7> jal func

Usually you don't have to worry about calculating them as your assembler (or linker) will take of getting the calculations right. Let's say you have a small function:


func:
  slti $t0, $a0, 2
  beq $t0, $zero, cont
  ori $v0, $zero, 1
  jr $ra
cont:
  ...
  jal func
  ... 

When translating the above code into a binary stream of instructions the assembler (or linker if you first assembled into an object file) it will be determined where in memory the function will reside (let's ignore position independent code for now). Where in memory it will reside is usually specified in the ABI or given to you if you're using a simulator (like SPIM which loads the code at 0x400000 - note the link also contains a good explanation of the process).

Assuming we're talking about the SPIM case and our function is first in memory, the slti instruction will reside at 0x400000, the beq at 0x400004 and so on. Now we're almost there! For the beq instruction the branch target address is that of cont (0x400010) looking at a MIPS instruction reference we see that it is encoded as a 16-bit signed immediate relative to the next instruction (divided by 4 as all instructions must reside on a 4-byte aligned address anyway).

That is:

Current address of instruction + 4 = 0x400004 + 4 = 0x400008
Branch target = 0x400010
Difference = 0x400010 - 0x400008 = 0x8
To encode = Difference / 4 = 0x8 / 4 = 0x2 = 0b10

Encoding of beq $t0, $zero, cont

0001 00ss ssst tttt iiii iiii iiii iiii
---------------------------------------
0001 0001 0000 0000 0000 0000 0000 0010

As you can see you can branch to within -0x1fffc .. 0x20000 bytes. If for some reason, you need to jump further you can use a trampoline (an unconditional jump to the real target placed placed within the given limit).

Jump target addresses are, unlike branch target addresses, encoded using the absolute address (again divided by 4). Since the instruction encoding uses 6 bits for the opcode, this only leaves 26 bits for the address (effectively 28 given that the 2 last bits will be 0) therefore the 4 bits most significant bits of the PC register are used when forming the address (won't matter unless you intend to jump across 256 MB boundaries).

Returning to the above example the encoding for jal func is:

Destination address = absolute address of func = 0x400000
Divided by 4 = 0x400000 / 4 = 0x100000
Lower 26 bits = 0x100000 & 0x03ffffff = 0x100000 = 0b100000000000000000000

0000 11ii iiii iiii iiii iiii iiii iiii
---------------------------------------
0000 1100 0001 0000 0000 0000 0000 0000

You can quickly verify this, and play around with different instructions, using this online MIPS assembler i ran across (note it doesn't support all opcodes, for example slti, so I just changed that to slt here):

00400000: <func>    ; <input:0> func:
00400000: 0000002a  ; <input:1> slt $t0, $a0, 2
00400004: 11000002  ; <input:2> beq $t0, $zero, cont
00400008: 34020001  ; <input:3> ori $v0, $zero, 1
0040000c: 03e00008  ; <input:4> jr $ra
00400010: <cont>    ; <input:5> cont:
00400010: 0c100000  ; <input:7> jal func
放低过去 2024-12-04 22:02:04

我认为计算这些非常困难,因为分支目标地址是在运行时确定的,并且预测是在硬件中完成的。如果您更深入地解释了问题并描述了您正在尝试做的事情,那么会更容易提供帮助。 (:

I think it would be quite hard to calculate those because the branch target address is determined at run time and that prediction is done in hardware. If you explained the problem a bit more in depth and described what you are trying to do it would be a little easier to help. (:

聚集的泪 2024-12-04 22:02:04

对于像这样的小函数,您可以手动计算从分支指令下的指令到目标的跳数。如果向后分支,则跳数为负。如果该数字不需要全部 16 位,则对于跳数最高有效位左侧的每个数字,将它们设为 1,如果跳数为正,则将它们全部设为 0,因为大多数分支都接近它们目标,这在大多数情况下可以为您节省大量额外的算术。

  • 克里斯

For small functions like this you could just count by hand how many hops it is to the target, from the instruction under the branch instruction. If it branches backwards make that hop number negative. if that number doesn't require all 16 bits, then for every number to the left of the most significant of your hop number, make them 1's, if the hop number is positive make them all 0's Since most branches are close to they're targets, this saves you a lot of extra arithmetic for most cases.

  • chris
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文