热门问题
时间线
聊天
视角
x86
中央處理器指令集架構 来自维基百科,自由的百科全书
Remove ads
x86泛指一系列基于Intel 8086且向后兼容的中央处理器指令集架构。最早的8086处理器于1978年由Intel推出,为16位微处理器。
![]() |
该系列较早期的处理器名称是以数字来表示80x86。由于以“86”作为结尾,包括Intel 8086、80186、80286、80386以及80486,因此其架构被称为“x86”。由于数字并不能作为注册商标,因此Intel及其竞争者均在新一代处理器使用可注册的名称,如Pentium,来描述x86架构下的处理器产品。现时英特尔将其称为IA-32,全名为“Intel Architecture, 32-bit”,一般情形下指代32位元的架构。
Remove ads
历史
x86架构于1978年推出的Intel 8086中央处理器中首度出现,它是从Intel 8008处理器中发展而来的,而8008则是发展自Intel 4004的。8086在三年后为IBM PC所选用,之后x86便成为了个人电脑的标准平台,成为了历来最成功的CPU架构。
其他公司也有制造x86架构的处理器,计有Cyrix(现为威盛电子所收购)、NEC集团、IBM、IDT以及Transmeta。Intel以外最成功的制造商为AMD,其早先产品Athlon系列处理器的市场份额仅次于Intel Pentium。
8086是16位元处理器;直到1985年32位元的80386的开发,这个架构都维持是16位元。接著一系列的处理器表示了32位元架构的细微改进,推出了数种的扩充,直到2003年AMD对于这个架构发展了64位元的扩充,并命名为AMD64。后来英特尔也推出了与之兼容的处理器,并命名为Intel 64。两者一般被统称为x86-64或x64,开创了x86的64位时代。
值得注意的是英特尔早在1990年代就与惠普合作提出了一种用在安腾系列处理器中的独立的64位架构,这种架构被称为IA-64。IA-64是一种崭新的系统,和x86架构完全没有相似性;不应该把它与x86-64或x64弄混。
Remove ads
设计
x86架构是重要地可变指令长度的CISC(复杂指令集电脑,Complex Instruction Set Computer)。字组(word, 4位元组)长度的记忆体存取允许不对齐记忆体位址,字组是以低位字节在前的顺序储存在记忆体中。向后相容性及Intel量产制程经常领先业界一直都是在x86架构的发展背后一股驱动力量(设计的需要决定了这项因素而常常导致批评,尤其是来自对手处理器的拥护者和理论界,他们对于一个被广泛认为是落后设计的架构的持续成功感到不解)。但在较新的微架构中,x86处理器会将常用的x86指令尽全力以硬体线路执行,不常用者则转换为更像RISC的微指令再予执行,从而获得可与RISC比拟的超纯量性能,而仍然保持向后兼容。x86架构的处理器一共有四种执行模式,分别是真實模式,保护模式,系统管理模式以及虚拟V86模式。
在这篇简短的文章中出现的指令和暂存器助忆符号的名称,都在Intel文件中有所指定以及使用在Intel组译器(Assembler)中(和相容的,比如微软的MASM、Borland的TASM、CAD-UL的as386等等)。一个以Intel语法指定的指令"mov al, 30h"与AT&T语法的"movb $0x30, %al"相当,都是会被转译为两个字节的机器码"B0 30"(十六进制)。你可以发现在这段程式中的"mov"或"al",都是原来的Intel助忆符号。如果我们想要的话,我们可以写一个组译器由程式码move immediate byte hexadecimally encoded 30 into low half of the first register(移动立即值位元十六进制编码30到第一个暂存器的低半部位),来产生相同的机器码。然而,传统上组译器(Assembler)一直使用Intel的助忆符号。
x86组合语言会在x86组合语言文章中有更详细的讨论。
Remove ads
在真实模式下,记忆体的存取是被区段开来。为了得到最后20位元的记忆体位址,要将区段的位址往左移动4位元,并且加上偏移的位址。因此,真实模式下总共可以定址的空间是220位元组,或者是1MB,于1979年是相当让人印象深刻的象征。在真实模式下有两种定址模式:near和far。在far模式,区段跟偏移都需要被指定;在near模式,只需要偏移模式被指定,而记忆体区段是由适当的区段暂存器获得。以资料而言是使用DS暂存器,程式码是CS暂存器,堆叠是SS暂存器。举个例子,如果DS是A000h且SI是5677h,DS:SI会指向记忆体的绝对位址DS × 16 + SI = A5677h
在这种架构下,两对不同的区段/偏移可以指向一个相同的绝对位址。因此如果DS是A111h且SI是4567h,DS:SI会指向跟上一段相同的A5677h。除了异值同址重复性之外,这种架构无法同时一次拥有4个以上的区段。此外,CS、DS和SS是为了程式正确功能而必须的,因此仅仅只有ES可以被用来指向其他的地方。这种模式原本是为了与Intel 8085相容,导致程式设计师永无止尽的痛苦。
除了以上所说的,8086也拥有16-bit的32K(其变种 Intel 8088 是8-bit的64K)输入输出空间,以及一个由硬体支援的64K(一个区段)记忆体堆叠。只有words(2位元组)可以被推入到堆叠中。堆叠是由记忆体的上端往下成长,他的底端是由SS:SP指向。有256个中断,可以由硬体或是软体同时组成。中断是可以串连在一起,使用堆叠来储存返回被中断的程式位址。
Remove ads
Intel 80286可以在不改变任何东西下,支援8086的真实模式16位元软体,然而它也支援额外的工作模式称为保护模式,可以将可定址的实体记忆体扩充到16MB,可定址的虚拟记忆体最大到1GB。这是使用节区暂存器来储存在节区表格中的索引值。处理器中有两个这样的表格,分别为GDT和LDT,每一个可以储存最多8192个节区的描述子,每一个节区可以给予最大到64KB的记忆体存取。节区表格提供一个24位元的基底位址(base address),可以用此基底位址增加想要的偏移量来创造出一个绝对位址。此外,每一个节区可以被赋予四种权限等级中的一种(称为"rings")。
尽管这个推出的功能是一项进步,但是他们并没有被广泛地使用,因为保护模式的作业系统无法执行当时的真实模式软体。这样的能力只有在随后80386处理器的虚拟86模式中出现。
在同时,作业系统比如OS/2尝试使用类似乒乓的方法,让处理器在保护和真实模式间切换。这样都会让电脑变慢且不安全,像是在真实模式下的程式可以轻易地使电脑当机。OS/2也定义了限制性的程式设计规则允许"Family API"或"bound"程式可以在真实模式或保护模式下执行。然而这是给原本为保护模式下设计的程式有关,反之则不然。保护模式程式并不支援节区选择子和实体记忆体之间的关系。有时候会错误地相信在16位元保护模式下执行真实模式的程式,导致IBM必须选择使用Intel保留给BIOS的中断呼叫。事实上这类的程式使用任意的选择子数值和使用在上面提到的“节区运算”的方式有关。
这个问题也在Windows 3.x上出现。这个推出版本想要在16位元保护模式下执行程式,而先前的版本只能在真实模式下执行。理论上,如果Windows 1.x或2.x程式是写得“适当”且避免使用节区运算的方式,它就有可能在真实和保护模式两者下执行。Windows程式一般来说都会避免节区运算,这是因为Windows实作出软体的虚拟记忆体方式,及当程式不执行时候,搬移记忆体中的程式码和资料,所以操作绝对位址的方式是很危险的;当程式不执行时,被认为要保持记忆体区块的“handles”,这样的handles已经非常相当于保护模式的选择子。在保护模式下的Windows 3.0执行一个旧的程式,会触发一个警告对话盒,建议在真实模式下执行Windows(推测还是仍然可以使用扩充记忆体,可能是在80386机器用EMM386模拟,因此它并不被局限于640KB)或是从厂商那更新到新的版本。好的行为之程式可能可以使用特别的工具来避免这样的对话盒。不可能有些GUI程式在16位元保护模式下执行,且其它GUI程式在真实模式执行,可能是因为这会需要两个分开的环境且会依于前面所提到的处理器在两个模式间的乒乓效应。从Windows 3.1版开始,真实模式就消失了。
Remove ads
Intel 80386推出后,也许是到目前为止x86架构的最大跃进。除了需要值得注意的Intel 80386SX是32位元架构但仅只有24位元定址(和16位元资料汇流排)。除此之外其他架构都是32位元 - 所有的暂存器、指令集、输出输入空间和记忆体定址。为了能够在后者所说的功能工作,要使用32位元扩充的保护模式。然而不像286,386所有的区段可以使用32位元的偏移量,即使记忆体空间有使用区段,但也允许应用程式存取超过4GB空间而不需要区段的分隔。此外,32位元保护模式提供分页的支援,是一种让虚拟记忆体得以实现的机制。
没有新的通用暂存器被加入。所有16位元的暂存器除了区段暂存器外都扩充为32位元。Intel在暂存器的助记符号上加入“E”来表示(因此扩充的AX变成EAX,SI变成ESI,依此类推)。因为有更多的暂存器数量、指令、和运算单元,因此机器码的格式也被扩充。为了提供与先前的架构相容,包含执行码的区段可以被标示为16或是32位元的指令集。此外,特殊的前置符号也可以用来在16位元的区段包含32位元的指令码,反之亦然。
分页跟区段的记忆体存取是为了支援现在多工作业系统所必须要的。Linux、386BSD、Windows NT和Windows 95都是一开始为386所发展,因为它是第一颗提供可靠地程式分离记忆体空间的支援(每个程式拥有自己的定址空间)以及可以在必要的情况下打断他们程式的执行(使用ring,一种x86保护模式下权力分级的名称)。这种386的基本架构变成未来所有x86系列发展的基础。
Intel 80386数学辅助运算处理器也在整合到这个CPU之后的x86系列中,也就是Intel 80486。新的FPU可以帮助浮点数运算,对于科学计算和图形设计是非常重要。
Remove ads
Intel首次在80386SL将系统管理模式引入x86体系结构。
1996年Intel的MMX(AMD认为这是矩阵数学扩充Matrix Math Extensions的缩写,但大多数时候都被当成Multi-Media Extension,而Intel从来没有官方宣布过词源)技术出现。尽管这项新的科技得到广泛宣传,但它的精髓是非常简单的:MMX定义了八个64位元SIMD暂存器,与Intel Pentium处理器的FPU堆叠有相重叠。不幸的是,这些指令无法非常简单地对应到由原来C编译器所产生的指令码中。MMX也只局限于整数的运算。这项技术的缺点导致MMX在它早期的存在有轻微的影响。现今,MMX通常是用在某些2D影片应用程式中。
1997年AMD推出3DNow!,是对于MMX的SIMD的浮点指令增强(针对相同的MMX暂存器)。尽管这些也没有解决编译器的难题,但这项技术的推出符合了PC上的3D休闲娱乐应用程式之崛起。3D游戏开发者和3D绘图硬体制造商在AMD的AMD K6和Athlon系列处理器上,使用3DNow!来帮助增加他们的效能。微软后来也在其开发的Direct X7.0中加入针对3DNow!的最佳化,使当时的Athlon处理器在3D游戏效能上首次全面超过对手英特尔的Pentium 3处理器。
在1999年Intel推出SSE指令集,增加了八个新的128-bit暂存器(不跟其他的暂存器重叠使用)。这些指令类似于AMD的3DNow!,主要是增加浮点数运算的SIMD指令。
2001年英特尔推出SSE2指令集,增加了:
- 完整地补充了整数指令(与MMX相似)到原来的SSE暂存器。
- 64位元的SIMD浮点运算指令到原来的SSE暂存器。
第一个的增加导致MMX几乎是过时可以舍弃的,第二个则允许这些指令可以让传统的编译器现实地产生。
于2004年随著Pentium 4处理器的改版Prescott核心推出。SSE3增加特定的记忆体和thread-handling指令来提升Intel超执行绪的效能,在科学计算方面也有增强。
2007年1月,Intel公开发表使用其45奈米制程"Penryn"晶片家族的PC和伺服器。"Penryn"是这一系列依据英代尔Core微架构之笔记型电脑、桌上型电脑和伺服器晶片家族的代号,首次正式发布时共有16款处理器,除了一款Intel Core 2 Extreme QX9650是针对普通台式机市场外,其余的双核Xeon 5200系列和四核5400系列都是服务器处理器。基本上Penryn是继Merom之后的缩小版Core 2 Duo,再加上47条新的SSE4指令集等额外配备。SSE4指令集之首次发表时间为2006年9月的英特尔开发者论坛(IDF,Intel Developer Forum)。
另外,x86处理器制造厂商AMD也在该公司K10架构的Phenom处理器中,加入4条新的SSE4A指令集。注意,SSE4与SSE4A无法彼此兼容。
定址模式在16-bit的x86处理器:
32-bit定址模式在32-bit或64-bit的x86处理器:
64-bit定址模式在64-bit的x86处理器:
x86汇编指令lea,是Load Effective Address的缩写,其优势是:
- LEA指令具有单时钟周期,执行效率很高。
- 是CPU地址生成单元参与运算的,而不是ALU参与运算的,所以在流水线上不会与上下文的算术逻辑指令产生流水相关
- INTEL指令集中不存在很多RISC机器所具有的三操作数算术运算指令,比如像ARM的"add r0,r1,r2",而LEA指令恰好提供了同样的功能,以模拟“三元算术逻辑指令”。例如:lea ebx ,[eax+edx]
- 在汇编语言程序设计中,在需要取得一个变量地址时,使用lea是很方便的。而mov指令则常常出错,因为在微软MASM汇编语法中,label和variable是不同的:addr不可前向引用,offset则能;addr可以处理局部变量而 offset则不能。
自Intel 8086和8088起,有14个16位元暂存器。其中四个(AX, BX, CX, DX)是通用目的(尽管每个暂存器都有附加目的;举个例子:只有CX可以被用来当作loop(回圈)指令的计数器。)每个暂存器可以被当成两个分开的位元组存取(因此BX的高位元可以被当成BH,低位元则可以当成BL)。除了这些暂存器,还有四个区段暂存器(CS、DS、SS、ES)。他们用来产生记忆体的绝对位址。还有两个指标暂存器(SP是指向堆叠的底部,BP可以用来指向堆叠或记忆体的其它地方)。两个指标暂存器(SI和DI)可以用来指向阵列的内部。最后,有旗标暂存器(包含状态旗标比如进位、溢位、结果为零,等等)。以及IP是用来指向目前执行指令的位址。
自Intel 80386起,四个通用暂存器(EAX, EBX, ECX, EDX),它们较低的16位元分别与原本16位元的通用暂存器(AX, BX, CX, DX)重叠共用。指标暂存器(EIP, EBP, ESP, ESI, EDI)。区段暂存器除了原本的(CS、DS、SS、ES),另外新增(FS、GS),但是区段暂存器在32位元模式下改做为记忆体区块的选择子暂存器。旗标暂存器被扩展为32位元,较低的16位元与原本在16位元下的旗标暂存器重叠共用。
MMX暂存器(MM0~MM7),它们分别与浮点运算器〈FP0~FP7〉相重叠,所以MMX与浮点运算不可同时使用,必须透过切换选择要使用哪一种。
英特尔原本已经决定在64位元的世代推出新的架构IA-64技术的Itanium处理器产品线来接替取代x86,但它与x86的软体天生不相容,因此藉以各种形式来执行x86的软体,不过,效率十分低下,加之处理器本身和软体移植的成本难以控制,因此这个计画最终告吹。
AMD自行把32位元x86(或称为IA-32)拓展为64位元,并命名为x86-64或Hammer架构,而后更名为AMD64架构,并曾禁止使用之前的名字来称呼这一架构[1]。以这个技术为基础的第一个产品是单核心的Opteron和Athlon 64处理器家族。由于AMD的64位元处理器产品线首先进入市场,且微软也不愿意为英代尔代号为Yamhill的64位元版x86处理器开发第三个不同的64位元作业系统,英代尔被迫采纳AMD64架构且增加某些新的扩充到他们自己的产品,命名为EM64T架构(显然他们不想承认这些指令集是来自它的主要对手),EM64T后来被英代尔正式更名为Intel 64。
这个架构也被称为 64位元拓展架构,即x64,譬如四个通用暂存器(RAX, RBX, RCX, RDX)是由32位元的(EAX, EBX, ECX, EDX)64位元扩展而来,相应的还有 指标暂存器(RIP, RBP, RSP, RSI, RDI),以及增加八个通用暂存器(R8~R15)等等。 这些资源只可在x64处理器的64位元模式下使用,在用来支援x86软体的遗留模式和相容模式中是不可见的。
SIMD registers YMM0 - YMM15.
SIMD registers ZMM0 - ZMM31.
64 | 56 | 48 | 40 | 32 | 24 | 16 | 8 |
---|---|---|---|---|---|---|---|
R?X | |||||||
E?X | |||||||
?X | |||||||
?H | ?L |
64 | 56 | 48 | 40 | 32 | 24 | 16 | 8 |
---|---|---|---|---|---|---|---|
? | |||||||
?D | |||||||
?W | |||||||
?B |
16 | 8 |
---|---|
?S |
64 | 56 | 48 | 40 | 32 | 24 | 16 | 8 |
---|---|---|---|---|---|---|---|
R?P | |||||||
E?P | |||||||
?P | |||||||
?PL |
Note: The ?PL registers are only available in 64-bit mode.
64 | 56 | 48 | 40 | 32 | 24 | 16 | 8 |
---|---|---|---|---|---|---|---|
R?I | |||||||
E?I | |||||||
?I | |||||||
?IL |
Note: The ?IL registers are only available in 64-bit mode.
64 | 56 | 48 | 40 | 32 | 24 | 16 | 8 |
---|---|---|---|---|---|---|---|
RIP | |||||||
EIP | |||||||
IP |
Intel CPU的x86虚拟化技术有VT-x、VT-d等。AMD CPU的x86虚拟化技术有AMD-V等。
x86指令格式
x86与x86-64指令集的指令的格式为:
分为4组,每组用1个字节编码。每组在指令中至多指定1个前缀值。4组的顺序可以任意。
- 第1组锁与重复(Lock and repeat)
- 锁(LOCK)编码为:F0H。用于互斥访问共享内存的操作。
- 非零时重复(REPNE/REPNZ)编码为:F2H。用于字符串操作指令。
- 为零时重复(REP/REPE/REPZ)编码为:F3H。用于字符串操作指令。
- 第2组
- 段覆盖(Segment override):CS、SS、DS、ES、FS、GS的段覆盖前缀的编码分别是2EH、36H、3EH、26H、64H、65H.
- 分支提示(Branch hints),用于条件分支指令Jcc。提示分支不发生编码为2EH;提示分支发生编码为3EH。
- 第3组操作数长度覆盖(Operand-size override)编码为66H。用于在16位与32位操作数切换。
- 第4组地址长度覆盖(Address-size override)编码为67H.用于在16位与32位地址切换。
长度为1、2或3字节,此外ModR/M中还可能有3位。对于双字节指令码或三字节指令码,其中的第1个字节为0FH,用于与指令前缀区分。
许多指令的内存操作数需要使用ModR/M字节作为寻址模式说明符。其中的mod与r/m组合,共有32个值,表示8个寄存器与24种寻址模式。reg/opcode表示寄存器号或者额外的3位指令码,其具体含义依赖基本指令码。Mod与R/M的5位表示的第一操作数(源与目的操作数中寻址方式更复杂的那个操作数,指令码中的“方向位”direction bit(d)给出源或目的操作数哪个是第一操作数)的寻址方式如下:
某些ModR/M字节表示的寻找模式,需要SIB字节来补充寻址方式。scale表示比例系数;index表示变址寄存器号;base表示基址寄存器号。使用scale与index的5位定义比例变址寄存器如下:
3位base表示的基址寄存器号,定义如下:
在汇编程序设计中,一般把第1操作数的寻址方式总结为如下8种:
综合指令格式中的ModR/M与SIB两个字节的语义规定,指令的第1操作数的寻址方式可总结为4种物理实现:
- 立即数:表示在指令的“立即数”部分。包括了直接寻址,即立即数作为内存的地址。
- 寄存器操作数:Mod为11B,根据R/B部分的值、指令码、操作数长度属性,确定具体的寄存器号。
- 基址相对寻址:即[Reg+disp8或disp32]。包括了寄存器间接寻址。这种情况计算第1操作数地址时使用了1个寄存器。
- 基址加比例变址的相对寻址:即[BaseReg+IndexReg*scale+disp8或disp32]。这种情况计算第1操作数地址时使用了2个寄存器。
某些寻址方式需要给出位移值。有些指令需要给出立即数作为操作数。
生产商
目前仍在设计、生产并贩卖x86处理器的公司包括:
曾经设计、生产并贩卖x86处理器,但现已退出x86处理器市场的公司包括:
- Chips and Technologies
- Cyrix(被威盛电子收购)
- IBM
- IDT
- 国家半导体(NS,National Semiconductor)
- 日本电气(NEC)
- NexGen(被超微收购)
- Rise Technology(被矽统科技收购)
- 意法半导体
- 矽统科技(SiS)
- 德州仪器(Texas Instruments)
- 全美达(Transmeta)
- 联华电子(UMC)
- Montalvo
参考文献
参见
Wikiwand - on
Seamless Wikipedia browsing. On steroids.
Remove ads