ARM彙編程式設計基礎之二 流水線對PC值的影響

2021-08-11 06:20:40 字數 1625 閱讀 1825

cpu模型圖,源自素材庫/fig/flash/5.1.swf

從上圖中我們看到cpu內部有3個主要組成部分:指令暫存器,指令解碼器,指令執行單元(包括alu和通用暫存器組)。

cpu在執行1條指令的時候,主要有3個步驟:取指(將指令從記憶體或指令cache中取入指令暫存器);解碼(指令解碼器對指令暫存器中的指令進行解碼操作,從而辨識出該指令是要執行add,或是sub,或是其它操作,從而產生各種時序控制訊號);執行(指令執行單元根據解碼的結果進行運算並儲存結果)

現在我們假設一下:cpu序列執行程式(即:執行完1條指令後,再執行下一條指令);指令執行的3個步驟中每個步驟都耗時1秒;整個程式共10條指令。那麼,這個程式總的執行時間是多少呢?顯然,是30秒。但這個結果令我們非常不滿意,因為它太慢了。有沒有辦法讓它座上京津高鐵提速3倍呢?當然有!仔細觀察上圖,我們發現:取指階段占用的cpu硬體是指令通路和指令暫存器;解碼階段占用的cpu硬體是指令解碼器;執行階段占用的cpu硬體是指令執行單元和資料通路。三者占用的cpu硬體完全不同,這樣就使得如下的操作得以進行:在對第1條指令進行解碼的時候,可以同時對第2條指令進行取指操作;在對第1條指令進行執行的時候,可以同時對第2條指令進行解碼操作,對第3條指令進行取指操作。顯然,這樣就可以將該程式的執行總時間從30秒縮減為12秒,提速近3倍。上面所述並行執行指令的方式就被稱為流水線操作。可見:流水線操作的本質是利用指令執行的不同階段使用的cpu硬體互不相同,併發的執行多條指令,從而提高時間效率。

流水線的引入,的確提高了cpu執行指令的時間效率,但卻為我們的匯程式設計序編寫引入了新的問題。請看下面的分析:

暫存器pc的值是即將被取指的指令的位址,正常情況下,在該條指令被取入cpu後執行期間,pc的值保持不變,在該條指令執行完成的時間點上,硬體會自動將pc的值增加乙個單位的大小,這樣pc就指向了下一條將被取指和執行的指令。而在引入流水線後,pc值的情況發生了變化,假定第1條指令的記憶體位址為x,則在時刻t,pc的值變為x,並在時刻t至時刻t+1期間維持不變;在時刻t+1,pc的值變為x+1個單位,並在時刻t+1至時刻t+2期間維持不變;在時刻t+2,pc的值變為x+2個單位,並在時刻t+2至時刻t+3期間維持不變;在時刻t+3,pc的值將變為x+3個單位。由此可見,在第1條指令的執行階段,pc的值不再是該指令在記憶體中的位置,而是該指令在記憶體中的位置+2個單元。對於arm指令集而言,每條指令的長度為32bit,佔4byte,所以1條指令在記憶體中需要4byte儲存。因此,我們的結論是:

指令執行時,pc的值 = 當前正在執行指令在記憶體中的位址 + 8

請牢記以上結論。雖然目前我們並不明白這個結論有何作用,但在後續的課程中,特別是通過檢視反彙編**的方式理解偽指令和編譯器行為的時候,這個結論將會很有幫助。

最後說明一點:其實arm現在的cpu的流水線級數早已經突破了3級。但我仍然以3級流水線來進行講解,是因為:1、較之多級流水線,3級流水線最簡單,因此也最便於初學者理解;2、雖然存在多種級別的流水線,但arm出於統一和前後相容的考慮,pc的值 = 當前正在執行指令在記憶體中的位址 + 8

這個結論在所有的流水線級別上都是相同的。作為程式設計人員而言,我們只需要知道這個結論即可。

ARM體系結構(二) 流水線

一 流水線的概念與原理 處理器按照一系列步驟來執行每一條指令,典型的步驟如下 從儲存器讀取指令 fetch 解碼 以鑑別它屬於哪一種指令 dec 從指令中提取指令的運算元 這些運算元往往存在於暫存器中 reg 如將運算元進行組合以得到結果或儲存器位址 alu 如果需要,則訪問儲存器以儲存資料 mem...

2 ARM 流水線 彙編

3級流水線 取指 解碼 執行 arm9 5級流水線 1.f add 0.d add f sub 1.e add d sub f orr f取指 d解碼e執行 1.add 0.sub add1.ldrsub 2.and ldr3.orrand 4.stops 指令可以通過加乙個s來設定cpsr的標誌位...

golang設計模式(二)流水線模式

產生資料 func makedata min,max int int return data 把輸入的資料通過通道傳遞出去 func echo nums int chan int close out return out func isprime v int b bool return true f...