# 8051 ISA Brief Introduction
**Repository Path**: zenny-chen/C51-isa-brief-introduction
## Basic Information
- **Project Name**: 8051 ISA Brief Introduction
- **Description**: 8051 ISA简介
- **Primary Language**: Unknown
- **License**: GPL-3.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 2
- **Forks**: 0
- **Created**: 2020-09-15
- **Last Updated**: 2025-12-11
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 8051 ISA Brief Introduction
8051 ISA简介
## 概述
**Intel MCS-51**(俗称**8051**)是一个单片微控制器(**MCU**)系列,由Intel在1980年代研发而成,用于嵌入式系统。Intel MCS-51的指令集架构师为John H. Wharton。此芯片的初始版本在1980年代到1990年代非常受欢迎,并且其增强的二进制兼容衍生品在当今仍大受欢迎。它属于一种复杂指令集的计算机(**CISC**),并且对程序指令与数据具有独立的存储空间。
Intel初始的MCS-51家族使用N类型的金属氧化物半导体(**NMOS**)技术,跟其之前的Intel MCS-48类似。但对于后续版本,在其名字中使用了字母 **C** 进行标识(比如,80C51),它使用了互补的金属氧化物半导体(**CMOS**)技术,并且比之前的NMOS技术消耗更少的电量。这使得该技术非常适用于以电池来驱动的设备。
该家族持续到1996年一直使用增强的8位MCS-151以及二进制兼容的8/16/32位MCS-251家族微控制器。而随后,Intel不再制造MCS-51、MCS-151以及MCS-251家族,增强的二进制兼容衍生品由不少生产商制作,至今仍受欢迎。某些衍生品还集成了一块数字信号处理器(**DSP**)。除了这些物理设备,有些公司也提供了MCS-51衍生品作为IP核心用于现场可编程门阵列(**FPGA**),或应用特定的集成电路(**ASIC**)设计。
## 重要特性与应用
8051架构在一个包内提供了许多功能(中央处理单元(CPU),随机访问存储器(RAM),只读存储器(ROM),输入/输出(I/O),中断逻辑,定时器等等),详细结构如下:
・8位算术逻辑单元(ALU)与累加器,8位寄存器(一个16位寄存器,用于特殊搬运指令),8位数据总线和两个16位地址总线,程序计数器(PC),数据指针寄存器(DPTR),还有8/11/16位相关操作;因而,8051架构主要作为一款8位的微控制器。
・具有17条指令的布尔处理器,单比特累加器,32个寄存器(4比特可寻址的8位寄存器),以及多达144个特殊单比特可寻址的RAM变量(累加器A与累加器B各8位,一共16位,然后加上RAM中有128位可单比特寻址的,一共144位比特)。
・乘法、除法与比较指令
・4个快速可切换寄存器段,每个段含有8个寄存器(基于存储器映射)
・带有可选寄存器段切换的快速中断
・带有可选择优先级的中断与线程
・128或256个字节的片上RAM(IRAM)
・双16位地址总线;它可以访问2×216个存储位置:64KB的ROM(PMEM)以及64KB的外部RAM(XRAM)
・片上ROM(不包括803x系列)
・四个8位双向输入/输出端口,可单比特寻址
・UART(串口)
・两个16位计数器/定时器
・省电模式(在某些衍生品上)
[i8051微架构](https://gitee.com/zenny-chen/C51-isa-brief-introduction/blob/master/images/Intel_8051_arch.svg)
8051核心的一个特性是包含了布尔处理引擎,它允许比特级的布尔逻辑操作,对选择内部寄存器、端口以及选择RAM位置进行直接而有效地执行。此特性的加持巩固了8051在工业控制应用领域的欢迎度,因为它缩减了30%之多的代码尺寸。另一个特性是包含了四个段可选择的工作寄存器组,这极大地减少了执行上下文切换以进入或离开中断服务例程所需的时间。只需一条指令,8051就能切换寄存器段,避免了用于将临界寄存器传输到RAM这一任务的时间消耗。
如果有需要,一旦配置了一个UART和一个定时器,程序员只需要写一个简单的中断例程来填充*发送*移位寄存器,每当最后一个比特被UART移出时;以及/或清空已满的*接收*移位寄存器(将数据拷贝到其他地方)。主程序然后只需要对8位数据执行串行的从栈上读或写到栈上。
如果有需要,一旦配置了一个UART和一个定时器,程序员只需要写一个简单的中断例程来填充*发送*移位寄存器,每当最后一个比特被UART移出时;以及/或清空已满的*接收*移位寄存器(将数据拷贝到其他地方)。主程序然后只需要对8位数据执行串行的从栈上读或写到栈上。

#### 衍生特性
截至2013年,许多主要芯片制作商仍然在开发新的衍生品,而且主要编译器提供商,诸如[IAR Systems](https://www.iar.com)、[Keil](http://www.keil.com)以及[Altium Tasking](https://www.tasking.com)不断地发布更新。
基于MCS-51的微控制器一般包含了一般包含了一个或两个UART,两个或三个定时器,128或256个字节的内部数据RAM(其中有16字节是可按位寻址的),高达128字节的I/O,512字节到64KB的内部程序存储器,并且有些衍生品还有扩展数据RAM(ERAM)位于外部数据空间。外部RAN和ROM共享数据与地址总线。原始的8051核心可以以每个机器周期12个时钟周期运行,大部分指令以一或两个机器周期进行执行。假设一块8051具有12MHz时钟频率,那么该8051可以每秒执行一百万条单周期指令,或是每秒五十万条两个周期的指令。增强的8051核心现在一般每个机器周期运行在六个、四个、两个,或甚至一个时钟周期,并且还拥有高达100MHz的时钟频率,并从而甚至能达到每秒更多的指令数。所有Sillicon Labs,还有某些Dallas和一些Atmel的设备具有单周期的核心。
8051的变种可以包含带有掉电检测的重置定时器、片上振荡器、自可编程的flash ROM程序存储器、内建的外部RAM、额外的内部程序贮存器,在ROM、EEPROM非挥发数据贮存器中的引导程序代码,I2C、SPI以及USB主机接口,CAN或LIN总线,ZigBee或蓝牙无线电模块,PWM生成器、模拟比较器,A/D与D/A转换器、RTC(实时时钟),额外的计数器和定时器,电路内的调试工具,更多的中断源,额外的省电模式,更多/更少的并行端口等等。Intel制造了一个可屏蔽编程版本————8052AH-BASIC,它在ROM中带有一个BASIC解释器,能够运行加载到RAM中的用户程序。
基于MCS-51的微控制器已经在极端环境下所采用了。高温度变体的样例有Tekmos TK8H51家族,用于-40°C到+250°C,或Honeywell HT83C51,用于-55°C到+225°C(在+300°C环境下可运行多达1年)。Radiation-hardenend MCS-51微控制器用于宇宙航天。
在某些工程学校,8051微控制器用于工业微控制器课程。
## 家族命名协定
8051是由Intel设计出的原始名称,带有4KB的ROM与128字节的RAM。从87开始的变体具有一个用户可编程的EPROM存储器,有时UV可擦写。带有一个**C**的变体作为第三代则是某种CMOS。8031与8032是无ROM版本,带有128和256字节的RAM。最后一个数字指示存储器大小,比如8052带有8KB的ROM,87C54带有16KB的EPROM,还有87C58带有32KB的EPROM,所有这些都具有256字节的RAM。
## 存储器架构
MCS-51具有四种不同类型的存储器————内部RAM(**IRAM**),特殊功能寄存器(**SFR**),程序存储器(**PMEM**),以及外部数据存储器(**XRAM**)。
8051被设计为一个经修改的Von-Neumann架构,它具有分开的存储器(数据与指令);它只能从程序存储器来获取代码进行执行,并且无法将指令写入到程序存储器。而这与Harvard架构类似。
大部分8051系统会遵从这个特征,并因而无法下载并直接执行新的程序。尽管8051的架构是唯一的,不过访问这两种类型的存储器的总线是相同的,只有数据总线、地址总线和控制总线。
#### 内部RAM
内部RAM(IRAM)具有一个8位地址空间,使用地址0到0xFF。IRAM从0x00到0x7F可以直接寻址访问,使用一个8位绝对地址作为指令的一部分。IRAM也可以进行寄存器间接访问:地址值可以加载到R0或R1中,而存储器则使用 **`@R0`** 或 **`@R1`** 语法进行访问。
原始的8051只有128字节的IRAM。8052添加了从0x80到0xFF的IRAM,这个区域的IRAM*只能*通过间接访问;而如果对此地址区间做直接访问,那么访问到的是特殊功能寄存器。大多数8051衍生品也都具有一个完整的256字节的IRAM。
从0x00到0x1F的32字节的存储器被映射到8个寄存器R0到R7。一次可用8个单字节的寄存器;程序状态字(**PSW**)中有2个比特对四个可能的段进行选择。
在IRAM中有16个字节(128位)的存储位置0x20到0x2F,是可按位寻址的。
#### 程序存储器
程序存储器(**PMEM**,比起IRAM与XRAM用得少一些)是一块多达64KB的只读存储器,在一个独立的地址空间中起始地址为0。它可以在片上也可以在片外,依赖于所使用芯片的特定模型。程序存储器是只读的,即便某些8051的变种使用片上flash存储器并提供一种在系统内或应用内对该存储器重新编程的方法。
除了代码之外,也可以将只读数据存放到程序存储器中,比如查找表,然后通过`MOVC A, @A + DPTR`或`MOVC A, @A + PC`指令进行获取。该地址被计算为8位累加器与一个16位寄存器(PC或DPTR)的和。
特殊的跳转和调用指令(`AJMP`和`ACALL`)可以在同一2KB的程序存储器内进行访问,所需的开销会稍微小点。
#### 外部数据存储器
外部数据存储器(**XRAM**)是第三个地址空间,也是从地址0开始,并允许16位的地址空间。它也可以在片上或片外;由于它是“外部”的,因此访问时要使用 **`MOVX`** (外部搬移)指令。8051的许多变种包含了标准的256字节的IRAM,外加若干KB的XRAM在片上。
XRAM的头256字节可以使用`MOVX A, @R0`、`MOVX A, @R1`,`MOVX @R0, A`以及`MOVX @R1, A`这些指令来访问。完整的64KB空间可以使用`MOVX A, @DPTR`和`MOVX @DPTR, A`来访问。
## 寄存器
在8051中仅有的没被存储器映射的寄存器就是16位的程序计数器(**PC**)了。程序计数器指定了下一条要执行的指令。相对分支指令提供了一个8位带符号的偏移加到PC上。
8个通用目的寄存器R0到R7可以用比其他指令少1个字节的指令进行访问。它们被映射到0x00到0x1F区间的IRAM中。在任一时刻只能使用该区间中的8个字节,而使用哪个区间则是通过PSW中两位段选择位来确定。
以下是8051寄存器的部分列表,这些寄存器为存储器映射到特殊功能寄存器空间:
#### 栈指针,SP(0x81)
这是一个8位寄存器,用于子例程调用以及返回指令。8051上的栈是向上增长的;SP在压送数据之前先被递增,而在推出数据之后再进行递减。
#### 数据指针,DPTR(0x82-0x83)
这是一个16位寄存器,用于访问PMEM和XRAM。
#### 程序状态字寄存器,PSW(0xD0)
这包含了重要的状态标志,按位序号来描述:
0. 奇偶性,P。此状态位给出了累加器A的奇偶性。
1. 用户定义,UD。此状态位可以由软件进行读写;它不受硬件影响。
2. 溢出标志,OV。当加法产生一次带符号溢出时,此标志位被置1。
3. 寄存器选择0,RS0。
4. 寄存器选择1,RS1。RS1作为寄存器段选择的高位;RS0作为寄存器段选择的低位。(RS1 RS0)所组成的0~3分别为对0x00~0x07,0x08~0x0F,0x10~0x17以及0x18~0x1F这四个段的使用。
5. 标志0,F0。可以通过软件进行读写;不受硬件影响。
6. 辅助进位,AC。当加法产生从比特3到比特4的一次进位时,此标志位被置1。
7. 进位位,C。经常用于通用寄存器的比特计算,或是作为“布尔累加器”。
#### 累加器,A(0xE0)
该寄存器被用于大部分指令。
#### B寄存器(0xF0)
这被用作为对累加器的扩展,一般用于乘法和除法指令。
有256个单个比特位是可直接寻址的。这些是16个IRAM的位置,从0x20到0x2F,然后再加上16个特殊功能寄存器0x80,0x88,0x90,……,0xF8。这些字节的任一比特都可以通过各种逻辑操作以及条件分支直接访问。对于0x20到0x2F这一IRAM范围,一共有128位比特可直接独立寻址。每个比特位具有一个从0x00到0x7F的位地址。0x20字节处的比特0具有位地址0x00,而0x20字节处的比特7具有0x07的位地址。0x2F字节处的比特7则具有0x7F的位地址。位访问操作可以从所使用的指令类型来区分完整的字节访问操作(按位的源或目的操作数与一个字节的源或目的操作数进行对照)。
MCS-51汇编语言允许一种可选用的按位寻址表示法,形式为 **XX.B**,这里XX表示指定字节的地址,而B则表示该字节内的比特位置。比如以下指令:
```nasm
MOV C, 22h.3
```
则是将0x13位地址(即位于0x22字节地址处的比特3)处的布尔值搬移到进位标志。而对于Keil C51编译器中使用SFR的比特寻址语法糖,可参考此链接:http://www.keil.com/support/man/docs/c51/c51_le_sbit.htm
注意,PSW并不包含常用的负数标志(N)以及清零标志(Z)。对于前者,我们可以直接对累加器寻址其最高有效位进行判别,由于累加器是属于可按位寻址的SFR。而对于后者,有显式的跳转指令基于累加器是否为零。而且还有双操作数的比较与跳转操作。
## 指令集
8051的所有指令都具有1到3个字节的长度,由一个初始操作码字节,后面可跟多达2个字节的操作数构成。
1⁄4的操作码字节,**x0-x3**,用于不规则的操作码。
3⁄4的操作码字节,**x4-xF**,分配给了16个基本ALU指令,这些指令带有12个可能的操作数。操作码的最低有效半字节(**nibble**)选择了基本操作数,如下所示:
● **x8-xF**:寄存器直接访问,R0~R7。
● **x6-x7**:寄存器间接访问,`@R0`或`@R1`。
● **x5**:存储器直接访问,其下一个字节指定了IRAM或SFR的位置。
● **x4**:立即数,其下一个字节指定了一个8位常量。当操作数是一个目的操作数(`INC operand`,`DEC operand`)时,或该操作已经包含了一个立即数的源操作数(`MOV operand, #data`,`CJNE operand, #data, offset`)时,这就指定了累加器取而代之被使用了。
最高有效半字节如下指定了操作。并不是所有的操作都支持所有的寻址模式;尤其当要写主要操作数时,立即数模式是不可用的。指令助记符使用 *目的操作数*, *源操作数* 这一顺序。
只有`ADD`、`ADDC`、与`SUBB`指令集PSW标志,而`INC`、`DEC`则不会。`CJNE`指令只修改PSW的 **C** 位,该比特为从 *操作数1* - *操作数2* 结果的借位。
不规则的指令由64个操作码组成,这些指令具有更有限的寻址模式,外加从一些规则指令中的不可应用的模式里搜刮出来的若干操作码。
#### 某些指令介绍
● **`ACALL`** :该指令具有2个字节,需要2个周期执行。其用法为:
```nasm
ACALL LABEL
```
其中,LABEL用于标识某条指令地址的标签。
ACALL指令调用了位于指定地址的一个子例程。为了获取当前指令(即当前的ACALL指令)的下一条指令的地址,PC被递增两次。然后16位的PC被存储在栈上(按低字节序),最后栈指针SP被递增两次。这条指令不影响任何标志。
对于本指令,所要调用的子例程的地址按如下计算:取所递增的PC的高5位(A15到A11),再取 **ACALL** 指令的指令操作码的高3位(用于表示A8~A10),最后取该指令的第二个字节(用于表示A0~A7)。因而,所要调用的子例程的地址必须位于执行当前 **ACALL** 的下一条指令的同一2KB程序存储器区域内。换句话说,上述的 **LABEL** 用于表示11位的地址偏移。
其操作过程如下:
```nasm
PC = PC + 2
SP = SP + 1
(SP) = PC[7:0]
SP = SP + 1
(SP) = PC[15:8]
PC[10:0] = addr10 ; 这里,PC[15:11],即高5位保持不变
```
● **`LCALL`** :该指令具有3个字节,2个执行周期,其用法为:
```nasm
LCALL addr16
```
**LCALL**指令调用指定地址处的子例程。此指令首先对PC加3以生成当前该指令的下一条指令的地址。然后将结果以低字节序压入栈中,随后栈指针SP递增2。接着,PC的高位字节与低位字节分别从指令字的第二和第三个字节加载。最后程序的执行被传递给了新PC所指的地址处的子例程。这条指令不影响任何标志。
其操作过程如下:
```nasm
PC = PC + 3
SP = SP + 1
(SP) = PC[7:0]
SP = SP + 1
(SP) = PC[15:8]
PC = addr16
```