学习心得之汇编

时间:2021-12-08 14:00:18

汇编是最接近机器的语言,它是直接对硬件进行操作的,了解汇编语言,就能更深入的了解硬件的结构。现详解MSC51的汇编语言。

汇编指令的属性:一指令要实现什么功能;二通过什么方式找到操作数

1.汇编指令

分为:数据传送类,算术运算类,控制转移类,逻辑运算类。

1.数据传送类,将数据从一处移往另一处,相当于C语言中的赋值语句。

如在函数内定义的局部变量:int a = 0x21;a++ ;翻译成汇编就是:

MOV R0,#21H

INC R0

如还有其它的变量,就将R0的值压栈,等到用的时候,再出栈;

如在函数外定义的全局变量:int a = 0x21;a++;

MOV R0,#81H     /*C语言中,编译器在编译时就已经将变量a的地址,分配好了*/

MOV A,#21H

INC A

MOV @R0,A

2.算术运算类,实现加减乘除等运算ADD/SUB/MUX/DIV/INC/DEC如同C语言中用到的+/-/*//。

3.控制转移类,实现程序的跳转LCALL/LJMP,如同C语言中的if/while/for/swith等条件选择/循环等语句,还有函数的调用,跳入中断服务子程序等。

4.逻辑运算类,实现逻辑运算及按位运算,AND/NOR/LCS/RCS/等相当于C语言中的&&/||/&/|/<</>>/~/等操作。

2.寻址方式

分为:立即数寻址,寄存器寻址,直接寻址,间接寻址,相对寄存器寻址,基址加变址寻址,相对基址加变址寻址。

上面的例子中,就已经涉及到了三种寻址方式。

MOV R0,#81H

R0为寄存器寻址,#81H为立即寻址

MOV @R0,A

@R0为寄存器间接寻址,A为寄存器寻址

这里R0存放的是地址值,但并不是所有的寄存器都有存址功能,具备存址功能的寄存器有:

R0/R1这两个8位通用寄存器,可寻址00H~FFH的256B空间,和DPTR这一个16位的地址寄存器可寻址0000H~FFFFH的64KB的空间。

那这两个寄存器除了寻址范围不同外,还有什么区别呢,这得从C51的存储结构说起,如下:

内部RAM:

00H~1FH:32B空间用于存放通用寄存器,共四组,每组有R0~R7八个寄存器,每个寄存器均为8位的,共4*8 = 32BYTE,通过设置PSW寄存器的RS1和RS2来选用哪组寄存器。

汇编语言可对这些寄存器直接操作,当使用C语言时,由系统根据情况来操作寄存器;

20H~2FH:16B可位寻址区,通过直接寻址位地址即可访问内存某位的值。如MOV C,21H

当使用C语言时,使用bdata进行定义存储类型时,系统会自动分配这一段区域的内存;或者使用bit数据类型定义时,系统会默认来分配这种存储类型。

30H~7FH:80B可直接寻址区,通过直接寻址字节地址即可访问内存某字节的值。如MOV A,32H

当使用C语言时,使用data存储类型时,系统会自动分配这一部分区域的内存,由于这一部分区域可直接寻址,因此速度很快。

80H~FFH:128B空间,里面存有部分SFR(特殊功能寄存器),另外的大部分区域都是不可直接寻址,只能通过寄存器间接寻址方式来寻址如:

MOV R0,#81H

MOV @R0,A     从而访问到地址为81H的值。

当使用C语言时,使用idata存储类型时,系统会自动分配这一部分区域的内存,由于这一部分除特殊功能寄存器外均为间接寻址区,因此速度相对较慢。

另外,我们经常有看到这样的指令:MOV R0,#30H   MOV @R0,A   这里30H的值不是可直接寻址区内的地址吗,即然可直接寻址,为什么还要用寄存器间接寻址来访问呢,其实这里的30H是外部RAM的空间,因为R0/R1可寻址00~FFH的256B空间,而实际只寻址了80H~FFH的内部RAM空间岂不是浪费了低128B可寻址资源,因此,规定R0/R1可访问内部RAM的80H~FFH空间,以及外部RAM的00~7F的空间,那外部RAM的80H~FF以及更大的空间怎么来访问呢,这里就用到DPTR这个16位的地址寄存器,毕竟大于FFH即超过8位的地址R0/R1就放不下了,这样就只能用16位来放,因此DPTR用来访问外部RAM的0080H~FFFFH的空间。其实,你应该已经发现了,内部RAM和外部RAM其实是共用了从00H~FFH的地址值。即这一段地址值既可以用来表示内部RAM也可以用来表示外部RAM的地址,那如何区分到底是内部RAM的地址还是外部RAM的地址就是通过寻址方式,以及用的是哪个地址寄存器来区分。