Intel 8086
8086是由英特爾公司於1976年开始設計,1978年年中发布的第一款16位微處理器,同时也是为x86架構系列之開端。随后于1979年,又推出了Intel 8088,它在芯片的外部接口使用8位数据总线,成为8086的一个低成本的简化产品。而最初的IBM PC使用8088微处理器。
目录 |
历史 [编辑]
背景 [编辑]
1972年,Intel发布了8008微处理器——世界上第一款8位微处理器。8008微处理器有18个引脚,其中地址总线使用了14个引脚,并且与8位数据总线复用引脚。指令集源自是Datapoint公司为计算机的CRT-键盘终端设计的但相当通用的指令集。当时英特尔还是一家生产DRAM为主业的公司,缺乏这方面的技术储备。
1974年,Intel发布了8080微处理器,被公认是第一款真正可用的微处理器。8080的芯片封装采用40个引脚,其中8个数据总线引脚、16个地址总线引脚都是专用的,因此数据总线与地址总线可以并行工作。8080的扩展后的指令集在源代码级别上向前兼容8008指令集。
1975年,Intel发布了第三款8位微处理器——8085。采用了新的制造工艺,简化了输入电压引脚的数量。同一时期还有Motorola 6800 (1974), Microchip PIC16X (1975), MOS Technology 6502 (1975), Zilog Z80 (1976), and Motorola 6809 (1978), 等8位微处理器。在8位微处理器市场竞争中Z80最为成功。
第一种x86设计 [编辑]
8086项目起始于1976年5月,是英特尔公司当时更为看重的16位的iAPX 432微处理器的备份项目。8086一方面要与Motorola, Zilog, National Semiconductor等公司的16位、32位微处理器竞争市场份额,另一方面也是对Zilog Z80在8位微处理器市场上的成功的回击。由于采用了与8085微处理器近似的微体系结构与物理实现工艺,8086项目进展相当快。
8086微处理器被设计为在汇编源程序上向前兼容8008, 8080, 8085等微处理器。指令集与编程模式是基于8080微处理器,但指令集做了扩展以完全支持16位计算。
新增加的指令包括:完全支持有符号整数、段基址+偏移量寻址、类似于Z80的自重复操作、直接支持嵌套的ALGOL类语言如Pascal或PL/M、微码实现的乘法除法指令、以及更好支持与协处理器(8087或8089)和多处理器系统的总线结构.
第一版的指令集与高层的体系结构的设计仅用了3个月。在没有CAD工具的时代,4名工程师与12名布线绘图员平行工作,用了2年多的时间才把8086的高层设计实现为可运行测试的产品。这在当时算是很快的研发速度。
8086是微码与逻辑电路的混合实现,使用了大约20,000个晶体管 (算上所有的ROM与可编程逻辑阵列为29,000个晶体管). 芯片面积为33 mm² ,制造工艺为3.2 μm.
8086体系结构由Stephen P. Morse设计,并在最后定案时得到Bruce Ravenel (8087体系结构设计者)的帮助。逻辑设计者是以Jim McKevitt与John Bayliss为首的硬件开发工程师团队。项目经理William Pohlman. 迄今8086的指令集仍然是PC机与服务器的基本指令集。
细节 [编辑]
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| The 8086 registers | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
总线与操作 [编辑]
所有的内部寄存器、内部及外部数据总线都是16位宽,因此是完全的16位微处理器。20位外部地址总线,因此物理寻址空间为1MiB (即220 = 1,048,576). 由于内部寄存器都是16位,对1M地址空间寻址时采取了段寻址方式。8086的封装采用40引脚的双列直插(dual in-line),数据总线与地址总线复用了前16个引脚。16位的I/O地址,因此独立的I/O寻址空间为16KiB (即216 = 65,536). 由于8086内部的地址寄存器是16 位宽,因而最大线性寻址空间为64 KiB. 使用超过64 KiB内存空间的程序设计时,需要调整段寄存器(segment registers)。直到32位的80386出现之前,8086的这种段寻址相当不便.
8086芯片封装的8个控制引脚在min或max下有不同功能。"min"模式是使用单处理器的小型计算机系统,"max"模式是使用多处理器的中到大型计算机系统。
寄存器与指令 [编辑]
8086有8个16比特的寄存器,包括栈寄存器SP与BP,但不包括指令寄存器IP、控制寄存器FLAGS以及四个段寄存器。AX, BX, CX, DX, 这四个寄存器可以按照字节访问;但BP, SI, DI, SP, 这四个地址寄存器只能按照16位宽访问。
8086以8080和8085(它與8080有汇编語言上的原始碼相容性)的設計為基礎,擁有類似的暫存器集合,但是擴充為16位元。总线接口單元(Bus Interface Unit)透過6位元組預存(prefetch)的貯列(queue)将指令送给執行單元(Execution Unit),所以取指令和執行是同步的-一種流水线的原始形式(8086指令長度變化從1到6位元組)。
8086有四個完全一样的16位元暫存器,但也能够當作八個8位元暫存器來存取;以及四個16位元索引暫存器(包含堆栈索引)。数据暫存器通常由指令隱含地使用,針對暫存值需要複雜的暫存器配置。它提供64K 8位元的輸出輸入(或32K 16位元)埠,以及固定的向量中斷。大部分的指令只能夠存取一個記憶體位址,所以其中一個運算子必須是一個暫存器。運算結果會儲存在運算子中的一個。
8086有4個記憶體區段(segment)暫存器,可以通过索引暫存器來設定。區段暫存器可以讓CPU一种当时是全新的方式存取多达1MB之記憶體。在現今有區段的處理器中,8086把區段暫存器左移4位元然後把它加上去寻址。这通常被認為是一個不太好的設計,因為这么做會讓各區段有重疊。儘管這樣對于汇编語言而言会显得有用——因为可以充分控制區段,但同时却使高级語言中的指针(像是C程式語言)使用變得困難。它降低了指针的高效率,且有可能產生兩個指向同一個地方的指標擁有不同的位址。更壞的是,這種方式產生要讓記憶體擴充到大於1MB的困難。而80286的寻址方式改變讓記憶體擴充較有效率。
由于8位机(如Intel 8008)时代沿袭下来的紧凑编码,大多数指令虽然有两个源操作数(operands)及一个输出结果,但单条指令至多使用两个地址,因此运算结果被存入一个源操作数中。且最多只能有一个内存操作数,另外的操作数是寄存器或立即数。内存操作数也可以用于存储指令的输出结果。8位微处理器的指令集不能把输出结果直接保存在内存操作数中,因此8086指令集的如此设计大大提高了代码密度(code density)。
相比与8080或8085,8086有更强的寄存器通用性,但比起典型的小型计算机来说仍有很大不如。8086的某些指令隐式使用某些寄存器。比起更为规则的16- 或32-位处理器如 PDP-11, VAX, 68000, 等等,8086的寄存器分配特性使得编译器的工作更为复杂; 另一方面,比起半现代化的但广为使用的8位微处理器如6502, 6809, 或8085, 编译器生成代码就容易太多了.
8086有64 KiB的字宽为8位的(或32K个宽度为16位的) I/O寻址空间.
栈的长度最大为64 KB (一个段) ,8086硬件支持栈顶由高地址向低地址生长。入栈、弹栈的数据单元长度为2字节。栈顶位置由寄存器的组合SS:SP给出.
共有256 个中断, 包括硬件中断与软中断。中断可以嵌套,使用栈来保存中断返回地址。
8086增加了一些8080与8085所没有的新指令,用于更好地支持Pascal与PL/M的高级程序设计特性; 如push mem-op, ret size, (其它一些指令如push immed and enter, 在随后的80186, 80286, and 80386中陆续增加.)
标志寄存器 [编辑]
8086有一个16位宽的标志寄存器FLAGS. 其中9个比特是被使用的,另外7个比特保留未用。具体是:进位标志CF、奇偶标志PF、辅助标志AF、为零标志ZF、符号标志SF、陷阱标志TF、中断标志IF、方向标志DF、溢出标志OF。
内存分段 [编辑]
在Intel的8位、16位处理器中,由于寄存器的宽度为8或16比特,而地址总线的宽度一般是要大于寄存器的宽度,所以为了能访问整个地址空间,需要采取特殊的寻址计算——分段寻址。从80386开始的32位微处理器,地址总线宽度也是32比特,可以视作扁平(flat)地址空间,不再需要分段寻址。
8086的分段寻址,是指一个物理地址由段地址(segment selector)与偏移量(offset)两部分组成,长度各是16比特。其中段地址左移4位(即乘以16)与偏移量相加即为物理地址。例如,06EFh:1234h,表示段地址为06EFh, 偏移量为1234h, 物理地址为06EF0h + 1234h = 08124h。在计算物理地址时如果发生上溢出,8086处理器舍弃进位。例如,FFFFh:0010h所对应的物理地址为00000h.
一个20位的物理地址对应着4096个不同的"段地址:偏移量"的组合。这是因为,偏移量的最低4位对应于物理地址的最低四位,而偏移量的高12位共有4096个取值。
段地址所对应的物理地址的粒度是16字节(=24),称之为paragraph。
段地址确定后,偏移量的取值最多为64KiB(=65536),这就是分段寻址的最大的线性地址空间。实际上在8086处理器上,操作系统分配的线性地址空间可以是不大于64KiB的任意数量。程序可以自由访问整个物理内存空间,操作系统没有任何权限限制或监管(supervision)。
8086处理器有20根地址总线引脚(pins),因此物理内存空间最大为220=1MiB=1,048,576字节。这还包括了IO内存。因此使用8086处理器的计算机的主存的容量少于1MiB,最常见的主存容量是640KiB。
由于X86指令集的向后兼容原则,计算物理地址时,段地址左移4位被所有后继支持实模式的X86处理器所继承。80286是使用24位宽地址总线的16位微处理器,如果要在整个224=16MiB物理存储空间寻址,就必须采用其它方式,即保护模式寻址,这时16位的段地址是指向段描述符表(segment descriptors table)的一个包含24位基地址的条目,基地址加上16位偏移量即为24位的物理地址。
在8086上运行的编译器,一般支持两种C语言的指针:近指针(near)与远指针(far)。近指针是16位的地址偏移值,隐式与程序的代码段地址或数据段地址结合使用以确定物理地址。远指针是32位的“段地址:偏置量”成对出现,用以确定20位的物理地址。某些编译器支持“巨指针”(huge),类似于远指针。但巨指针的地址运算是线性20位;而远指针的地址运算在16位偏移值溢出时不影响段地址部分,因此远指针的线性部分是16位。
为了避免对大量的指针、数据结构、函数指出是“近”还是“远”,编译器提供了内存模式(memory model)给出了缺省的内存访问方式:
- 微模式tiny 数据段代码段共用不超过64K内存空间,编译为.com可执行文件;
- 小模式small 数据段、代码段各用最多64K内存共空间;
- 紧凑模式compact 数据段> 64K;
- 中模式medium 代码段> 64K;
- 大模式large 代码段数据段都 > 64K;
- 巨模式huge 单个数组> 64K。
预编译库对不同的内存模式要分别编译为相应版本。
移植老的程序 [编辑]
8位机上的程序可以不考虑段地址直接以.com可执行文件以“微模式”在8086上运行。这是当时8086与MS-DOS作为新平台取得市场成功的关键原因——大量已存的CP/M应用程序能很快得到利用。
性能 [编辑]
外部总线作为数据与地址的复用,降低了CPU的性能。取16比特或8比特数据需要4个时钟周期。指令的长度为1-6个字节,取指令与执行是并发完成的。CPU内的总线界面单元把取到的指令保存在6字节的预取队列中。
| instruction | register-register | register immediate | register-memory | memory-register | memory-immediate |
|---|---|---|---|---|---|
| mov | 2 | 4 | 8+EA | 9+EA | 10+EA |
| ALU | 3 | 4 | 9+EA, | 16+EA, | 17+EA |
| jump | register => 11 ; label => 15 ; condition,label => 16 | ||||
| integer multiply | 70~160 (depending on operand data as well as size) plus EA | ||||
| signed integer divide | 80~190 (depending on operand data as well as size) plus EA | ||||
- EA = 计算有效地址的时间, 5 到 12 周期.
- 用时为最好的情形, 依赖于预取状态, 指令对齐, 及其它因素.
8086涉及内存访问的指令,包括跳转(jump)指令需要比8080与8085更多的时间,原因在于:
- 取指令与执行指令是松散耦合,对于跳转与随机数据访问没有特殊措施,效率较低.
- 没有专门的地址计算部件,只能用主ALU,虽然有专用的段地址 + 偏移地址的加法器
- 外部地址总线与数据总线是多工复用,与8位处理器相比要多用33~50%的总线周期
8086的后继处理器的内存访问性能大大增强了。80186 and 80286有专门的地址计算硬件,节约了很多时间周期。80286的外部地址总线与数据总线是分开各自专用的。
浮点 [编辑]
8086/8088可以连接上专用的数学协处理器以增加浮点计算性能。标准的数学协处理是Intel 8087,执行80位浮点数运算。
使用8086的微電腦 [编辑]
第一個以8086為基礎的商業微電腦是Mycron2000。
IBM Displaywriter文字處理機也使用8086。在大部分顯要的所有微處理器中,IBM PC使用了更窄的記憶體總線版本的8086,也就是Intel 8088。 8086CPU結構上的一個重要特點是分為二大部分,即總線接口單元BIU和執行單元EU,其中BIU負責外部信息交換,EU負責指令執行,二者合理分工、並行工作,工作效率比此前的CPU明顯提高,常稱之為流水線結構。
外部連結 [编辑]
参考文献 [编辑]
- ^ Microsoft Macro Assembler 5.0 Reference Manual. Microsoft Corporation. 1987. "Timings and encodings in this manual are used with permission of Intel and come from the following publications: Intel Corporation. iAPX 86, 88, 186 and 188 User's Manual, Programmer's Reference, Santa Clara, Calif. 1986." (Similarly for iAPX 286, 80386, 80387.)
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Article based on Intel 8086 at FOLDOC,used with permission.