計算機流水線在正常程式中的體現(效果可視)

2023-04-01 12:00:24

眾所周知,流水線技術對於軟體開發人員不是可見的(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位元來解碼