首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何计算跳转目标地址和分支目标地址?

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

Stack Overflow用户
提问于 2011-08-05 08:40:47
回答 4查看 114.5K关注 0票数 35

我是汇编语言的新手。我读到了有关MIPS架构的文章,我被跳转目标地址分支目标地址以及如何计算它们的每个所困扰。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-03-21 06:05:07

(在下面的图表和文本中,PC是分支指令本身的地址。PC+4是分支指令本身的结尾,也是分支延迟时隙的开始。除了在绝对跳跃图中。)

1.分支地址计算

在MIPS中,分支指令只有16位偏移量来确定下一条指令。我们需要一个寄存器加到这个16位的值上,以确定下一条指令,而这个寄存器实际上是体系结构所暗示的。它是PC寄存器,因为PC在提取周期期间得到更新(PC+4),因此它保存下一条指令的地址。

我们还将分支距离限制为从分支指令之后的(指令)到-2^15 to +2^15 - 1指令。然而,这并不是真正的问题,因为大多数分支机构都是本地的。

按部就班地So :

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

2.跳转地址计算

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

一步一步地再次使用

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

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

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

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

票数 79
EN

Stack Overflow用户

发布于 2011-08-05 17:23:30

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

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

当把上面的代码翻译成二进制指令流时,汇编器(或者链接器,如果你首先汇编成一个目标文件),它将确定函数在内存中的位置(现在让我们忽略与位置无关的代码)。它将驻留在内存中的位置通常是在ABI中指定的,或者如果您正在使用模拟器(如在0x400000加载代码的SPIM -注意,该链接也包含了对该过程的很好的解释)。

假设我们在讨论SPIM的情况,并且我们的函数首先在内存中,那么slti指令将驻留在0x400000中,beq将驻留在0x400004中,依此类推。现在我们就快到了!对于beq指令,分支目标地址是cont (0x400010)的地址。查看MIPS instruction reference,我们可以看到它被编码为相对于下一条指令的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位用于地址(假设最后两位为0,则有效为28位),因此在形成地址时使用PC寄存器的4位最高有效位(除非您打算跨越256MB边界,否则无关紧要)。

返回到上面的示例,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

您可以使用我遇到的这个online MIPS assembler快速验证这一点,并尝试不同的指令(请注意,它不支持所有操作码,例如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
票数 21
EN

Stack Overflow用户

发布于 2014-02-25 05:27:45

对于像这样的小函数,您可以根据分支指令下的指令,手工计算到目标的跳数。如果它向后分支,则将该跳数设为负数。如果这个数字不需要所有的16位,那么对于你的跳数的最高有效位左边的每个数字,将它们设为1,如果跳数为正,则将它们设为全0,因为大多数分支离它们的目标很近,这在大多数情况下为您节省了大量额外的计算。

  • chris
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6950230

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档