空指令的作用
大多數(shù)CPU指令集設(shè)計(jì)中會有空指令實(shí)現(xiàn):
例如:
x86的空指令是nop,對應(yīng)的機(jī)器指令是0x90,它等價(jià)于xchge ax,ax 指令;
MIPS的空指令nop對應(yīng)的機(jī)器碼是0x0000 0000(32位全零),它等價(jià)于將R0(0值)左移0位;
ARM32的空指令nop對應(yīng)機(jī)器碼是0x00 00 A0 E1?,ARM64將NOP改為偽指令了,對應(yīng)的機(jī)器碼是0xE0 03 00 AA,等價(jià)于MOV X0,X0,或者0x00 00 00 91,等價(jià)于?ADD X0, X0, #1
不管是哪種空指令,本質(zhì)都是CPU做了個(gè)沒有意義的動(dòng)作,做完后不改變CPU所有寄存器的內(nèi)容,只是白白占用了指令執(zhí)行周期。
那空指令的作用是什么?
?編譯器可以利用加nop指令來解決流水線沖突問題:

解決流水線沖突,也可以像大多數(shù)教材里說的,使流水線暫?;蚣託馀?。

Nop和氣泡的區(qū)別:加nop指令是在編譯環(huán)節(jié)由編譯器做的事情,nop是一條完整的指令,必須從取指階段開始。加氣泡bubble一般都是在某條指令取指令以后發(fā)現(xiàn)沖突時(shí),由處理器判斷,當(dāng)前已經(jīng)取指的指令如果進(jìn)行到執(zhí)行階段,就會產(chǎn)生錯(cuò)誤結(jié)果,因此會讓這條錯(cuò)誤的指令在bubble之后的各個(gè)階段都執(zhí)行相當(dāng)于nop的操作,不改變寄存器狀態(tài)。這樣就相當(dāng)于取消了這條錯(cuò)誤指令。
關(guān)于流水線加氣泡和暫停的區(qū)別:
https://blog.csdn.net/zhousiyuan0515/article/details/126910056
暫停是避免冒險(xiǎn)的一種常用手段,暫停時(shí),處理器會停止流水線中一條或多條指令,直到冒險(xiǎn)條件不再滿足,讓一條指令停在譯碼階段直到產(chǎn)生它的源操作數(shù)的指令通過了寫回階段,因此,其后的指令也應(yīng)該暫停在取指階段,直到暫停結(jié)束。
我們使用插入氣泡來實(shí)現(xiàn)暫停(暫停和氣泡不是一個(gè)東西,氣泡是把流水線寄存器清空,而暫停時(shí)維持流水線寄存器的狀態(tài),我們只是說插入氣泡來實(shí)現(xiàn)暫停,并沒有說暫停和氣泡是一個(gè)東西),暫停不會改變?nèi)魏螤顟B(tài),而只會阻止被暫停的指令流水進(jìn)入下一個(gè)階段。因此我們查看上文討論過的程序發(fā)現(xiàn),我們需要產(chǎn)生三條nop指令,雖然實(shí)現(xiàn)起來非常容易,但是帶來的副作用就是我們暫停了三個(gè)周期,這是很大的代價(jià)。