在通过Cross Compiler编译C到汇编MIPS之后,我得到了:
main:
.frame $fp,32,$31 # vars= 16, regs= 1/0, args= 0, gp= 8
addiu $sp,$sp,-32
sw $fp,24($sp)
move $fp,$sp
li $2,5 # 0x5
sw $2,8($fp)
lw $2,8($fp)
nop
sw $2,16($fp)
li $2,5 # 0x5
lw $3,16($fp)
nop
beq $3,$2,$L4
nop
li $2,10 # 0xa
lw $3,16($fp)
nop
beq $3,$2,$L5
nop
li $2,1 # 0x1
lw $3,16($fp)
nop
beq $3,$2,$L3
nop
b $L7
nop
$L3:
lw $2,8($fp)
nop
addiu $2,$2,3
sw $2,8($fp)
b $L7
nop
$L4:
lw $2,8($fp)
nop
sll $2,$2,3
sw $2,8($fp)
b $L7
nop
$L5:
lw $2,8($fp)
nop
srl $2,$2,2
sw $2,8($fp)
$L7:
move $sp,$fp
lw $fp,24($sp)
addiu $sp,$sp,32
j $31
nop
.end main
我不明白为什么有很多nop
代码行,这段代码中nop
的含义是什么?它对Pipeline Hazards
中的任何内容有帮助吗?如果我删除所有的n ??
答案 0 :(得分:2)
NOP
被插入。
回想一下,MIPS管道由5个阶段组成:Fetch,Decode,eXecute,Memory,Write-back。
让我们来看看NOP
。第一个是:
lw $2,8($fp)
nop
sw $2,16($fp)
此代码假定没有内存 - 内存转发。为什么?因为如果你绘制一个时间线管道图,你会看到NOP
迫使sw
的内存阶段在lw
的回写阶段后的一个周期内发生。因此,代码假定处理器具有存储器 - > ALU转发或回写 - >内存转发。如果我们之间没有使用NOP
,sw
的内存阶段会从$2
读取一些垃圾值(无论来自解码阶段),行为都是未定义的。< / p>
第二个nop
:
lw $3,16($fp)
nop
beq $3,$2,$L4
此处,$3
仅在lw
的Memory阶段结束后可用。如果我们没有NOP
,那么beq
eXecute阶段将发生在与lw
的内存阶段相同的周期中,即使使用内存也是如此 - &gt; ALU转发。因此,我们必须延迟beq
一个周期,这就是NOP
正在做的事情。使用此NOP
,beq
的执行阶段将在lw
的内存后一个周期发生。这是有效的,假设有记忆 - &gt; ALU转发。
类似的原因也适用于其他情况,我建议你自己解决这个问题。
答案 1 :(得分:2)
根据您的代码添加所有'nop'指令以修复以下错误
1)分支延迟
2)负载延迟
因为这些nop是由编译器添加的,你可以明确地给编译器一个选项,让我们不要通过“set noreorder”更好地添加这些nop指令。我应该给你参考read。 “请参阅Mips Run 2nd Edition”页面编号我并没有看到'nop'是危险屏障。按照这本书。