(已更正) 这个问题包括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中的"译码电路".