你可以看看到维基百科或学生简短总结 。 人人都说有对同一事物的两个指令。 但是,没有人告诉为什么呢?
Answer 1:
分行允许的条件。 但是在指令允许条件下占用更多的比特。 因此,一个分支机构的地址是唯一的2 ^ 16位,只允许你分支2 ^ 15 - 1个落后的指令或2 ^ 15的指示前进。
跳转是无条件的和留出的条件保存的位可用于地址。 跳转允许26位地址,因此可以在代码中不是分支更远跳。 在不被条件为代价的。
Answer 2:
分行( b
)使用PC相对位移而跳跃( j
)使用绝对地址。 这种区别是位置无关的代码很重要。 此外,只有跳转可用于间接控制传输( jr
,使用寄存器值)。
Answer 3:
如已经提到的,分支具有较少的位,较小的范围,是相对的。 跳转有更多的位,是绝对的。
就拿这个例子
b l0
nop
beq $0,$1,l1
nop
j l2
nop
l0: .word 0,0
l1: .word 0,0
l2: .word 0,0
你得到这个
00000000 <l0-0x1c>:
0: 10000006 b 1c <l0>
4: 00000000 nop
8: 10010006 beq zero,at,24 <l1>
c: 00000000 nop
10: 0800000b j 2c <l2>
14: 00000000 nop
18: 00000000 nop
0000001c <l0>:
...
00000024 <l1>:
...
0000002c <l2>:
...
现在是什么其他的答案可能没有提到的是,无条件转移被编码,至少GNU汇编,作为一个分支,如果相同,具有相同的寄存器。 有一个在MIPS没有无条件转移,有分支,如果相等,分支如果不从我可以告诉相等。
你看到跳转以上使用0XB它是字地址,0XB * 4 = 0x2c上的目的地,其中,所述条件语句用相对寻址PC +的地址(signed_offset * 4)的pc = instruction_address + 4; 或采取instruction_address + 4 +(signed_offset * 4),以获得目标地址。
使用别名b。对于分支,而不是J表示跳将创建与位置无关的代码。 跳转不会,如果有你走动,近重新链接跳转可能是更好的使用分支,而不是跳跃,即使它是一个别名。 如果你是一个纯粹的,那么你可以使用真正的指令BEQ $ 0 $ 0标签或选择任何寄存器BEQ $ 4,$ 4的标签。 寄存器0是特殊的,快速的可能是更好的选择。
Answer 4:
跳转和无条件的分支,在MIPS,是不一样的。
这两个分支和跳转指令将数据写入程序计数器登记,以便于下次提取周期,不同的指令将被取出,而不是在程序存储器中线上的下一个指令。 在这个意义上说,他们进行相同类型的操作。
它们的不同在于分支是有条件的,他们只更改,如果满足特定条件要执行的下一条指令。 这可通过在执行代码的差在被图示的if
语句或通过调用一个函数。
if (a == 0) {
a = 1
}
setAtoOne()
的if
语句跳转到指令设置a = 1
只有a == 0
。 该函数将跳转到该指令而不管。
在这种情况下,我们谈论的一个分支中条件总是如此。 这是写作的只是另一种方式
beq $zero, $zero, (int)offset
$零总是等于$为零,因此它总是跳转到指定的偏移。 这就像这个if语句
if (true) { a = 1 }
有分支和跳转指令的另一个区别。 跳转指令指定的PC将被设置成,而分支指令抵消了程序计数器的地址的绝对地址。
PC = 32-bit address # Jump
PC += 16-bits lower
实际上,这并不完全正确。 我们编写汇编与绝对地址和偏移量但在这两种转移和跳转它被编译为一个偏移量。 这就是为什么你不能在内存跳转或转移到任何地方,使用跳转到注册期待jr
指令。 这是因为MIPS的基本设计,固定长度的一个字指令。
所有MIPS指令是1个字(即4个字节/ 32位)长。 它们包含指令(称为操作码)的ID是与执行该指令所需要的其他信息一起6个比特。 这可能是寄存器或“即时”值,基本上整数在指令中编码的ID。
在MIPS在内存中的每个字节有之间的地址0x00000000
- 0xFFFFFFFF
。 为了得到这些,我们需要指定地址字节之一。 如果幸运的话存储在寄存器中,我们只想地址jr
和使用已经存储在寄存器中的地址。 然而,我们没有。
这成为问题,我们只对我们的指示,32位,我们需要所有这些位在这个范围内指定地址。 我们也只好放弃处理器用于识别指令6位。 现在我们只剩下26位。
更糟的是,当我们的分支,我们需要额外的10位来指定两个寄存器我们是在比较我们的条件。 该解决方案是使用偏移。
比方说,我们在地址0x12345678
,我们正在执行在内存中无条件跳转到下一个地址j 0x1234567c
。 这是汇编代码,我会告诉该如何被翻译成机器代码并执行。
首先,我们骗了一点。 我们知道指令是一个字(4个字节)和MIPS它的规定,他们必须在字边界内。 这意味着所有指令具有4个字节的地址分开,这意味着它们总是以00结束二进制表示。 太好了,我们可以剃去这两个毫无意义位。 我们也刮胡子第6,但不要担心,我们会得到他们回来。
jump 0001 0010 0011 0100 0101 0110 0111 11 00 jump 0001 0010 0011 0100 0101 0110 0111 11 00 0000 10 00 1000 1101 0001 0101 1001 1111 #in machine code # jump op = 0000 10
当我们执行这个我们采取 00 1000 1101 0001 0101 1001 1111 0000 00 00 1000 1101 0001 0101 1001 1111 # extend >> 6 0000 00 10 0011 0100 0101 0110 0111 11 00 # << 2
然后,我们和PC(这里我们从执行)和0xf0000000
0001 0010 0011 0100 0101 0110 0111 1000
1111 0000 0000 0000 0000 0000 0000 0000
AND
0001 0000 0000 0000 0000 0000 0000 0000
我们知道,利用这个结果,或将其与我们的指令整数
0001 0000 0000 0000 0000 0000 0000 0000
0000 0010 0011 0100 0101 0110 0111 1100
OR
0001 0010 0011 0100 0101 0110 0111 1100
这是0x1234567c
在十六进制和我们想去的地方,现在我们跳到那里。 这就是为什么你不能再超过256MB(2 ^ 28位),远离你的当前指令跳(除非你跳转到一个寄存器的值jr
)
同样的基本思想适用于分支机构,除了现在你也有被比较的2个寄存器(要求10位),所以你只有16位,可以用来抵消,因此,你为什么不能用树枝就跳。
一般情况下,这是很好的,因为我们主要是在过程中使用的分支,以实现循环和开展有条件分配。
这是MIPS架构的设计,所有的结果。 这本来是完全可能的地方分支机构和跳跃之间唯一的区别将是有条件的方面和在那里的“无条件”分支会表现一样无条件跳转指令。