【问题标题】:MIPS Instruction DecodingMIPS指令解码
【发布时间】:2019-04-26 11:47:27
【问题描述】:

我正在尝试了解如何解码 MIPS 二进制指令。

我使用 gcc 在 Debian MIPS 系统上用 C 语言编译了一个 hello world 程序,objdump 显示 .text 部分中的第一条指令是:

600: 03e00025 move zero,ra

我不明白它如何确定这是MOVE 指令。

03e00025 是二进制的00000011111000000000000000100101。如果我理解正确,这里的前 6 位是操作码,在这种情况下全为 0,这意味着它是 R 型指令,所以我们必须查看最后 6 位,即100101。查看MIPS Instruction Set Manual 看起来这应该是OR 指令。我什至在该手册中都找不到MOVE

对此进行谷歌搜索,我发现程序集中显然存在“伪”指令,并且据称move $t, $s 扩展为addiu $t, $s, 0,但如果我查看手册ADDIU 有操作码001001。我发现的另一个结果声称它转换为ADD,但ADD 的最后六位应该是100000,所以也不适合。

我错过了什么?

【问题讨论】:

  • 是的,编码为or $0, $ra, $0

标签: assembly mips disassembly objdump instruction-encoding


【解决方案1】:

MIPS 机器代码没有针对move 的特定操作码,但为了方便人类,许多汇编器支持伪指令,如lilamove,它们可以组装成一个或多个真机指令。 addiu 是常见的。

objdump 将指令解码为or $0, $ra, $0(根据 Jester)来向您展示它的实际编码方式是完全正确的。

出于某些目的,反汇编程序可以对任何常用的方法进行解码,以将寄存器复制到move 助记符中。添加或 ORing 立即数 0,或读取 $zero 寄存器中的零,对值不做任何操作,因此它被原封不动地复制。

在阅读 asm 时,您通常不关心它是 ororiaddiu $0, $ra, 0 还是其他。


不同的汇编器可能对move 伪指令使用不同的实现,或者手写的asm 可以使用其中的任何一个。我认为这两种方式都不会对性能产生任何影响。所以具体使用哪条机器指令来实现move取决于汇编器。


我不确定目标为$zeromove 的意义是什么。那将是一个空操作,因为$zero 丢弃了写入。 (它相当于 /dev/zero 的 CPU 寄存器)

【讨论】:

  • 哇,好棒的答案!现在我明白了 :-) 非常感谢!
  • 关于伪指令的实现选择:一些 ISA(例如 RISC-V)为伪指令定义规范编码。比如nopmov。在复杂的微架构中,这可以实现更简单的检测逻辑,例如零周期寄存器重命名,因为只有一个编码可以检测。 nop-like instr。也可用于编码微架构。提示(例如分支预测提示)。
猜你喜欢
  • 2012-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-10
相关资源
最近更新 更多