2017年6月16日 星期五

淺談古代CPU:32bit與4G?(1)

在 32 位元 CPU 中,如果單純以 CPU 做記憶體定址時,4GiB 為其極限。 」這是某個網站對新處理器「深入分析」文章中出現的敘述。

這句話倒底對不對呢?這就是以下要討論的,其實這些都是很基本的計算機結構常識;首先我們從定義開始:什麼是CPU的「bit數」?CPU的「記憶體定址」又是什麼?

雖然幾十年前對這個定義有不少爭論,不過現在一般來說,一個CPU架構裡的「bit數」,通常從程式觀點來看,指的是「整數暫存器的bit數」,也就是一個整數指令能夠運算的最大位元長度,舉例來說,以前8088/8086和286,整數暫存器最大就是16位元。所以是16位元處理器,80386/486暫存器可以到32位元,所以是32位元處理器,沒有任何問題。

可是「記憶體定址」是另外一回事, 什麼是「記憶體定址」?如果把裡裡外外所有繁瑣的細節都省略,當作一個抽象的個體來看,CPU就是一個可以輸入或輸出(為了方便,以下把輸出和輸入簡稱為讀寫,讀是輸入,寫是輸出)資料的黑盒子,而這個黑盒子從「哪裡」讀寫資料?這個「哪裡」就是記憶體,當然這是個抽象的描述,有些人可能會爭辯還有I/O等等,但是對程式或CPU來說那還是一種「記憶體」。

CPU讀寫資料的大小是有限的,更進一步來說,CPU能夠「從多大的範圍讀寫資料」也是有限制的,回到剛剛的黑盒子,CPU如何決定從「哪裡」存取資料?答案是:CPU會先寫出一串資料,這串資料稱為「位址(address)」,這串資料是有大小限制的,如果是32bit,表示CPU只能從2^32這麼大的範圍內選一段讀寫,一段的基本單位通常是byte(當然,也會有例外),古早的CPU通常會特別有一組訊號線來表示這串資料,這組訊號叫「定址線」,所以32條定址線,基本單位byte,表示這顆CPU只能從2^32 = 4 giga byte = 4GiB大小的空間中讀寫資料,也就是說記憶體定址空間是 4 GiB。

所以32位元CPU的記憶體定址就是4 GiB?

回答這個問題之前,請先容我反問一下,如果上面的敘述成立,請問16位元的CPU,記憶體定址應該是多大?2^16 = 64K byte?

別傻了,就拿剛剛舉過的例子,Intel 8088/8086有20條定址線,80286有24條定址線,所以一個是1MB,一個是16MB,隨便哪一個都超過64K。

問題出在哪裡?問題在於,整數暫存器的大小,跟記憶體定址線的大小,這兩個本來就是互相獨立的參數,上面的8086和286就是個例子,只是x86進入32位元時代後,剛好386、486到Pentium都是位元數等於定址線數,也就是暫存器32位元,定址線也剛好是32位元,如此而已。

問題又來了,如果一顆CPU的整數運算大小比定址線還小,那程式怎麼存取記憶體?這也是個好問題,答案是:看指令集怎麼規定;拿8086來說,它有幾個特別的暫存器,牽涉到記憶體存取的指令時,CPU真正計算位址的方法是:把這些暫存器的值,跟你的指令裡面指定位址的值拿來一起計算,最後產生的才是20位元的記憶體位址;到了286時比較複雜,某個暫存器會指到某張表,表裡面的數字跟暫存器的數字一起計算等等等等,其他處理器可能有其他方法,但是總而言之言而總之,有太多太多方法可以讓程式在存取記憶體時,可以不用受限於一個整數暫存器的大小。

所以一切的謎底都解開了嗎?也不盡然如此,在386之前,這種不太直觀的記憶體存取機制,對程式設計師來說其實很麻煩,所以從386開始,暫存器和定址線就一樣是32位元,程式可以擺脫那些麻煩的機制,就這樣過了很長的一段太平日子,因為太平日子過太久,所以大家都忘記了過去那段苦日子,以為32位元就等於4G記憶體定址。

不過太平日子其實也是會過去的,故事還沒完,我們下期待續。


沒有留言: