assembly - MIPS 汇编链接器练习
解决方案
如果你擅长手动编码和解码指令,这对你来说实际上很容易。考虑一下底部的这一行,内容如下:
38: 08000014 j 50 <check+0x50>
因为这是一个跳转指令,我们必须像链接器那样修改它。最后,我们试图跳到第 50 行,内容如下:
50: 8fc20000 lw v0,0(s8)
我们必须考虑两件事,第 50 行的实际地址,以及第 38 行的内容,目前为08000014
如果我将08000014分解为二进制,我会得到:
0000 1000 0000 0000 0000 0000 0001 0100
如果我没有幸知道这是一个跳转指令(就像在这种情况下),我怎么知道它是什么格式?按格式,我指的是 MIPS 参考数据表,它具有R、I和J指令格式。您必须取 6 个最高有效位!
0000 10|00 0000 0000 0000 0000 0001 0100
如果 6 个最高有效位为 0,那么我们将采用R格式。但是,在这种情况下,000010是二进制的2。如果您扫描数据表中的OPCODE / FUNCT列,您会在对应于跳转指令的行上找到 2 个十六进制,它具有J格式:
6 bit opcode | 26 bit instruction
如果我们继续将上面的二进制序列的其余部分分成四组:
0000 10|00 00|00 00|00 00|00 00|00 00|01 01|00
然后左移两位,我们得到:
0010 0000 0000 0000 0000 0000 0101 0000
将其转换回十六进制以获得:
2 0 0 0 0 0 5 0
记下 2 个最不重要的十六进制值。他们读了50。巧合?我觉得不行让我们继续...
请注意,检查的地址是00400690,我们试图跳转到的行是 50 偏移量。这意味着我们必须做一些十六进制加法。400690 + 50 = 4006E0
取那个20000050值并用 4006E0 替换 6 个最低有效位以获得.....鼓声..... 204006E0!我们几乎完成了,我们只需要逆转我们之前所做的一步。取这个数字,并将其分解为二进制:
0010 0000 0100 0000 0000 0110 1110 0000
然后将所有内容向右移动 2 位以获得:
0000 1000 0001 0000 0000 0001 1011 1000
然后转换回十六进制:
0 8 1 0 0 1 B 8
这将是内容列中的值。至于这条跳转指令的地址,我们只是做我们所做的找到第 50 行的地址。跳转指令是从check偏移 38 处,所以我们只需将 00400690 加上 38 就可以得到这个字的地址,这是4006C8