CPU 的指令集存放在什麼地方?


(已更正) 這個問題包括CPU的硬體結構和彙編語言的範疇. 這裡梳理一下.

首先, 題主"李建國"自問自答的部分說的是正確的, CPU的指令集是軟體與CPU這兩個層級之間的介面, 而CPU自己, 就是對於這一套CPU指令集的"實例化".

無論處於上層的軟體多麼的高級, 想要在CPU執行, 就必須被翻譯成"機器碼", 翻譯這個工作由編譯器來執行. 編譯器在這個過程中, 要經過"編譯", "彙編", "鏈接"幾個步驟, 最後生成"可執行文件". 可執行文件中保存的是二進位機器碼. 這串機器碼可以直接被CPU讀取和執行.

軟體意義上, "指令集"實際上是一個規範, 規範彙編的文件格式.

以下為一條x86彙編代碼:

mov word ptr es:[eax + ecx * 8 + 0x11223344], 0x12345678

這裡可以體現出指令集的格式限制:

1. 可以使用mov指令, 但它只能有2個操作數.

2. 它的操作數長度是16 (word), 不要看到後面0x12345678就認為是32位操作數.

3. 它帶有段超越前綴, 這裡使用了es, 還可以使用ds, cs, ss, fs, gs. 但是只能用這幾個.

4. 第一個操作數是一個內存地址, 第二個是立即數. 但是, 這個內存地址不能亂寫, 寫成[eax+ecx*10+0x11223344]就錯了.

實際上, 一條彙編指令與一段機器碼是一一對應的. 上面這段匯, 可以被x86編譯器翻譯成幾乎唯一的一段機器碼:

26 66 c7 84 c8 44 33 22 11 78 56

上面提到的1,2,3,4點如果有一個弄錯, 這一步就會失敗.

可以看出來, 指令集的作用, 就是告訴程序員/編譯器, 彙編一定要有格式. 支持什麼指令, 指令帶什麼限制條件, 用什麼操作數, 用什麼地址, 都是指令集規範的內容, 要是寫錯了, 就無法翻譯成機器碼.

指令集規範彙編, 彙編可以翻譯成機器碼, 機器碼告訴CPU每個周期去做什麼. 因此, CPU指令集是描述CPU能實現什麼功能的一個集合, 就是描述"CPU能使用哪些機器碼"的集合".

那機器碼進入到CPU後又做什麼呢?

=====================編譯器和CPU的分界線========================

需要被執行的機器碼先要被OS調度到內存之中, 程序執行時, 機器碼依次經過了Memory--Cache--CPU fetch, 進入CPU流水線, 接著就要對它進行解碼了, 解碼工作生成的象是CPU內部數據格式, 微碼(或者類似的格式, 這個格式不同的廠商會自己設計).

這個過程畫成圖就是:

軟體層: 彙編語言

------------------------------------------------------------------------

介面: 彙編語言所對應的機器碼

------------------------------------------------------------------------

硬體層: CPU使用內部數據結構進行運算

如果機器碼代表的功能是在指令集規範內的, 這條機器碼就可以生產微碼, 並在CPU內正常流動. 假設機器碼是錯誤的, 是不可以通過CPU的解碼階段的, 控制電路一定會報錯. 這種情況反映在Windows里往往都是藍屏, 因為CPU無法繼續執行, 它連下一條指令在哪都不知道.

那麼指令集在CPU里就代表: 只有CPU指令集範圍內的指令可以被成功的解碼, 並送往CPU流水線後端去執行.

和常規的想法不一樣, CPU不需要任何形式的存儲介質去存儲指令集, 因為"解碼"這個步驟就是在對指令集里規範的機器碼做解碼. 硬體上, 解碼這件事需要龐大數目的邏輯門陣列來實現.

跳出格式這個圈子來看待這個問題. 可以說, CPU執行單元的能力, 決定了指令集的範圍. 比如, CPU的執行單元有能力執行16位加法, 32位加法, 64位加法, 那麼指令集里一般就會有ADD 16, ADD 32, ADD 64這樣的表達方式. 如果CPU的執行單元沒有電路執行AVX指令, 那麼指令集里一般就沒有VINSERTF128這樣的指令供使用. 所以, 強有力的執行單元能夠提供更多的指令集.

再來看"CPU指令集在哪裡"這個問題, 回答是, CPU本身就是CPU指令集. 指令集規定CPU可以做什麼事, CPU就是具體做這件事的工具. 如果一定要指定一個狹義的CPU指令集的存放位置. 那就是CPU中的"解碼電路".


看到這些答案我有點想笑

指令集不是應該存在那一本本厚厚的manual裡面嗎。。。。。


是,這個解釋起來有點長。Be patient

現代的CPU沒拆過,我只在計算機組成原理實驗課上用VHDL在某個實驗平台上做過一個模擬的CPU。舉個例子你可能比較好理解。

比如我們設計一套指令集,其中肯定有條加法指令。比如Add R1 R2 。我們可以認為這條指令的意思是計算寄存器R1中的內容和R2的和,然後把結果存到R1寄存器中。

那麼經過編譯後這條指令會變成二進位,比如010100010010 。這條二進位指令一共12位。明顯可以分為三大部分。最前面的0101表示這是條加法指令,後面0001說的是第一個操作數是寄存器1,最後0010說的是第二個數就是寄存器2(其實實際沒有這麼簡單的指令,至少應該區分操作數是寄存器還是直接的數據,但為了把這說的更容易理解作了簡化)。我們可以通過十二根導線把這條指令輸入一個CPU中。導線通電就是1,不通電就是0 。為了敘述方便我們從左到右用A0-A11給這12根導線編上號。

然後計算機會分析這條指令。步驟如下:

  1. 最開始的兩根導線A0和A1,第一根有電第二根沒電,就能知道這是一條運算指令(而非存儲器操作或者跳轉等指令)。那麼指令將被送入邏輯運算單元(ALU)去進行計算。其實很簡單。只要這兩根線控制接下來那部分電路開關即可。
  2. 接下來的A2和A3,01表示加法,那麼就走加法運算那部分電路,關閉減法等運算電路。
  3. A4-A7將被送入寄存器電路,從中讀取寄存器保存的值。送到ALU的第一個數據介面電路上。
  4. 後面的A8-A11同樣被送入寄存器選擇電路,接通R2寄存器,然後R2就把值送出來,放到ALU的第二個數據介面上。
  5. ALU開始運算,把兩個介面電路上的數據加起來,然後輸出。
  6. 最後結果又被送回R1。

基本上簡單的運算計算機就是這麼操作的。他其實不知道你那些指令都是什麼意思。具體的指令編程機器碼後就會變成數字電路的開關信號。其中某幾段會作為控制信號,控制其他部分的數據走不同的電路以執行運算。他沒有一個地方保存著如何翻譯這些機器碼的字典,所有機器碼的意義都被體現在整個電路的設計中了。

當然,從彙編到機器碼這步是彙編程序翻譯的。彙編程序當然知道某條指令要翻譯成什麼樣的機器碼。


相信你閱讀完ISA和Microarchitecture的wiki頁面就會得出自己的結論:

Instruction set

Microarchitecture


評分最高的(@Cascade )回答的應該是指令是如何執行的,對題主提的指令集存在CPU哪裡,我的回答是:

1. 指令集是在設計CPU時規定的,指令集規定了有哪些CPU能夠「一條條」執行的「指令」是合法的。

2. 指令集是一個集合,它的功能性體現在每條能夠執行的「指令」上面。涉及到具體指令後,就涉及到誰是「操作對象」,和「如何找到操作對象」,「對操作對象進行什麼操作」,這些問題上來。

3. 指令的功能是通過CPU中功能邏輯電路來實現的,之前的「指令設計」決定了如何進行「邏輯電路設計」。而相同的指令可以採取不同的邏輯電路設計。

4. 因為「指令集」本身沒有功能性,所以在CPU中你不能找到「指令集」這個實體,但是指令集中的指令與CPU的內部晶體管組成的邏輯電路是等價的(除了指令部分還有中斷,外設等這些暫不考慮),那麼非要化等價的話,就是實現指令集中各指令的整體晶體管邏輯電路。

5. 如果你非要在沒給出指令集的CPU來找到它的指令集的話,你可以通過修改PC指向的下一條指令的內容,並觀察內存及各寄存器的變化,來試探每條指令編碼的功能(這顯然沒有什麼實際價值)(你可以用這種方法去理解指令的功能)。

入門小菜,歡迎大家批評指正。我會及時修改。


指令集系統不是存放在cpu中的,它是被整合到操作系統內核最底層的hal(硬體抽象層)中的,屬於操作系統與硬體之間(宏指令與微指令)的介面。它向操作系統定義了CPU最基本的功能,而操作系統執行某個任務的實質就是在調用這些功能。這就好比算一道複雜的數學題,不管題有多複雜解題的每一步都要遵循最基礎的定理公式,而指令集就是計算機解題所需的定理公式。指令集系統的統一解決了不同品牌不同型號的CPU對操作系統與應用軟體兼容性的問題,有了統一的指令集系統不管是I或A的CPU二者電路設計與微指令如何不同,對於windows或linux都能很好地兼容,用戶買一款CPU就能使用各種軟體,程序員編寫軟體也不用研究每款CPU中的具體電路與微指令,只需調用通用的指令集即可。

PS:這個問題是我提的,但上面的回答確實不靠譜,查了相關的資料終於有了靠譜的答案。


存放於CPU的邏輯電路中。


cpu取指令過後,將指令(一個由0,1構成的字元串)輸入解碼電路,解碼電路根據指令集的描述,生成各種控制信號。指令集可以看作是cpu行為的描述,而cpu裡面的電路是指令集的實現。指令集不會被「存儲」在某處


CPU是某個特定的指令集在硬體上的實現。它本身並不知道為什麼要這麼做,也不知道它在做什麼,它存在的終極目的就是「實現」這個指令集。


其實指令集就是各種電路,指令集要執行還是要轉換成二進位,而二進位就是電路的狀態,即是高低電平的抽象說法,也就是說整個電腦其實就是電路,而電路的高低電平我們用二進位抽象講述。


CPU指令集是一種規範,並不「存放」在什麼地方。

我們知道,CPU執行的時候,執行的是機器碼。

總結起來:(彙編 --&> 機器碼 的這種「翻譯規則」) + (CPU執行機器碼的邏輯電路) = 指令集。

我舉個例子,我們知道,現在指令集有CISC(複雜指令集)和RISC(精簡指令集)。Windows只能跑在CISC上,而Linux即可以跑CISC,也可以跑RISC。

CISC架構的CPU上,加法運算指令:

MUL ADDRA, ADDRB

這條指令可以將ADDRA和ADDRB中的數相乘並將結果儲存在ADDRA中。其中將ADDRA, ADDRB中的數據讀入寄存器,相乘和將結果寫回內存的操作全部依賴於CPU中設計的邏輯來實現。這種架構會增加CPU結構的複雜性和對CPU工藝的要求,但對於編譯器的開發十分有利。比如上面的例子,C程序中的a*=b就可以直接編譯為一條乘法指令。

RISC架構要求軟體來指定各個操作步驟。上面的例子如果要在RISC架構上實現,將ADDRA, ADDRB中的數據讀入寄存器,相乘和將結果寫回內存的操作都必須由軟體來實現,即:

MOV A, ADDRA;

MOV B, ADDRB;

MUL A, B;

STR ADDRA, A。

這種架構可以降低CPU的複雜性以及允許在同樣的工藝水平下生產出功能更強大的CPU,但對於編譯器的設計有更高的要求。

所以,通過比較CISC和RISC的不同,我們能看出CPU指令集就是上面總結的:

(彙編 --&> 機器碼 的這種「翻譯規則」) + (CPU執行機器碼的邏輯電路) = 指令集。


指令集根本就是電路結構,不同的電路結構就是不同的指令集,已經不屬於軟體的範圍了。


晶元的開關邏輯中。指令集對應晶元中的二進位。


突然間想到,我們國內沒有定義這個指令集的衝動嗎?悲觀的講,如果沒有的話,以後我們只是在用一個黑盒子而已。好可怕


根據我對《微處理器系統結構與嵌入式系統設計》的粗略理解,指令集是一個整體概念,包括指令功能、指令格式和定址方式。CPU內部有專門的指令寄存器,而指令涉及到的數據可能在寄存器里,也可能在別的存儲器里。

所以@狼大人 說的運算單元似乎不太準確。


你們知道指令的原始出處嗎,指令是帶物理性的明白了嗎。去看看計算機簡史吧。


贊同樓上大部分的回答,下面是我從網上摘抄的:

首先,建議你把基本概念弄清楚了再來表達你的準確想法,不然旁人很難幫上你的忙。

一般我們指的解碼器是從一種數據表示形式轉換為另一數據表示形式的器件。而指令的解析未必就是你說到的解碼器可以解決的,而是諸如乘法器、全加法器或者更為基本的觸發器或邏輯電路直接構成,並不屬於解碼器的子集。

根據前面對解碼器的解釋,指令解碼器也是同樣的道理,你可以把它理解為普通的地址解碼器,比如3-8解碼器(或8-256解碼器),其實就是把3(或8)條數據線上表示的信息轉換為8(或256)條數據線來表示的一種形式,(即解碼),然後利用該信息表示的獨立性和唯一性對功能電路作出恰當的選擇(比如選擇當前執行的指令的部件為加法處理單元)。在這個意義上來說它就是一個普通的地址解碼器,用於選中哪個功能單元來處理當下的操作數。 一條指令只需一個地址,而非你說的多少種解碼器,一個8位指令解碼器就可以支持256條指令,一個16位指令解碼器可達到最多65536條指令。


**指令集就相當於少林寺的藏經閣,裡邊藏著一整套武功心法(指令),而CPU就相當於少林寺中最牛叉的達摩祖師,學會了藏經閣中所有的武功心法。這個時候,你請達摩祖師演示一套武功,他就會給你演示一遍。

也就是你寫了一個命令,cpu就能執行相應的命令。cpu能實現所有的指令集,但是到底執行哪一條,就需要你編寫程序,然後經過編譯以後告訴cpu,演示哪套武功才行。


推薦閱讀:

俠客風雲傳到現在仍不支持6代CPU的核顯,很多新機型都無法玩,是遊戲商的問題還是intel的問題呢?
2級緩存12兆和3級緩存8兆的cpu哪個性價比好?
E3大法到底好不好?

TAG:中央處理器CPU |