眾所周知,流水線技術對於軟體開發人員不是可見的(visiable),畢竟已經在在機器語言之下,是組成機器語言的基本邏輯
但今天我就帶領大家看看我新發現的結果,那就是流水線的可視效果,包括流水線預測技術的側面體現,當然也是可見的
首先我先宣告一下需要的基礎,需要懂16位元以及32位元作業系統下的組合語言,不懂者當然是不能體會到這篇文章的意圖的
知識點來源:x86組合語言從真真實模式到保護模式(希望以後大家寫部落格能標出知識點來源,幫助小白糾正知識是從部落格學來的壞習慣,以及給大家一個深入學習的機會)
好了,直接開始看程式碼(全組合)
1 mov eax,cr0 2 or eax,1 3 mov cr0,eax ;設定PE位 並以32位元模式開始譯碼 4 5 ;以下進入保護模式... ... 6 ;jmp dword 0x0008:flush ;16位元的描述符選擇子:32位元偏移 7 8 ;清流水線並序列化處理器 9 [bits 32];將之後的程式碼全部解析成32位元模式程式碼 10 flush: 11 mov cx,0100 ;載入資料段選擇子(0x10)
1-3行就是將16位元真真實模式轉換到32位元保護模式,並且將16位元下的譯碼模式轉換成32位元的譯碼模式
第6行的程式碼是跳轉到flush標籤,也就是第10行,不過我在這裡先行給它註釋
第9行是一條對於編譯器有作用的標籤,和C語言中的#pragma comment差不多,這裡的意思是之後的程式碼全部編譯成32位元的組合
下面是執行時的反組合程式碼
這兩條連續的反組合指令是從組合程式碼中的第三行開始的,我把組合程式碼以及機器指令一併圈了出來
大家有沒有發現不對勁,第二條反組合指令和我們手寫的組合指令不能說是看不出來,只能說是毫無關聯,
明明我們的運算元是cx,這邊竟然變成了ecx,還有立即數,明明是0x0010,這邊變成了0xd98e0010,也不怪大家看不出來,這換誰都一樣
大家都知道,機器是很傻的,我們叫他幹啥,他就幹啥,這邊為什麼就沒有聽我們的話呢
其實就是因為計算機流水線的緣故,大家可以回憶一下流水線的特性(不會等一條指令執行完了,再取下一條指令)
我們再仔細觀察一下第二條指令的機器程式碼, 66 b9 10 00 8e d9
66這這機器指令字首的作用是16位元模式下,將16位元暫存器轉成32位元暫存器,
32位元模式下,將32位元暫存器轉成16位元暫存器,
因為32位元和16位元下的代表暫存器的機器碼是一樣的,就比如16位元下cx是d9,而32位元模式下ecx也是d9,那總得有機器碼在32位元下表示cx吧
就拿上面這條66 b9 10 00 8e d9 舉例
32位元模式下這條指令是 :mov cx,0x0010(8e,d9之所以沒了,就是因為cx裝不下,本來這就是下一條指令的內容)
而16位元模式下就是: mov ecx,0xd98e0010
很明顯啊,我們的程式碼使用了16位元下的解碼方式,但是我們明明已經進入了保護模式
而究其原因就是計算機流水線的緣故了,很明顯是我們在mov cr0,eax之前就開始譯碼(decode)了mov cx,0x0010,而且是以16位元模式譯碼,直接導致了程式的失控
現在我們把組合程式碼第6行的註釋開啟,讓jmp生效(雖然我的學過的流水線遇到jmp是不會導致流水線暫停的,但有可能我虛擬機器器模擬的硬體太老)
可以看到,這下反組合指令就是完全正確的了,也的確說明了流水線發生了暫停,不然我們解碼肯定會以16位元來解碼