(已更正) 這個問題包括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中的"譯碼電路".