1

我对下面代码中的几个 MIPS 指令有疑问
1.addi是算术指令,它的目的是什么?
2. 为什么andnop后面有一个s,后面有多个s ? 谢谢 !jbeqnopaddi

if(a==b)  x=3; /* simple C code */
else      x=4;
y=5;  

       lw   $1,a       # possible unoptimized assembly language
       lw   $2,b       # no ($0) shown on memory access
       nop             # wait for b to get into register 2
       nop             # wait for b to get into register 2
       beq  $1,$2,lab1
       nop             # branch slot, always executed *********
       addi $1,4       # else part
       nop             # wait for 4 to get into register 1
       nop             # wait for 4 to get into register 1
       sw   $1,x       # x=4;
       j    lab2
       nop             # branch slot, always executed *********    
lab1:  addi $1,3       # true part  
       nop             # wait for 3 to get into register 1
       nop             # wait for 3 to get into register 1
       sw   $1,x       # x=3;  
lab2:  addi $1,5       # after if-else, always execute
       nop             # wait for 5 to get into register 1
       nop             # wait for 5 to get into register 1
       sw   $1,y       # y=5;
4

3 回答 3

3

addi 是“添加立即数”,它将立即数(常量,整数)添加到寄存器的内容。其他添加变体是使用寄存器添加寄存器。

从 mips 的角度来看,addi 之后的 nops 和描述完全没有意义。Mips 很好地用于教育目的,您正在使用或正在教授的特定实现可能需要时间让 addi 指令解码和执行并将结果存储到寄存器文件,然后该寄存器可以用作另一条指令的输入。通常,mips 核心(或任何现代流水线处理器)将阻止下一条指令或使用其他解决方案来缩短作为下一条指令输入的一条指令的结果。

它不仅是 addi,而且是 lw,您可以在其中看到这些 nop 用于延迟时间,正如评论所说的那样,将结果存储在寄存器中。

至少要考虑基本步骤,获取、解码、执行、存储结果。即使真正的 mips 不需要,这段代码似乎也允许至少其中一些步骤完成。

在分支之后有延迟槽是非常重要的事情(当然其他人会这样做,但它比常见的更罕见)。最简单的方法是在每个分支或跳转后放一个 nop 并浪费循环。最终,您将了解何时可以将其中一条指令放在分支之前并将其放在之后,否则如果找不到则使用 nop。

一般来说,代码看起来不错。为了使 addi 指令工作以使代码代表 C 代码,addi 确实需要使用始终为零的寄存器 0。Addi 接受一个寄存器,然后立即将它们加在一起,然后将结果放入另一个寄存器中,一个 addi 有两个寄存器,一个常量...您拥有的代码仅显示一个寄存器。对于该代码中所有 addi 的使用,如果您这样想的话:

addi $1,4 
changes to 
addi $1,$0,4
register $0 is always zero so this instruction really means
$1 = 0 + 4 = 4
$1 = 4

我从正式的角度和机器代码的角度了解 mips 指令,也许 addi $1,4 是代表更正式的 addi $1,$0,4 的快捷方式。汇编代码然后检查该指令的机器代码,您可能会看到两个寄存器 $1 和 $0 以及立即数 4。

Mips 没有 mov 指令,您可以在其中一次移动整个寄存器大小的立即数。lui 指令用于在寄存器的上半部分放置位,在下半部分放置零。Lui 后跟一个 addi 或一个 ori 可以用作一个团队来加载立即数。或者,如果高位为零,则可以使用带有寄存器 0 ($0) 的 addi 或 ori 在单个指令中设置低位。为了让这个 asm 表示 C 代码,必须是后者。

于 2012-11-01T05:47:32.733 回答
1

我不知道 MIP 汇编器我猜如下(在阅读了 Wiki 文章MIPS Architecture之后)

  1. 作者知道 a = 0,因此 $1 = 0,因此 addi $1, 4 将 $1=4 设置为 x 为 sw 做好准备。
  2. NOP 没有意义——除非作者知道指令是并行的,因此插入时钟周期等待以确保前面的指令完成。

代码是否有更多上下文(即 x 和 a、b 等的设置)

于 2012-11-01T03:17:22.397 回答
1

在普通的 MIPS 汇编程序中,addi $1,4是 的简写addi $1,$1,4,即 $1 加 4。将常量加载到寄存器中的正常速记是li $1,4汇编程序通常翻译成的ori $1,$0,4。(寄存器 $0 始终包含零。)

讲师的示例似乎不正确,除非a已知始终为零。在这种情况下,有更好的方法来实现此代码。

于 2012-11-01T22:12:33.367 回答