目录
51单片机储存器结构
80C51单片机的内部存储器分为内部程序存储器和内部数据存储器,这种程序与数据分开存放的存储器结构称为“哈佛”结构。所谓哈弗就是数据与程序分开存储,这也是51单片机的缺点:速度不快;对应的是冯诺依曼结构,是数据与程序存储一块。
程序存储器
单片机复位后,程序计数器(PC)的内容为0000H,从0000H单元开始执行程序。STC89C52系列HD版本单片机除可以访问片上Flash存储器外,还可以访问64KB的外部程序存储器。因此,对于STC89C52系列HD版本单片机而言,其利用EA引脚来确定是访问片内程序存储器还是访问片外程序存储器。当EA引脚接高电平时,STC89C52系列HD版本单片机首先访问片内程序存储器
当PC的内容超过片内程序存储器的地址范围时,系统会自动转到片外程序存储器。以STC89C54单片机的HD版本为例,当若EA引脚接高电平,单片机首先从片内程序存储器的0000H单元开始执行程序,当PC的内容超过3FFFH时系统自动转到片外程序存储器中取指令。此时外部程序存储器的地址从4000H开始。
另外中断服务程序的入口地址(又称中断向量)也位于程序存储器单元。在程序存储器中,每个中断都有一个固定的入口地址,当中断发生并得到响应后,单片机就会自动跳转到相应的中断入口地址去执行程序。外部中断0的中断服务程序的入口地址是0003H,定时器/计数器0中断服务程序的入口地址是000BH,外部中断1的中断服务程序的入口地址是0013H,定时器/计数器1的中断服务程序的入口地址是001BH等。由于相邻中断入口地址的间隔区间(8个字节)有限,一般情况下无法保存完整的中断服务程序,因此,一般在中断响应的地址区域存放一条无条件转移指令,指向真正存放中断服务程序的空间去执行。
数据存储器
内部RAM共256字节,可分为3个部分:低128字节RAM(与传统8051兼容)、高128字节RAM(Intel在8052中扩展了高128字节RAM)及特殊功能寄存器区。
低128字节的数据存储器既可直接寻址也可间接寻址。高128字节RAM与特殊功能寄存器区貌似共用相同的地址范围,都使用80H~FFH,地址空间虽然貌似重叠,但物理上是独立的,使用时通过不同的寻址方式加以区分。
高128字节RAM只能间接寻址,特殊功能寄存器区只可直接寻址,通过不同的寻址方式,区别使用相同的地址空间
寄存器A是专门用来放操作数和运算结果的,51单片机的所有运算几乎都要通过累加器A来实现,不通过累加器A实现不了。 而寄存器B是专门为乘法和除法设计的寄存器
特殊功能寄存器(SFRs)
特殊功能寄存器(SFR)是用来对片内各功能模块进行管理、控制、监视的控制寄存器和状态寄存器,是一个特殊功能的RAM区。STC89C52系列单片机内的特殊功能寄存器(SFR)与内部高128字节RAM貌似共用相同的地址范围,都使用80H-FFH,但特殊功能寄存器(SFR)必须用直接寻址指令访问。单片机上电后SP=0x07
程序计数器PC在物理上是独立的,不属于SFR之列。PC字长16位,是专门用来控制指令执行顺序的寄存器。单片机上电或复位后,PC=0000H,强制单片机从程序的零单元开始执行程序。
累加器ACC是8051单片机内部最常用的寄存器,也可写作A。常用于存放参加算术或逻辑运算的操作数及运算结果。
B寄存器在乘法和除法运算中须与累加器A配合使用。MUL AB指令把累加器A和寄存器B中的8位无符号数相乘,所得的16位乘积的低字节存放在A中,高字节存放在B中。DIV AB指令用B除以A,整数商存放在A中,余数存放在B中。寄存器B还可以用作通用暂存寄存器。
堆栈指针SP是一个8位专用寄存器。它指示出堆栈顶部在内部RAM块中的位置。系统复位后,SP初始化位07H,使得堆栈事实上由08H单元开始,考虑08H~1FH单元分别属于工作寄存器组1-3,若在程序设计中用到这些区,则最好把SP值改变为80H或更大的值为宜。STC89C52系列单片机的堆栈是向上生长的,即将数据压入堆栈后,SP内容增大。
直接与间接寻址
比如MOV A,#01H
MOV R0,A ;执行完这一句之后,R0=#01H, 直接寻址
MOV A,#20H
MOV @R0,A ;把#20H送给R0指向的单元0x01H,执行完之后01地址中存储的内容就变成#20H,间接寻址
汇编
新建一个空项目,并新建一个c文件,写如下代码
编译文件后,按下调试按钮,放大镜中间有个d字母就是它
代码的位置 指令的字节形式 指令
C:0x0000 020030 LJMP C:0030
//main函数开始的地方
C:0x0003 751000 MOV 0x10,#0x00 //给0x10 0x11这2个字节的位置赋值5
C:0x0006 751105 MOV 0x11,#0x05
C:0x0009 7B03 MOV R3,#0x03 //给R3赋值3
C:0x000B 7A00 MOV R2,#0x00
C:0x000D 7D02 MOV R5,#0x02 //给R5赋值2
C:0x000F 7C00 MOV R4,#0x00
C:0x0011 7F01 MOV R7,#0x01 //给R7赋值1,参数传递过程是从后向前的,在调用函数前会将参数赋值
C:0x0013 7E00 MOV R6,#0x00
C:0x0015 12001D LCALL add(C:001D) //调用add函数,会把返回地址0x0018压入栈
C:0x0018 8E08 MOV 0x08,R6 //add函数的结果放在0x08和0x09这2个字节的位置,这是计算的结果
C:0x001A 8F09 MOV 0x09,R7
C:0x001C 22 RET
//ADD函数
C:0x001D EF MOV A,R7
C:0x001E 2D ADD A,R5
C:0x001F FF MOV R7,A
C:0x0020 EE MOV A,R6
C:0x0021 3C ADDC A,R4
C:0x0022 CF XCH A,R7
C:0x0023 2B ADD A,R3
C:0x0024 CF XCH A,R7
C:0x0025 3A ADDC A,R2
C:0x0026 FE MOV R6,A
C:0x0027 E511 MOV A,0x11
C:0x0029 2F ADD A,R7
C:0x002A FF MOV R7,A
C:0x002B E510 MOV A,0x10
C:0x002D 3E ADDC A,R6
C:0x002E FE MOV R6,A
C:0x002F 22 RET //返回的时候会把栈顶的地址0x0018弹出给PC
//建立栈
C:0x0030 787F MOV R0,#0x7F
C:0x0032 E4 CLR A //将A寄存器置0
C:0x0033 F6 MOV @R0,A //间接寻址,将A的值0赋值给0x7F的位置
C:0x0034 D8FD DJNZ R0,C:0033 //循环,将0x7F到0x01位置赋值0
C:0x0036 758111 MOV SP(0x81),#0x11 //栈指针SP设置为0x11 SP寄存器位置是0x81 用直接寻址
C:0x0039 020003 LJMP main(C:0003)
在单片机中,DJNZ指令的具体功能是使操作数的内容减1,并判断操作数是否等于0,如果不等于0,则跳转至标号处,如果等于0,则顺序往下执行
C字母代表这是代码区,0x0000地址存放了一条3B大小的指令 LJMP C:0030
为什么第一条是跳转指令?
为啥单片机的SP复位后指向0x07, 因为0x00~0x07这8个字节用于R0 ~R7这8个寄存器
准确的说,栈空间的起始位置在0x08开始,所以a变量的位置是0x08~0x09, int变量占2B
C:0x0030处的代码建立了栈,Sp等于0x11,注意SP=0x11即指向第4个参数的低位字节的地址,说明单片机的sp指向的栈顶是有数据的
压栈指令会先将sp增加,留出空间,后填入数据
例如压入返回地址0x18, 先将sp+2指向0x13, 然后将0x12~0x13这2个字节的地方填入返回地址0x0018,注意地址的填入是反着填,0x12位置填入18,0x13位置填入00
当程序执行main函数结束后,即将执行RET指令,在执行前SP=0x11
执行后SP=0x0f,比0x11少了2,把之前SP指向的2个字节(0x10位置和0x11位置)当做返回地址赋给PC指针,而且赋值的时候把05作为高位,00作为低位,PC=0x0500
PC最后指向0x0500,并非程序所占用的空间,也就是超出了程序的大小空间,会提示access violation at C:0x0500 : no 'execute/read' permission
标签:字节,程序,存储器,51,MOV,单片机,地址,寄存器 From: https://www.cnblogs.com/cyfuture/p/16616909.html