如何计算MIPS分支指令的最大单跳范围?

时间:2018-04-24 23:01:34

标签: assembly mips

我正在学习计算机体系结构(MIPS架构)并阅读以下语句:

1.Branch指令有一个16位有符号字偏移字段,允许从当前位置分支到地址+或-128kBytes(+ 0x1FFFC TO -0X20000)。

2.跳转指令指定当前256MByte(0x0FFFFFFC)区域内的地址,该区域由程序计数器指定最高4位。

我理解上面描述的跳跃范围的概念但是如何使用" 256Mbyte"的范围来计算三个数字0x0FFFFFFC,0x1FFFC和0X20000。和"范围为+ -128千字节"?

谢谢!

2 个答案:

答案 0 :(得分:2)

其他答案并没有真正回答您如何计算/找到这些十六进制值的问题。所以这是我的答案。

在二进制中考虑这一点比在十六进制中容易得多。因为 2bit 左移对于理解这个概念很重要 2bits 乘以 4。 由于简单的十六进制数字是 16 个值,因此不能很好地用十六进制表示。 但我还是试着解释一下:

0x20000

1 分支指令使用 16 位立即数字段。 (5 位 RS,RT)(6 位操作码)== 32 位 (https://en.wikibooks.org/wiki/MIPS_Assembly/Instruction_Formats#I_Format)

那 16 位是有符号的。它们可以是积极的也可以是消极的。

这为您提供了 -(2^15) == -32768 的有效范围

+(2^15 -1) == 32767

MIPS 将任何地址输入乘以 4。强制它们按字对齐。

所以你的最小值 -(2^15) 乘以 4:-{2^15 *4} (4=2^2), {2^(15+2)} (15+2 == 17): 变成-(2^17) == -131072

二进制(带符号的 2 的补码)。 1000 0000 0000 0000 <<2 == 10 0000 0000 0000 00[00]

将其转换为十六进制 10=2 (0000=0) gives 2 0 0 0 0 == 0x20000

这将在将其添加到 (PC+4) 之前进行符号扩展:

so for say, instruction #32770, PC=0x00420008 (PC+4)=0x0042 000C

0x0042000C - 0x20000 = 0x0040000C, instruction #3(记住,偏移量基于 PC+4)

#32770+1 +-32768 == 3

0x1FFFC

最大值相同: (2^15 -1) 乘以 4:{(2^15 -1) *4} (4=2^2), {2^(15+2) -(1*4)} (15+2 == 17)

变成(2^17 -4) == 131068 0111 1111 1111 1111 <<2 == 01 1111 1111 1111 11[00]

将其转换为十六进制 01=1 (1111=F) (1100=C) gives 1 F F F C == 0x1FFFC

注意地址需要加到当前(Program Counter+4)

so for say, instruction #32770, PC=0x00420008 (PC+4)=0x0042000C

0x0042000C + 0x1FFFC= 0x440008, instruction #65538(记住,偏移量基于 PC+4)

#32770+1 +32767 == 65538

0x0FFFFFFC

2 现在跳转使用 28 位地址。
另请注意,跳转使用绝对地址。不是偏移量。

最大 28 位值为 (2^26 -1) == 67108863, 0x03FFFFFF ``

移位 2 (*4) 变为 28 位。 {(2^26 -1) *4}, == {2^28 -4} == 268435452,0x0FFFFFFC

但是那缺少的四位呢? ..它们来自PC——在Memory阶段,它已经增加到(PC+4)

对于指令#32770,PC=0x00420008 (PC+4)=0x0042000C 0x0042000C in binary is [0000] 0000 0100 0010 0000 0000 0000 1100

+0x0FFFFFFC in binary [####] 1111 1111 1111 1111 1111 1111 1100 它只有 28 (27:0) 位并且缺少 31:28 位。

从 PC+4 中获取数据。我们得到:

 0000 ---- ---- ---- ---- ---- ---- ---- (PC+4)
 ---- 1111 1111 1111 1111 1111 1111 1100 (Target-Address)
-----------------------------------------
 0000 1111 1111 1111 1111 1111 1111 1100 (Jump-Address)

(在这种情况下与符号扩展相同的值)

更好地解释地址是如何计算的。 How to Calculate Jump Target Address and Branch Target Address?

答案 1 :(得分:1)

为什么不问一个经过测试和调试过的工具链,然后将其与文档进行比较?

so.s

four:
nop
nop
nop
j one
nop
j two
nop
j three
nop
j four
nop
nop
nop
nop
nop
one:
nop
two:
nop
nop
three:
nop

构建和反汇编

mips-elf-as so.s -o so.o
mips-elf-objdump -D so.o

so.o:     file format elf32-bigmips


Disassembly of section .text:

00000000 <four>:
    ...
   8:   0800000f    j   3c <one>
   c:   00000000    nop
  10:   08000010    j   40 <two>
  14:   00000000    nop
  18:   08000012    j   48 <three>
  1c:   00000000    nop
  20:   08000000    j   0 <four>
  24:   00000000    nop
    ...

0000003c <one>:
  3c:   00000000    nop

00000040 <two>:
    ...

00000048 <three>:
  48:   00000000    nop

链接到某个地址并反汇编

00001000 <_ftext>:
    ...
    1008:   0800040f    j   103c <one>
    100c:   00000000    nop
    1010:   08000410    j   1040 <two>
    1014:   00000000    nop
    1018:   08000412    j   1048 <three>
    101c:   00000000    nop
    1020:   08000400    j   1000 <_ftext>
    1024:   00000000    nop
    ...

0000103c <one>:
    103c:   00000000    nop

00001040 <two>:
    ...

00001048 <three>:
    1048:   00000000    nop

所以跳转很容易分支怎么样?

four:
nop
nop
nop
beq $10,$11,one
nop
beq $10,$11,four
nop
nop
nop
one:
nop

汇编和反汇编

00000000 <four>:
    ...
   8:   114b0006    beq $10,$11,24 <one>
   c:   00000000    nop
  10:   114bfffb    beq $10,$11,0 <four>
  14:   00000000    nop
    ...

00000024 <one>:
  24:   00000000    nop

一些经验对此有帮助,首先是前进0x24 - 0x8 = 0x1C。这些都是固定的32位指令,所以不太可能浪费这两位并削减范围,所以0x1C>&gt; 2 = 7.编码有6.好吧它也可能是他们在考虑pc有已增加,或另一种方式来查看这是前面的6(+1)指令。 0xC,0x10,0x14,0x18,0x1c,0x20,0x24。所以这意味着倒退就是 (0x00 - (0x10 + 4))&gt;&gt; 2 =(0x00-0x14)&gt;&gt; 2 = 0xFFFF ... FFFFEC&gt;&gt; 2 = 0xFF ... FFFB 当然这就是我们得到的。

所以对于分支机构你需要

((destination - (current address + 4))/4)&0xFFFF = 
(((destination - current address)/4) + 1)&0xFFFF

对于立即跳跃= {pc [31:28],目的地[28:2]}

您应该能够从该信息中找出范围。

作为指令的编码的关键是固定在32位并在32位边界上对齐,所以两个lsbits总是零以及与它们相关的数学,所以为什么要将你的范围缩小4来存储零?你没有,你有效地将补偿包装到了眼前。一些(固定长度)指令集不这样做,但通常有理由不作为设计的一部分。

通常,如果您有权访问一个调试汇编程序,那么它将提供比指令集引用更有用的信息,这是基于学习许多指令集的经验。如果你是第一个为某个处理器编写汇编程序的人,那么这意味着你在那里工作或直接访问处理器的设计者,你可以简单地问他们数学,而不是依赖于尚未编写的手册,他们将在芯片录制完毕后编写,因为您/他们需要汇编程序来验证设计。所以电子邮件,Skype和最重要的白板讨论指令编码。您可能还可以访问芯片源代码和/或模拟器,这样您就可以运行代码,看到它在sim中执行(检查波形)并查看它分支到哪里(它取出的位置),立即更改,看看在它取得的地方。

基本上,您应该总是能够访问具有答案的资源,该答案可以帮助解释缺少某些细节的手册。有时你会得到一本好的手册......(你仍然应该用资源验证)。