Intel 8080

<image>

英特尔8080微处理器是英特尔设计和制造的第二款8位微处理器。它于1974年4月首次亮相，是早期8008设计的扩展和增强版本，尽管它们之间没有二进制兼容性。最初规定的时钟频率或频率限制为2 MHz，常见指令使用4、5、7、10或11个周期。因此，该处理器能够每秒执行数十万条指令。后来推出了两个更快的变种，8080A-1和8080A-2，它们的时钟频率限制分别为3.125 MHz和2.63 MHz。8080在大多数应用中需要两个支持芯片才能工作：i8224时钟生成器/驱动器和i8228总线控制器。它采用N型金属氧化物半导体逻辑（NMOS）实现，使用非饱和增强模式晶体管作为负载，因此除了主要的晶体管-晶体管逻辑（TTL）兼容的+5 V外，还需要+12 V和-5 V的电压。

尽管早期的微处理器通常用于如计算器、收银机、计算机终端、工业机器人等大批量生产的设备中，8080在更广泛的应用中取得了更大的成功，它在很大程度上被认为是微型计算机行业的起点。其受欢迎的几个因素包括：其40脚封装比18脚的8008更易于接口，并且使其数据总线更高效；其NMOS实现使其晶体管比P型金属氧化物半导体逻辑（PMOS）的8008更快，同时通过使其与TTL兼容简化了接口；可用的支持芯片种类更多；其指令集相对于8008有所增强；以及其完整的16位地址总线（相对于8008的14位）使其能够访问64 KB的内存，是8008范围的四倍。它被用于Altair 8800和后续的S-100总线个人计算机，直到被Z80取代，并且是由Gary Kildall开发的CP/M操作系统的原始目标CPU。

8080直接影响了后来的x86架构。英特尔设计了8086，使其汇编语言与8080足够相似，大多数指令可以直接映射到彼此上，这样就可以在8086上执行转译的8080汇编代码。

## 历史

微处理器的客户对采用8008持谨慎态度，原因在于它存在诸多限制，如单一寻址模式、低时钟速度、低引脚数以及小型片上栈，这些因素限制了软件的规模和复杂度。对于8080的设计提案有很多，范围从仅仅给8008添加栈指令到完全脱离所有之前英特尔的架构。最终的设计是各种提案之间的一种妥协。

Federico Faggin是8080架构的发起人，他在1972年初向英特尔的管理层提出了这一芯片设计，并推动了它的实施。六个月后，他终于获得了开发的许可。Faggin于1972年11月从日本聘请了与他一起设计4004的Masatoshi Shima。Shima在Faggin的指导下进行了详细设计，使用了Faggin为4000系列创造的随机逻辑硅门设计方法。

8080被明确设计为一个面向更广泛客户的通用微处理器。大量的开发工作致力于尝试将8008的辅助芯片的功能整合到一个封装中。开发初期就决定8080不与8008二进制兼容，而是选择源兼容性，一旦通过转译器运行，就可以允许新软件不受8008同样的限制。出于同样的原因，以及为了扩展基于栈的例程和中断的能力，栈被移至外部内存。

注意到程序员在大型机系统中对通用寄存器的专用使用，芯片架构师Stanley Mazor决定8080的寄存器将是专用的，寄存器对有不同的用途集。这也使得工程师能够更有效地将晶体管用于其他目的。

Shima在1973年8月完成了布局。在NMOS制造调整之后，一个8080的原型在1974年1月完成。它有一个缺陷，即使用标准TTL设备驱动时，因为高电流流入狭窄的线路而增加了地线电压。在Shima对原型进行特性分析之前，英特尔已经按照销售部门的指示生产了40,000个8080单元。它被发布时要求使用低功耗肖特基TTL（LS TTL）设备。8080A修正了这个缺陷。

## 功能

<image>

### 编译模型

Intel 8080 是 8008 的后继者。它使用与 8008 相同的基本指令集和寄存器模型，尽管它既不与其前身兼容源代码，也不兼容二进制代码。8008 中的每条指令在 8080 中都有等效指令。8080 还在其指令集中添加了 16 位操作。而 8008 需要使用 HL 寄存器对来间接访问其 14 位内存空间，8080 添加了寻址模式，允许直接访问其完整的 16 位内存空间。8008 的内部 7 级下压调用堆栈被专用的 16 位堆栈指针（SP）寄存器替换。8080 的 40 引脚 DIP 封装允许它提供 16 位地址总线和 8 位数据总线，实现对 64 KiB（2^16 字节）内存的访问。

15｜14｜13｜12｜11｜10｜09｜08｜07｜06｜05｜04｜03｜02｜01｜00｜(bit position)

主寄存器

A｜Flags｜程序状态字

B｜C｜B

D｜E｜D

H｜L｜H (间接地址)

索引寄存器

SP｜栈指针

程序计数器

PC｜程序计数器

状态寄存器

S｜Z｜0｜AC｜0｜P｜1｜C｜Flags

### 寄存器

处理器有七个 8 位寄存器（A、B、C、D、E、H 和 L），其中 A 是主 8 位累加器。其他六个寄存器可以根据特定指令作为单独的 8 位寄存器或在三个 16 位寄存器对（BC、DE 和 HL，在 Intel 文档中分别称为 B、D 和 H）中使用。某些指令还允许 HL 寄存器对作为（有限的）16 位累加器使用。伪寄存器 M，指的是由 HL 指向的解引用内存位置，几乎可以在任何其他寄存器可以使用的地方使用。8080 有一个 16 位的堆栈指针指向内存，替换了 8008 的内部堆栈，并有一个 16 位的程序计数器。

标志

处理器维护内部标志位（状态寄存器），这些标志位指示算术和逻辑指令的结果。只有特定的指令会影响标志位。标志位包括：

- 符号（S），如果结果为负则设置。
- 零（Z），如果结果为零则设置。
- 奇偶校验（P），如果结果中 1 的位数为偶数则设置。
- 进位（C），如果最后一次加法操作产生了进位或者最后一次减法操作需要借位则设置。
- 辅助进位（AC 或 H），用于二进制编码的十进制算术（BCD）。

特定指令可以设置或反转进位位。条件分支指令测试各种标志状态位。累加器和标志位一起被称为 PSW，或程序状态字。PSW 可以被推入或从堆栈中弹出。

### 命令与指令

与许多其他 8 位处理器一样，所有指令都编码为一个字节（包括寄存器编号，但不包括立即数数据），以简化操作。有些可以跟随一到两个字节的数据，这可以是立即数操作数、内存地址或端口号。像更高级的处理器一样，它有自动 CALL 和 RET 指令用于多级过程调用和返回（甚至可以像跳转一样有条件地执行），以及用于在机器堆栈上保存和恢复任何 16 位寄存器对的指令。存在八个一字节的调用指令（RST），用于在固定地址 00h、08h、10h、...、38h 处的子程序。这些旨在由外部硬件提供，以调用相应的中断服务例程，但也经常用作快速系统调用。执行最慢的指令是 XTHL，用于将 HL 寄存器对与堆栈指针指示的地址处存储的值交换。

#### 8 位指令

所有具有两个操作数的 8 位操作只能在 8 位累加器（A 寄存器）上执行。另一个操作数可以是立即值、另一个 8 位寄存器或由 16 位寄存器对 HL 地址的内存字节。增量和减量操作可以在任何 8 位寄存器或 HL 地址的内存字节上执行。支持直接复制任意两个 8 位寄存器之间以及任何 8 位寄存器和 HL 地址的内存字节之间。由于 MOV 指令的规则编码（使用了可用操作码空间的四分之一），存在将寄存器复制到其自身的冗余代码（MOV B,B），除了用于延迟外几乎无用。然而，系统性的 MOV M,M 操作码被用来编码停止（HLT）指令，直到外部重置或中断发生时停止执行。

#### 16 位操作

虽然 8080 通常是一个 8 位处理器，它有限地能够执行 16 位操作。任何三个 16 位寄存器对（BC、DE 或 HL，在 Intel 文档中分别称为 B、D、H）或 SP 可以使用LXI加载立即 16 位值，使用INX 和 DCX进行增量或减量操作，或使用 DAD 加到 HL 上。通过将 HL 加到其自身，可以使用一条指令实现与 16 位算术左移相同的结果。唯一影响任何标志的 16 位指令是 DAD，它设置 CY（进位）标志，以允许进行编程的 24 位或 32 位算术（或更大），这对于实现浮点算术是必需的。可以使用 DAD SP 和 SPHL 分配堆栈帧。可以使用 PCHL, 执行对计算指针的跳转。LHLD 从直接寻址的内存中加载 HL，SHLD 同样存储 HL。XCHG指令交换 HL 和 DE 寄存器对的值。XTHL 与堆栈上最后推入的项和 HL 交换。

### 指令集

操作码｜操作数｜助记符｜周期数｜描述

7｜6｜5｜4｜3｜2｜1｜0｜b2｜b3

0｜0｜0｜0｜0｜0｜0｜0｜—｜—｜NOP｜4｜No operation

0｜0｜RP｜0｜0｜0｜1｜datlo｜dathi｜LXI rp,data｜10｜RP ← data

0｜0｜RP｜0｜0｜1｜0｜—｜—｜STAX rp｜7｜(RP) ← A BC or DE only

0｜0｜RP｜0｜0｜1｜1｜—｜—｜INX rp｜5｜RP ← RP + 1

0｜0｜DDD｜1｜0｜0｜—｜—｜INR ddd｜5/10｜DDD ← DDD + 1

0｜0｜DDD｜1｜0｜1｜—｜—｜DCR ddd｜5/10｜DDD ← DDD - 1

0｜0｜DDD｜1｜1｜0｜data｜—｜MVI ddd,data｜7/10｜DDD ← data

0｜0｜RP｜1｜0｜0｜1｜—｜—｜DAD rp｜10｜HL ← HL + RP

0｜0｜RP｜1｜0｜1｜0｜—｜—｜LDAX rp｜7｜A ← (RP) BC or DE only

0｜0｜RP｜1｜0｜1｜1｜—｜—｜DCX rp｜5｜RP ← RP - 1

0｜0｜0｜0｜0｜1｜1｜1｜—｜—｜RLC｜4｜A1-7 ← A0-6; A0 ← Cy ← A7

0｜0｜0｜0｜1｜1｜1｜1｜—｜—｜RRC｜4｜A0-6 ← A1-7; A7 ← Cy ← A0

0｜0｜0｜1｜0｜1｜1｜1｜—｜—｜RAL｜4｜A1-7 ← A0-6; Cy ← A7; A0 ← Cy

0｜0｜0｜1｜1｜1｜1｜1｜—｜—｜RAR｜4｜A0-6 ← A1-7; Cy ← A0; A7 ← Cy

0｜0｜1｜0｜0｜0｜1｜0｜addlo｜addhi｜SHLD add｜16｜(add) ← HL

0｜0｜1｜0｜0｜1｜1｜1｜—｜—｜DAA｜4｜If A0-3 > 9 OR AC = 1 then A ← A + 6; then if A4-7 > 9 OR Cy = 1 then A ← A + 0x60

0｜0｜1｜0｜1｜0｜1｜0｜addlo｜addhi｜LHLD add｜16｜HL ← (add)

0｜0｜1｜0｜1｜1｜1｜1｜—｜—｜CMA｜4｜A ← ¬A

0｜0｜1｜1｜0｜0｜1｜0｜addlo｜addhi｜STA add｜13｜(add) ← A

0｜0｜1｜1｜0｜1｜1｜1｜—｜—｜STC｜4｜Cy ← 1

0｜0｜1｜1｜1｜0｜1｜0｜addlo｜addhi｜LDA add｜13｜A ← (add)

0｜0｜1｜1｜1｜1｜1｜1｜—｜—｜CMC｜4｜Cy ← ¬Cy

0｜1｜DDD｜SSS｜—｜—｜MOV ddd,sss｜5/7｜DDD ← SSS

0｜1｜1｜1｜0｜1｜1｜0｜—｜—｜HLT｜7｜Halt

1｜0｜ALU｜SSS｜—｜—｜ADD ADC SUB SBB ANA XRA ORA CMP sss｜4/7｜A ← A ALU operation SSS

1｜1｜CC｜0｜0｜0｜—｜—｜Rcc｜5/11｜If cc true, PC ← (SP), SP ← SP + 2

1｜1｜RP｜0｜0｜0｜1｜—｜—｜POP rp｜10｜RP ← (SP), SP ← SP + 2

1｜1｜CC｜0｜1｜0｜addlo｜addhi｜Jcc add｜10｜If cc true, PC ← add

1｜1｜0｜0｜0｜0｜1｜1｜addlo｜addhi｜JMP add｜10｜PC ← add

1｜1｜CC｜1｜0｜0｜addlo｜addhi｜Ccc add｜11/17｜If cc true, SP ← SP - 2, (SP) ← PC, PC ← add

1｜1｜RP｜0｜1｜0｜1｜—｜—｜PUSH rp｜11｜SP ← SP - 2, (SP) ← RP

1｜1｜ALU｜1｜1｜0｜data｜—｜ADI ACI SUI SBI ANI XRI ORI CPI data｜7｜A ← A ALU operation data

1｜1｜N｜1｜1｜1｜—｜—｜RST n｜11｜SP ← SP - 2, (SP) ← PC, PC ← N x 8

1｜1｜0｜0｜1｜0｜0｜1｜—｜—｜RET｜10｜PC ← (SP), SP ← SP + 2

1｜1｜0｜0｜1｜1｜0｜1｜addlo｜addhi｜CALL add｜17｜SP ← SP - 2, (SP) ← PC, PC ← add

1｜1｜0｜1｜0｜0｜1｜1｜port｜—｜OUT port｜10｜Port ← A

1｜1｜0｜1｜1｜0｜1｜1｜port｜—｜IN port｜10｜A ← Port

1｜1｜1｜0｜0｜0｜1｜1｜—｜—｜XTHL｜18｜HL ↔ (SP)

1｜1｜1｜0｜1｜0｜0｜1｜—｜—｜PCHL｜5｜PC ← HL

1｜1｜1｜0｜1｜0｜1｜1｜—｜—｜XCHG｜4｜HL ↔ DE

1｜1｜1｜1｜0｜0｜1｜1｜—｜—｜DI｜4｜Disable interrupts

1｜1｜1｜1｜1｜0｜0｜1｜—｜—｜SPHL｜5｜SP ← HL

1｜1｜1｜1｜1｜0｜1｜1｜—｜—｜EI｜4｜Enable interrupts

7｜6｜5｜4｜3｜2｜1｜0｜b2｜b3｜助记符｜周期数｜描述

SSS DDD｜2｜1｜0｜CC｜ALU｜RP

B｜0｜0｜0｜NZ｜ADD ADI (A ← A + arg)｜BC

C｜0｜0｜1｜Z｜ADC ACI (A ← A + arg + Cy)｜DE

D｜0｜1｜0｜NC｜SUB SUI (A ← A - arg)｜HL

E｜0｜1｜1｜C｜SBB SBI (A ← A - arg - Cy)｜SP or PSW

H｜1｜0｜0｜PO｜ANA ANI (A ← A ∧ arg)

L｜1｜0｜1｜PE｜XRA XRI (A ← A ⊻ arg)

M｜1｜1｜0｜P｜ORA ORI (A ← A ∨ arg)

A｜1｜1｜1｜N｜CMP CPI (A - arg)

SSS DDD｜2｜1｜0｜CC｜ALU

### 输入/输出方案

#### 输入输出端口空间

8080 支持多达 256 个输入/输出（I/O）端口，通过使用端口地址作为操作数的专用 I/O 指令访问。这种 I/O 映射方案被认为是一个优势，因为它释放了处理器有限的地址空间。许多 CPU 架构相反使用所谓的内存映射 I/O（MMIO），在这种设计中，RAM 和外围芯片使用共同的地址空间。这消除了对专用 I/O 指令的需求，尽管这样的设计可能存在的一个缺点是，由于外围设备通常比内存慢，因此必须使用特殊硬件来插入等待状态。然而，在一些简单的 8080 计算机中，I/O 确实被当作内存单元进行寻址，即“内存映射”，从而不使用 I/O 命令。I/O 寻址有时也可以利用处理器将相同的 8 位端口地址输出到低地址字节和高地址字节的事实（即，IN 05h 会在 16 位地址总线上放置地址 0505h）。类似的 I/O 端口方案被用在向后兼容的 Zilog Z80 和 Intel 8085，以及密切相关的 x86 微处理器系列中。

#### 独立的堆栈空间

处理器状态字中的一个位（见下文）指示处理器正在从堆栈访问数据。使用这个信号，可以实现一个独立的堆栈内存空间。这个功能很少被使用。

### 状态字

对于更高级的系统，在每个机器周期的开始，处理器在数据总线上放置一个八位状态字。这个字节包含的标志决定了是访问内存还是 I/O 端口，以及是否需要处理中断。

中断系统状态（启用或禁用）也在一个单独的引脚上输出。对于简单系统，其中不使用中断，在某些情况下可能会发现这个引脚被用作额外的单比特输出端口（例如，在苏联制造的流行的 Radio-86RK 计算机）。

### 示例代码

以下是8080/8085汇编器源代码，用于一个名为memcpy的子程序，该子程序将给定大小的数据块从一个位置复制到另一个位置。数据块一次复制一个字节，数据移动和循环逻辑使用16位操作。

```
 
 
 
 
 
 
 
 
 
 
 
1000
1000
1000  78
1001  B1
1002  C8
1003  1A
1004  77
1005  13
1006  23
1007  0B
1008  78
1009  B1
100A  C2 03 10
100D  C9
```

```nasm
; memcpy --
; 将内存块从一个位置复制到另一个位置。
;
; 输入寄存器
;   BC - 要复制的字节数
;   DE - 源数据块的地址
;   HL - 目标数据块的地址
;
; 返回寄存器
;   BC - 零

            org     1000h       ;起始地址为1000h
memcpy      public
            mov     a,b         ;将寄存器B的值复制到寄存器A
            ora     c           ;寄存器A与寄存器C进行按位或操作，结果存入寄存器A
            rz                  ;如果零标志被置位，则返回
loop:       ldax    d           ;从DE指向的地址加载数据到A
            mov     m,a         ;将寄存器A的内容存储到HL指向的地址
            inx     d           ;增加 DE
            inx     h           ;增加 HL
            dcx     b           ;BC减一（不影响标志位）
            mov     a,b         ;将B复制到A（以便将BC与零比较）
            ora     c           ;A = A | C （B和C都是零吗？）
            jnz     loop        ;如果零标志未被置位，则跳转到'loop:'
            ret                 ;返回
```

<image>

### 针脚

地址总线拥有自己的16个针脚，而数据总线有8个可用的针脚，无需任何复用。使用另外两个针脚（读和写信号），可以非常容易地组装简单的微处理器设备。仅需为独立的IO空间、中断和DMA添加解码处理器针脚信号的芯片。

然而，针脚的负载能力是有限的；即使是简单的计算机通常也需要总线放大器。

处理器需要三个电源（-5V、+5V和+12V）和两个非重叠的高幅度同步信号。然而，至少在苏联后期的版本КР580ВМ80А能够仅使用单一的+5V电源工作，将+12V针脚连接到+5V，将-5V针脚接地。

随芯片提供的文档中的针脚布局表，如下描述针脚：

针脚｜信号｜类型｜指令

1｜A10｜Output｜地址总线10

2｜GND｜地

3｜D4｜Bidirectional｜双向数据总线，处理器还会暂时在此设置“处理器状态”，提供有关处理器当前正在执行的操作的信息：、D0 读取中断命令。响应中断信号时，处理器正在读取并执行一个带有此标志的任意命令。通常，支持芯片会提供子程序调用命令（CALL或RST），将控制权转移到中断处理代码、D1 读取（低电平意味着写入）、D2 访问堆栈（可能最初计划了一个单独的堆栈内存空间）、D3 无操作，已被HLT指令停止、D4 向输出端口写入数据、D5 读取可执行指令的第一个字节、D6 从输入端口读取数据、D7 从内存读取数据

4｜D5

5｜D6

6｜D7

7｜D3

8｜D2

9｜D1

10｜D0

11｜−5 V｜-5伏电源供应。这必须是首先连接的电源，并且是最后断开的电源，否则处理器将会受损

12｜RESET｜Input｜复位。该信号强制执行位于0000地址的命令。其他处理器寄存器的内容不会被修改。这是一个反相输入（激活电平为逻辑0）

13｜HOLD｜Input｜直接内存访问请求。请求处理器将数据和地址总线切换到高阻抗（“断开连接”）状态

14｜INT｜Input｜中断请求

15｜φ2｜Input｜时钟发生器信号的第二相位

16｜INTE｜Output｜处理器拥有两个命令，用于在该引脚上设置0或1电平。这个引脚通常被用于中断控制。然而，在简单的计算机中，它有时被用作单比特输出端口，用于各种目的

17｜DBIN｜Output｜读(处理器从内存或输入端口读取数据)

18｜WR｜Output｜写(处理器向内存或输出端口写入数据。这是一个反向输出，激活电平为逻辑零)

19｜SYNC｜Output｜激活电平表明处理器已经将“状态字”放置在数据总线上。这个状态字的各个位提供了额外的信息，以支持独立的地址和内存空间、中断和直接内存访问。这个信号在可以用于将数据总线上的处理器状态字写入某个外部寄存器之前，需要通过额外的逻辑处理，例如， 8238 系统控制器和总线驱动器

20｜+5 V｜+5伏电源供应

21｜HLDA｜Output｜直接内存访问确认。处理器将数据和地址引脚切换到高阻抗状态，允许其他设备操纵总线

22｜φ1｜Input｜时钟发生器信号的第一相位

23｜READY｜Input｜等待(利用这个信号，可以暂停处理器的工作。它还用于支持基于硬件的逐步调试模式)

24｜WAIT｜Output｜等待(指示处理器处于等待状态)

25｜A0｜Output｜地址总线

26｜A1

27｜A2

28｜12 V｜+12伏电源供应，这必须是最后连接和第一个断开的电源

29｜A3｜Output｜地址总线；可以根据需求切换到高阻抗状态

30｜A4

31｜A5

32｜A6

33｜A7

34｜A8

35｜A9

36｜A15

37｜A12

38｜A13

39｜A14

40｜A11

## 支持芯片

8080的成功关键因素之一是有广泛的支持芯片可用，提供串行通信、计数/定时、输入/输出、直接内存访问和可编程中断控制等多种功能：

- 8214 - 优先级中断控制单元
- 8224 – 时钟发生器
- 8228/ 8238 – 系统控制器和总线驱动器
- 8251 – 通信控制器
- 8253 – 可编程间隔定时器
- 8255 – 可编程外围接口
- 8257 – DMA控制器
- 8259 – 可编程中断控制器

## 实现

8080集成电路使用非饱和增强型负载nMOS门，需要额外的电压（用于负载门偏置）。它是在一个硅门过程中制造的，使用最小特征尺寸为6微米。设计中大约4500个晶体管通过单层金属层互联，但较高电阻的多晶硅层（一些互联需要更高的电压）是用晶体管门实现的。芯片尺寸大约为20平方毫米。

## 基本资料

- 产品化：1974年
- 产品化：1990年
- CPU主频范围：2
- CPU主频范围：MHz
- CPU主频范围：3.125
- 制作工艺/制程：6 µm
- 推出公司：Intel
- 设计团队：Intel
- manuf1：Intel
- sock1：DIP40
- pack1：40-pin DIP
- 指令集架构：8080
- transistors：4,500 or 6,000
- data-width：8 bits
- address-width：16 bits
- 核心数量：1
- 前任：Intel 8008
- 继任：Intel 8085
- support status：Unsupported