我试图了解如何解码MIPS二进制指令。
我在带有gcc和objdump的Debian MIPS系统上用C语言编写了一个hello world程序,向我展示了.text节中的第一条指令是:
SignedoutCallbackPath
我不明白它如何确定这是600: 03e00025 move zero,ra
指令。
MOVE
是03e00025
的二进制。如果我正确理解这里的前6位是操作码,在这种情况下全为0,这意味着它是R型指令,因此我们必须查看后6位,即00000011111000000000000000100101
。查看MIPS Instruction Set Manual似乎应该是100101
指令。在该手册中我什至找不到OR
。
对此进行了谷歌搜索,我发现程序集中显然有“伪”指令,并且应该将MOVE
扩展为move $t, $s
,但是如果我看一下手册addiu $t, $s, 0
的操作码为{ {1}}。我发现另一个结果声称它可以转换为ADDIU
,但是001001
的最后六位应为ADD
,所以也不适合。
我想念什么?
答案 0 :(得分:1)
MIPS机器码没有针对move
的特定操作码,但是为了方便人类,许多汇编程序都支持伪指令,例如li
,la
和{{1 }}汇编成一个或多个真实的机器指令。 move
是常见的。
对于objdump,将指令解码为addiu
(根据Jester)以向您展示其实际编码方式是完全正确的。
出于某些目的,对于反汇编程序而言,解码任何将寄存器复制到or $0, $ra, $0
助记符的常用方法都是有意义的。对立即数move
进行加或或运算,或从读取0
寄存器中读取零,对该值不执行任何操作,以便将其复制不变。
阅读汇编程序时,通常不必关心它是$zero
,or
,ori
还是其他任何东西。
不同的汇编器可能对addiu $0, $ra, 0
伪指令使用不同的实现,或者手写asm可以使用其中的任何一种。我认为这两种方式都不会对性能造成任何影响。因此,使用哪种机器指令来实现move
的细节取决于汇编程序。
我不确定目的地为move
的{{1}}的点是什么。那将是无操作的,因为move
会丢弃写操作。 (相当于$zero
的CPU寄存器)