Intel 8086

微處理器

Intel 8086[1](亦稱之為iAPX 86[2]是由英特爾公司於1976年初開始設計,1978年年中發表的Intel第一款16位元微處理器。随後於1979年,又推出了Intel 8088,它在晶片的外部連接椎使用8位資料匯流排(允許使用更廉價和更少積體電路[note 1])的支援,成為8086的一个低成本的簡化产品,并用在IBM PC的原始設計中的處理器(包括廣為人所知的IBM PC XT)中而被人知曉。

Intel 8086
產品化1978年至1990年代
生产商
指令集架構x86-16
制作工艺/製程3 μm
CPU主频范围5 MHz 至 10 MHz
封裝
上代產品Intel 8080
繼任產品8018680286(兩種晶片均在1982年引進)
相關產品8088

8086是Intel最成功的处理器系列x86架构的开端。

历史

背景

1972年,Intel发布了8008微处理器——世界上第一款8位微处理器。[note 2] 8008微处理器有18个引脚,其中地址总线使用了14个引脚,并且与8位数据总线复用引脚。指令集源自是Datapoint公司为计算机的CRT-键盘终端设计的但相当通用的指令集。当时英特尔还是一家生产DRAM为主业的公司,缺乏这方面的技术储备。

1974年,Intel发布了8080微处理器,[note 3] 被公认是第一款真正可用的微处理器。8080的芯片封装采用40个引脚,其中8个数据总线引脚、16个地址总线引脚都是专用的,因此数据总线与地址总线可以并行工作。8080的扩展后的指令集在源代码级别上向前兼容8008指令集。

1975年,Intel发布了第三款8位微处理器——8085。采用了新的制造工艺,简化了输入电压引脚的数量。同一时期还有Motorola 6800(1974)、Microchip PIC16X(1975)、MOS Technology 6502(1975)、Zilog Z80(1976)及Motorola 6809(1978)等8位微处理器。在8位微处理器市场竞争中Z80最为成功。

第一种x86设计

 
Intel 8086 晶粒

8086项目起始于1976年5月,是英特尔公司当时更为看重的16位元的iAPX 432英语Intel iAPX 432微处理器的备份项目。8086一方面要与Motorola, Zilog, National Semiconductor等公司的16位元、32位元微处理器竞争市场份额,另一方面也是对Zilog Z80在8位元位微处理器市场上的成功的回击。由于采用了与8085微处理器近似的微体系结构与物理实现工艺物理实现工艺,8086项目进展相当快。

8086微处理器被设计为在汇编源程序上向前兼容8008, 8080, 8085等微处理器。指令集与编程模式是基于8080微处理器,但指令集做了擴充以完全支援16位元计算。

新增加的指令包括:完全支持有符号整数、段基址+偏移量寻址、类似于Z80的[3]自重复操作、直接支持嵌套的ALGOL类语言如Pascal或PL/M、微码实现的乘法除法指令、以及更好支持与协处理器(8087或8089)和多处理器系统的总线结构。

第一版的指令集与高层的体系结构的设计仅用了3个月。[note 4] 在没有CAD工具的时代,4名工程师与12名布线绘图员平行工作,[note 5] 用了2年多的时间才把8086的高层设计实现为可运行测试的产品。这在当时算是很快的研发速度。

8086是随机逻辑[4]微码的混合实现[note 6],使用了大约20,000个晶体管(算上所有的ROM可编程逻辑阵列为29,000个晶体管)。芯片面积为33 mm²,制造工艺为3.2 μm.

8086体系结构由Stephen P. Morse设计,并在最后定案时得到Bruce Ravenel(8087体系结构设计者)的帮助。逻辑设计者是以Jim McKevitt与John Bayliss为首的硬件开发工程师团队[note 7]。项目经理William Pohlman。迄今8086的指令集仍然是PC机与服务器的基本指令集。

细节

 
8086引脚的功用,在min与max模式下有所不同
 
最小模式下8086引脚名称和功能简述
Intel 8086寄存器
19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 (比特位置)
主寄存器
  AH AL AX(累加器)
  BH BL BX(基址寄存器)
  CH CL CX(计数寄存器)
  DH DL DX(数据寄存器)
变址寄存器
0 0 0 0 SI 源变址寄存器
0 0 0 0 DI 目的变址寄存器
0 0 0 0 BP 基址指针寄存器
0 0 0 0 SP 堆栈指针寄存器
程序计数器
0 0 0 0 IP 指令指针
段寄存器
CS 0 0 0 0 代码段寄存器
DS 0 0 0 0 数据段寄存器
ES 0 0 0 0 附加段寄存器
SS 0 0 0 0 堆栈段寄存器
状态寄存器
  - - - - O D I T S Z - A - P - C 标志寄存器

总线与操作

所有的内部寄存器、内部及外部数据总线都是16位宽,因此是完全的16位微处理器。20位外部地址总线,因此物理定址空间为1MiB (即220 = 1,048,576).由于内部寄存器都是16位,对1M地址空间寻址时采取了段寻址方式。8086的封装采用40引脚的双列直插(dual in-line),数据总线与地址总线复用了前16个引脚。16位的I/O地址,因此独立的I/O寻址空间为64KiB的虛擬定址空間 (即216 = 65,536).由于8086内部的地址寄存器是16 位宽,因而最大线性寻址空间为64 KiB.使用超过64 KiB内存空间的程序设计时,需要调整段寄存器(segment registers)。直到32位的80386出现之前,8086的这种段寻址相当不便.

8086芯片封装的8个控制引脚在minmax下有不同功能。"min"模式是使用单处理器的小型计算机系统,"max"模式是使用多处理器的中到大型计算机系统。

寄存器与指令

8086有8个16比特的寄存器,包括栈寄存器SP与BP,但不包括指令寄存器IP、控制寄存器FLAGS以及四个段寄存器。AX, BX, CX, DX,这四个寄存器可以按照字节访问;但BP, SI, DI, SP,这四个地址寄存器只能按照16位宽访问。

8086以80808085(它與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所没有的新指令,用于更好地支持PascalPL/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应用程序能很快得到利用。

实例代码

以下8086/8088汇编源代码是将给定大小的数据块从一个位置拷贝到另一个位置的叫做_memcpy的子程序。每次拷贝一个字节,数据移动和循环逻辑采用16位操作。

                     
                     
                     
                     
                     
                     
                     
                     
                     
                     
 
0000:1000            

0000:1000            
0000:1000 55         
0000:1001 89 E5      
0000:1003 06         
0000:1004 8B 4E 06   
0000:1007 E3 11      
0000:1009 8B 76 04   
0000:100C 8B 7E 02   
0000:100F 1E         
0000:1010 07         

0000:1011 8A 04      
0000:1013 88 05      
0000:1015 46         
0000:1016 47         
0000:1017 49         
0000:1018 75 F7      

0000:101A 07         
0000:101B 5D         
0000:101C 29 C0      
0000:101E C3         
0000:101F            
; _memcpy(dst, src, len)
; Copy a block of memory from one location to another.
;
; Entry stack parameters
;      [BP+6] = len, Number of bytes to copy
;      [BP+4] = src, Address of source data block
;      [BP+2] = dst, Address of target data block
;
; Return registers
;      AX = Zero

            org     1000h       ; Start at 0000:1000h

_memcpy     proc
            push    bp          ; Set up the call frame
            mov     bp,sp
            push    es          ; Save ES
            mov     cx,[bp+6]   ; Set CX = len
            jcxz    done        ; If len=0, return
            mov     si,[bp+4]   ; Set SI = src
            mov     di,[bp+2]   ; Set DI = dst
            push    ds          ; Set ES = DS
            pop     es

loop        mov     al,[si]     ; Load AL from [src]
            mov     [di],al     ; Store AL to [dst]
            inc     si          ; Increment src
            inc     di          ; Increment dst
            dec     cx          ; Decrement len
            jnz     loop        ; Repeat the loop

done        pop     es          ; Restore ES
            pop     bp          ; Restore previous call frame
            sub     ax,ax       ; Set AX = 0
            ret                 ; Return
            end proc

上面的代码使用BP(基指针)寄存器建立一个调用帧(包含子程序执行过程中的所有参数和局部变量的栈的区域)。这种调用约定支持可重入递归代码,大多数类ALGOL语言上世纪50年代后期就已采用这种约定。ES段寄存器保存在堆栈上,并用DS段寄存器中的值替换,于是指令MOV AL会在相同的源数据段和目的数据段之间操作。在返回前,子程序恢复了ES寄存器以前的值。

上面的子程序是一种比较麻烦的拷贝成块数据的方法。若源数据区域和目的数据区域都是处于单个65,536字节的段中(上述程序的要求),使用8086的块MOV指令更有优势。上面的循环部分可以替换为:

0000:1011 F2         
0000:1012 A5         
loop        rep                  ; Repeat until CX=0
            movsw                ; Move the data block

这种方法每次可以拷贝一个字。REP指令使下面的MOVSW重复直至CX=0,重复之时自动递增SI和DI。另外,MOVSBMOVSD指令可以用来一次拷贝单个字节或双字。大多数汇编器在REP指令用在MOVSW之前为REP MOVSW的情况下都会正确汇编。

如果被中断,这个程序也能正确运行,因为程序计数器会继续指向REP指令,知道块拷贝已经结束。拷贝会在中断服务程序将控制恢复的时候继续。

性能

 
Intel 8088(8086的一个变种)简化模块图; 1=主寄存器; 2=段址寄存器与IP寄存器; 3=地址加法器; 4=内部地址总线; 5=指令队列; 6=控制单元; 7=总线界面; 8=内部数据总线; 9=ALU; 10/11/12=外部数据/地址/控制总线

外部总线作为数据与地址的复用,降低了CPU的性能。取16比特或8比特数据需要4个时钟周期。指令的长度为1-6个字节,取指令与执行是并发完成的。CPU内的总线界面单元把取到的指令保存在6字节的预取队列中。

典型指令的执行时间
(时钟周期)[5]
指令 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
整数乘法 70~160(取决于操作数data以及大小)加上EA
有符号整数除法 80~190(取决于操作数data以及大小)加上EA
  • EA = 计算有效地址的时间,5到12周期.
  • 用时为最好的情形,依赖于预取状态,指令对齐,及其它因素.

8086涉及内存访问的指令,包括跳转(jump)指令需要比80808085更多的时间,原因在于:

  • 取指令与执行指令是松散耦合,对于跳转与随机数据访问没有特殊措施,效率较低.
  • 没有专门的地址计算部件,只能用主ALU,虽然有专用的段地址 + 偏移地址的加法器
  • 外部地址总线与数据总线是多工复用,与8位处理器相比要多用33~50%的总线周期

8086的后继处理器的内存访问性能大大增强了。8018680286有专门的地址计算硬件,节约了很多时间周期。80286的外部地址总线与数据总线是分开各自专用的。

浮点

8086/8088可以连接上专用的数学协处理器以增加浮点计算性能。标准的数学协处理是Intel 8087,执行80位浮点数运算。

微電腦

第一個以8086為基礎的商業微電腦是Mycron2000。

IBM Displaywriter文字處理機也使用8086。在大部分顯要的所有微處理器中,IBM PC使用了更窄的記憶體總線版本的8086,也就是Intel 8088。 8086CPU結構上的一個重要特點是分為二大部分,即總線接口單元BIU和執行單元EU,其中BIU負責外部信息交換,EU負責指令執行,二者合理分工、並行工作,工作效率比此前的CPU明顯提高,常稱之為流水線結構。

硬件模式

8086和8088支持两种硬件模式:最大模式和最小模式。最大模式是用在大型应用中的多重处理,并且也是支持8087处理器的必需。该模式通常硬件化在电路中,不能由软件改变。具体来说,#33引脚(MN/MX)是连载高电压还是接地决定了模式。改变引脚#33的状态就改变了其他特定引脚的功能,这些引脚中大多数是CPU处理(局部)总线的。IBM PC和PC/XT使用工作在最大模式的Intel 8088,让CPU与PC或PC/XT主板上安装在数学协同处理器插口的可选8087协同处理器。(PC和PC/XT可能因为其他原因而要求用最大模式,比如要支持DMA控制器。)

外设

紀念

2018年6月8日,英特尔在官网上开启了限量抽奖活动,奖品为i7-8086k,限量生产8086个。

注释

  1. ^ Fewer TTL buffers, latches, multiplexers (although the amount of TTL logic was not drastically reduced). It also permitted the use of cheap 8080-family ICs, where the 8254 CTC, 8255 PIO, and 8259 PIC were used in the IBM PC design. In addition, it made PCB layout simpler and boards cheaper, as well as demanding fewer (1- or 4-bit wide) DRAM chips.
  2. ^ using enhancement load PMOS logic (requiring 14 V, achieving TTL compatibility by having VCC at +5 V and VDD at –9 V)
  3. ^ using non-saturated enhancement load NMOS logic (demanding a higher gate voltage for the load transistor gates)
  4. ^ Rev.0 of the instruction set and architecture was ready in about three months, according to Morse.
  5. ^ Using rubylith, light boards, rulers, electric erasers, and a digitizer (according to Jenny Hernandez, member of the 8086 design team, in a statement made on Intel's webpage for its 25th birthday).
  6. ^ 8086 used less microcode than many competitors' designs, such as the MC68000 and others
  7. ^ Other members of the design team were Peter A.Stoll and Jenny Hernandez.

参考文献

  1. ^ Microprocessor Hall of Fame. Intel. [2007-08-11]. (原始内容存档于2007-07-06). 
  2. ^ Official Intel iAPX 286 programmers' manual页面存档备份,存于互联网档案馆) (page 1-1)
  3. ^ Birth of a Standard: The Intel 8086 Microprocessor. Thirty years ago, Intel released the 8086 processor, introducing the x86 architecture that underlies every PC — Windows, Mac, or Linux — produced today页面存档备份,存于互联网档案馆), PC World, June 17, 2008
  4. ^ Randall L. Geiger, Phillip E. Allen, Noel R. Strader VLSI design techniques for analog and digital circuits, McGraw-Hill Book Co., 1990, ISBN 978-0-07-023253-2, page 779 "Random Logic vs. Structured Logic Forms", illustration of use of "random" describing CPU control logic
  5. ^ 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.