Assembly 此组件MIPS中的Nop和管道危险
通过交叉编译器将C编译成程序集MIPS后,我有:Assembly 此组件MIPS中的Nop和管道危险,assembly,mips,Assembly,Mips,通过交叉编译器将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,1
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
的含义是什么?它对管道危险有帮助吗?如果我删除所有的NOP怎么办 由于管道危险,插入了NOP
回想一下,MIPS管道由5个阶段组成:获取、解码、执行、存储和写回
让我们看一些NOP
s。第一个是:
lw $2,8($fp)
nop
sw $2,16($fp)
此代码假定没有内存转发。为什么?因为如果您绘制时间线管道图,您将看到NOP
正在强制sw
的内存阶段在lw
上的写回阶段之后正好一个周期发生。因此,代码假定处理器具有内存->ALU转发,或写回->内存转发。如果我们没有在两者之间使用NOP
,sw
的内存阶段将从$2
中读取一些垃圾值(来自解码阶段的任何内容),并且行为将是未定义的
第二个nop
:
lw $3,16($fp)
nop
beq $3,$2,$L4
这里,$3
仅在lw
的内存阶段完成后可用。如果我们没有NOP
,那么beq
执行阶段将与lw
的内存阶段在同一个周期内发生,这是不可能的,即使使用内存->ALU转发。因此,我们必须将beq延迟一个周期,这就是NOP所做的。使用此NOP
,beq
的执行阶段将在lw
的内存后一个周期发生。这是可行的,假设存在内存->ALU转发
类似的原因也适用于其他情况,我建议您自己尝试解决。
NOP
s是由于管道危险而插入的
回想一下,MIPS管道由5个阶段组成:获取、解码、执行、存储和写回
让我们看一些NOP
s。第一个是:
lw $2,8($fp)
nop
sw $2,16($fp)
此代码假定没有内存转发。为什么?因为如果您绘制时间线管道图,您将看到NOP
正在强制sw
的内存阶段在lw
上的写回阶段之后正好一个周期发生。因此,代码假定处理器具有内存->ALU转发,或写回->内存转发。如果我们没有在两者之间使用NOP
,sw
的内存阶段将从$2
中读取一些垃圾值(来自解码阶段的任何内容),并且行为将是未定义的
第二个nop
:
lw $3,16($fp)
nop
beq $3,$2,$L4
这里,$3
仅在lw
的内存阶段完成后可用。如果我们没有NOP
,那么beq
执行阶段将与lw
的内存阶段在同一个周期内发生,这是不可能的,即使使用内存->ALU转发。因此,我们必须将beq延迟一个周期,这就是NOP所做的。使用此NOP
,beq
的执行阶段将在lw
的内存后一个周期发生。这是可行的,假设存在内存->ALU转发
类似的原因也适用于其他情况,我建议您自己尝试解决这些问题。根据您的代码,添加了所有“nop”指令以修复以下错误 1) 分支延迟 2) 负载延迟
由于这些nop是由编译器添加的,所以您可以通过“set noreorder”显式地为编译器提供一个选项,使其不添加这些nop指令。更好的是,我应该为您提供阅读参考。“见Mips运行第二版”第288页。根据本书,我不认为“nop”是危险屏障装置。根据您的代码,添加了所有“nop”说明以修复以下错误 1) 分支延迟 2) 负载延迟
由于这些nop是由编译器添加的,所以您可以通过“set noreorder”显式地为编译器提供一个选项,使其不添加这些nop指令。更好的是,我应该为您提供阅读参考。“见Mips运行第二版”第288页。根据这本书,我不认为nop是危险屏障。我认为第一个(
lw…nop…sw
)确实有内存转发,如果没有,将有2条nop线(…nop…nop…)来避免危险。@VAK有内存->ALU转发或写回->内存转发,但没有内存->内存。如果有内存->内存,我们就不需要NOP。有了这个NOP,我们将sw
的解码与lw
的内存放在同一个周期上(因此,可能有来自内存的转发->ALU,丢弃从解码读取的垃圾);它还将sw
的内存放在与lw
的写回相同的周期中,因此我们也可以进行写回->内存转发。但是我们肯定没有内存->内存,或者如果我们有,编译器也不会意识到。我认为第一个(lw…nop…sw
)确实有内存转发,如果没有,将有两条nop行(…nop…nop…)来避免危险。@VAK有内存->ALU转发或写回->内存转发,但没有内存->内存。如果有内存->内存,我们就不需要NOP。有了这个NOP,我们将sw
的解码与lw
的内存放在同一个周期上(因此,可能有来自内存的转发->ALU,丢弃从解码读取的垃圾);它还将sw
的内存放在与lw
的写回相同的周期中,因此我们也可以进行写回->内存转发。但是我们肯定没有内存->内存,或者如果我们有,编译器也不知道。