1. CPU中的内部结构
(0) CPU的组成结构与运行
CPU由ALU和控制器组成。
数据、指令编号存储在ROM中,指令从ROM中读出来之后传输到指令译码器(Instruction decoder)不同的指令会产生不同的指令信号,不同控制信号会作用于不同的电路
- 从ROM中取指令
- 指令译码器译码
- 送到ALU执行
CPU中的ALU只是运算器,不传输运算信号时,ALU不动。
那么就会涉及到控制器,控制指令的执行过程,引出了PC指针,PC向ROM提供了指令存储地址,PC会自动更新。PC控制的是取指的顺序。
(1) 寄存器
寄存器的英语为register,后面加s表示寄存器组。
-
CPU中的寄存器用于暂存信息,这些信息既可为将处理的字节数据,也可以为地址指向的数据。
-
大多数8051的寄存器都是八位的,但是有两个寄存器比较特殊:PC和DPTR。
-
8位寄存器由最高位MSB(最高有效位)D7到最低位LSB(最低有效位)D0组成。所以任何大于8位的数据处理前都会被分割为8位进行处理。
-
常用寄存器有A、B、R0-R7、DPTR(数据指针)、PC(程序计数器)
-
寄存器A也成为累加器,用于处理所有的算术和逻辑指令。
常用寄存器中,参与运算的寄存器:A B;构成RAM的寄存器:R0-R7;数据寄存器:DPRT;程序指针:PC
(2) 指令
指令分为三类:
- 数据传送
- 数据运算
- 程序执行顺序控制
为了详细介绍寄存器中A的作用,引出了两个指令:MOV和ADD
加井号表示具体的数(立即数=常数,存放在ROM中),不加井号代表地址。
在读取数据时,如果有井号,则读取RAM中具体地址的房间里中的数,如果没有井号,则直接读取具体的寄存器。
MOV
MOV指令简单来说就是用于复制。
MOV destination,source ;复制源操作数到目的操作数中
指令需要从后往前读,也就是将源操作数复制到目的操作数中
MOV A,#44H ;将数值十六进制44放在A寄存器中
MOV A,R1 ;将寄存器R1中的数值放在R1中
MOV R2,#3FH ;将数值十六进制3F放在寄存器R2中
MOV R3,#321H ;出错,因为寄存器是8位,最多只能存储FFH
MOV R2,#0F9H ;需要在井号后添加0,因为如果前面是字母的话,汇编器会混淆,无法识别是数字 ;还是地址。为了避免这样的事情发生,如果第一个为字母,需要在前面添加一个 ;0,避免混淆
MOV R2,#456 ;出错。存储的为立即数,寄存器最高位8位,可存储十进制的值最大为255, ;456>255,所以会出错
MOV R2,17H
根据上述例子可以得出,如果想要直接存储数值,需要添加井号,若不添加井号,代表存储进寄存器的值为存储单元17H中的数。
ADD
ADD指令简单来说就是相加。
ADD A,源操作数 ;将源操作数与A相加,添加到A(累加器)中
指令同样需要从后前读,使用ADD指令需要注意以下几项:
- 使用ADD指令时,必须要使用累加器,不可以使用其他寄存器
- 可以直接对A添加立即数
MOV A,#24H ;可以先将立即数存入A中
MOV R2,#34H ;将立即数存入寄存器R2中
ADD A,R2 ;将R2中的内容添加到A中
除此之外,也可以直接将A加具体的立即数
MOV A,#25H
ADD A,#34H
8051中程序计数器和数据指针是16位寄存器。
PC指针总是指向ROM地址,向ROM中
PC指针总是指向下一条要执行的指令(取指令完成的时候,PC自动更新到下一条要执行的指令。)
一条指令一般占两个字节,按照顺序结构,PC会指向0002
PC指针在51单片机是不可改写的(无法编程),因为PC指针自动更新
2. 8051汇编编程
(1) 汇编语言结构
汇编语言程序是由一连串的汇编指令组成。
一条汇编指令是由助记符和可选的1个或两个操作数组成
- 助记符:给CPU的指令,告诉CPU如何对操作数进行操作
- 助记符就是ADD、MOV
- 助记符可以产生操作码
- 操作数:将要被操作的数据
汇编语言程序要么由汇编语言指令:ADD、MOV组成;要么是由指示符(伪指令)组成
- 汇编语言指令是给CPU的指令
- 指示符(伪指令)是给汇编器的指令
- ORG:通知汇编器将操作数放在储存单元0中
- END:告诉汇编器编译结束。
- 伪指令不产生操作码
3. 程序计数器与ROM
(1) 程序计数器PC
8051的一个16位寄存器为PC,PC指向下一条将要执行指令的地址。当CPU从ROM中取得操作码时,PC会自动增加并指向下一条指令。
16位计数器代表8051可以访问的空间为0000H~FFFFH,共64kb。
(2) 复位唤醒
控制器在每次上电时都会在存储地址0000处唤起。也就是上电后,8051程序计数器PC的值就是0000,第一个操作码就存储在ROM地址0000H中。
(3) 放置代码与ROM中
首先汇编语言要转成机器语言供编译器读取。0000地址含有7D,是将值装载到寄存器R5的操作码,而地址0001就包含装载到R5的操作数。
7D为操作码,25为操作数。可以看出,操作码和操作数分别占据一个ORM地址。
(4) 程序执行过程
- 上电后,PC值为0000,从程序ROM的0000地址得到第一个操作码。执行操作码的时候,CPU将处理操作数。单片机处理操作码的时候PC会自增,指向0002,重复上述操作。
- 指令有的是1B指令,也就是占据一个内存位置。有的指令是2B指令,会占据两个内存位置。
- 程序计数器PC会一直自增,直到所有的指令都被取走并被执行。而程序技术器指向下一条即将执行的指令也说明了微处理器称PC为指令指针的原因。
(5) 单字节的执行程序
程序会存储在ROM中,假设ROM中存在程序
- 8051上电,程序计数器的值为0000,从0000读取第一个操作码7D,讲操作数装载到寄存器R5中,操作数为地址0001
- 完成上述过程代表一条指令完成,随后程序计数器会自增,指向0002,再读取0002的操作码,重复上述过程。
- 有些指令只占据一个地址,那么就执行对应的操作码即可。
(6) ROM存储映射
求片上ROM的地址映射方法如下:
- 将ROM的存储大小改为字节B
- 将其改为16进制
- 因为地址是从0开始,所以改为16进制的时候,最大值需要减1
例题:
- 4KB,转为字节为4096B,再将其转为16进制为1000H,因为地址从0000开始,所以ROM存储映射为0000-0FFFH
- 16KB是4KB的四倍,所以为0000-3FFFH
- 32KB是16KB的两倍,所以为0000-7FFFH
4. 数据类型和指令
1. 定义指令
定义指令用于定义8位数据,定义数据的时候,数据可以是任何进制或ASCII码的形式。在定义数据的时候,需要在数据后加上具体进制的符号。表示ASCIII码还需要使用引号
DATA1: DB 28 ;十进制
DATA2: DB 00110101B ;二进制
DATA3: DB 39H ;十六进制
DATA4: DB "2591" ;ASCII码
DATA5: DB 'O' ;单字块的ASCII码
2. 汇编指令
1. ORG:初始
ORG用于表示起始地址,默认为16进制
2. EQU:等同
EQU用于定义常量,不占据存储器空间。
COUNT EQU 25
...
MOV R3 #COUNT
3. END:结束
告诉汇编器8051这是最后一行,之后的源代码都会忽略
5. 8051标志位和PSW寄存器
在上述的CPU内部工作原理中,提到了运算时如果超的话,会将标志位存储在标志位中
1 PSW程序状态字寄存器
PSW寄存器是8位寄存器,但8051只使用了6位,2位是用户自定义标志位。
6位中4位是状态标志位。CY:进位,AC辅助进位,P奇偶校验位,OV溢出位。
第1位和第5位用于用户自行选择,第三第四位为RS0和RS1,用于寄存器组选择。
1. CY 进位标志
当有来自D7的进位时,该位置1,只有在8位的加减法操作后才会受影响。也可以通过SETB C
或CLR C
来将这个位置置1或是置0
2. AC 辅助进位标志
当执行加或减操作发生在D3或D4的进位时,该为置1,否则清0。该标志用于完成BCD的算术运算
3. P 奇偶标志
P反映累加器A中1的数目。如果寄存器A包含奇数个1,那么P=1。如果包含偶数个1,那么P=0
4. OV 溢出标志
如果运算结果太大导致最高位溢出到符号位,那么标志位置1
2. 指令对PSW的影响
6. 寄存器组和栈
8051有128B的RAM
1. RAM分配
8051的RAM是128字节,分配的地址范围为00-7FH。
- 00-1F(十六进制)32字节的寄存器组和栈
- 20H-2FH,16字节的位可寻址 读/写存储器
- 30H-7FH,80字节的读/写存储,也称为高速暂存器。
2. 寄存器组
00-1F用于分配寄存器组和栈
将这32字节分配到4个寄存器组,每组有8个寄存器:R0-R7
- 第0组寄存器:00-07H,R0-R7,默认寄存器
- 第1组寄存器:08H-0FH, R0-R7
- 第3组寄存器:10F-17H, R0-R7
- 第4组寄存器: 18H-1FH, R0-R7
由于第一组寄存器和栈公用相同的RAM空间,所以在编程时尽量回避第一组寄存器。或另开辟一块RAM空间给栈。
通过PSW寄存器中位选择D3,D4来修改寄存器组。
3. 进一步理解RAM存储
除了对特定的寄存器进行存储,还可以通过地址来对RAM进行存储值
如果想要使用其他寄存器组,可以通过SETB
来将PSW中的D3、D4位进行修改来改变寄存器组。
4. 压栈与出栈
8051中栈指针指向栈的最后一位,每压入栈中一个元素,栈指针会加1.
因为栈和第一组寄存器组占据的RAM空间一样,所以从07开始
5. 栈上限(需要问老师)
6. 解决栈与寄存器组1的冲突
为了使用寄存器1,需要将栈重新分配存储空间。可以分配RAM中60H或更高的位置来分配地址给栈。
7. 提高CPU效率的办法
- 增加芯片的时钟效率
- 增加导线变成哈佛体系结构
- 改变CPU的内部结构,使用RISC结构。