汇编语言指令系列

简介: 汇编语言指令系列

(一)七大寻址方式

① 立即寻址:

以"#"开头,例如"#41H",例如:MOV A, #52H

② 寄存器寻址:

包括的寄存器有:

对于16位操作数,寄存器可以是:AX、BX、CX、DX、SI、DI、SP和BP等。

对于8位操作数,寄存器可以是AL、AH、BL、BH、CL、CH、DL、DH。

例如:MOV  BX, AX ;将AX寄存器中存放的数据赋给BX


③ 直接寻址:

例如 MOV R0,3AH,其中3AH是一个地址,而不像立即寻址那样是一个值


④ 寄存器间接寻址:

以"@"为标志,@R0表示取寄存器的值的值,例如(R0)=40H,(40H)=30H,那么@R0=30H,例如:MOV A,@R0 ;(A)=30H

包含的寄存器有:

@Ri(i=0,1)、@DPTR

⑤ 变指寻址:

变址寻址的形式一般为:操作数的地址=基址(存在于DPTR或PC中)+偏移量(存在于累加器A中)


@A+PC,@A+DPTR


例如:(A)=#0FH,(DPTR)=#2400H,执行MOVC A,@A+DPTR后,(A)=(240FH)


因为A+DPTR=240FH,所以MOVC A,@A+DPTR就是将240FH中的内容赋给A

⑥ 相对寻址:

相对寻址的形式一般为:目的地址=转移指令所在的地址+转移指令字节数+rel


其中,偏移量rel是带符号8位二进制补码数:-128~+127。


例如,2000H: SJMP 08H

该指令占据2个字节,转移偏移量为08,所以执行该程序PC地址为2000H,指令后,程序跳转到2000H+2H+08H=200AH

⑦ 位寻址:

对位地址中的内容进行位操作的寻址方式称为位寻址。由于单片机中只有内部RAM和特殊功能寄存器的部分单元有位地址(内RAM中位寻址区20H~2FH单元的128位(位地址为00H~7FH)以及11个特殊功能寄存器的83个可寻址位),因此位寻址只能对有位地址的这两个空间进行寻址操作。


直接寻址和位寻址的区别:


直接寻址:


直接寻址,是把数据直接写入当前地址,或者把当前地址的内容读出如:MOV A,90H,就是把地址90H中的内容写入到寄存器A中。


位寻址:


对内部RAM和特殊功能寄存器具有位寻址功能的某位内容进行置1和清0操作。

位地址一般以直接位地址给出,位地址符号为“bit”,写入和读出的是一个位bit变量。如:


MOV C,7AH,就是把地址7AH中的第1位内容写入位C变量,而内容只能是0、1。


MOV C,2FH.2,就是把地址2FH中的第2位的内容写入到C变量。内容只能是0、1。一个字节由8位组成。

例如:MOV A,00H和MOV C,00H,前者是将RAM中地址为00H的8位内容传递给A,后者是将位寻址区(20H-2FH)中的地址为00H的1位内容传递给C。这两个00H不是在同一个地址。

(二)重要指令

指令符号

A:累加器,用于运算及存放数据。


B:专用寄存器,用于MUL和DIV指令中,存放第二操作数、乘积高位字节。


CY:进位标志位,或布尔处理器中的累加器。


bit:内部RAM或专用寄存器中的直接寻址位。


/bit:位地址单元内容取反。


DPTR:16位数据指针,也可作为16位地址寄存器。


Rn:工作寄存器中的寄存器R0、R1...R7之一


Ri:工作寄存器中的寄存器R0或R1


#data:8位立即数


#data16:16位立即数


direct:片内RAM或SFR的地址(8位)


@:间接寻址寄存器


addr11:11位目的地址


addr16:16位目的地址


rel:补码形式的8位地址偏移量,便宜范围为-128~127


/:位操作指令中,该位求反后参与操作,不影响该位


X:片内RAM的直接地址或寄存器


(X):相应地址单元中的内容


→:箭头左边的内容送入箭头右边的单元内

1)转移指令

①MOV A,Rn; Rn-->(A) 读取片内RAM

②MOVX A,@DPTR;((DPTR))-->(A) 读取片外RAM

③MOVC A,@A+DPTR ;((A)+(DPTR))-->(A) 读取ROM的值

(2)堆栈指令

①PUSH direct;

(sp)+1-->(sp),(direct)-->((sp))

栈顶指针SP+1,然后将直接地址中的内容压入栈;

②POP direct;

((sp))-->(direct),(sp)-1-->(sp)

将堆栈栈顶内容弹出堆栈,栈顶指针SP-1;

(3)加减

ADD类——指令不带进位的加法运算指令

ADD A,Rn ;A与Rn中内容相加后再送到A;(A)+(Rn)->(A)

ADDC类——指令带进位的加法运算指令

ADDC A;Rn A与Rn中内容在进位状态相加后再送到A;(A)+(Rn)+(CY)->(A);

SUBB类

SUBB A,Rn; A减Rn内容和进位标志;(A)-(Rn)-(CY)->(A)

INC类(加1)、DEC类(减1)

INC A ;(A)+1->(A);        DEC A;(A)-1->(A)

4)乘除

MUL AB;

(A)××(B)-->低八位存放在A(7~0),高八位存放在B (15~8)

DIV AB;

(A)/(B)-->(A)存放商,(B)存放余数

(5)位操作

ANL类指令

功能:将源操作数的内容和目的操作数的内容按位“与”,结果存入目的操作数指定单元。

ANL A,Rn; A和Rn中内容相与后的结果存入A;(A)ꓵ(B)->(A) 同1为1

ORL类指令

功能:将源操作数内容和目的操作数内容按位“或”,结果存入目的操作数指定单元中。

ORL A,Rn ;A和Rn中内容相或后的结果存入A;(A)ꓴ(B)->(A) 有1为1

XRL类指令

功能:将两个操作数指定内容按位“异或”,结果存入目的操作数指定单元中。

XRL A,Rn ;A和Rn中内容按位异或后的结果存入A;(A)⊕(B)->(A) 不同为1,相同为0

(6)循环移位指令

RL A ;A中内容循环左移,执行该指令一次左移一位,例如:

(A)=00001111,循环左移后,最高位移动到了最低位(A)=00011110

RR A ;A中内容循环右移,执行该指令一次右移一位,例如:

(A)=00001111,循环右移后,最低位移动到了最高位(A)=10000111

总结:左移一位=A*2;右移=A÷2


(7)无条件转移指令

LJMP add16 ;无条件跳转到add16地址,可在64KB范围内转移,称为长转移指令

AJMP add11 ;无条件转向add11地址,在2KB范围内转移

SJMP rel ;相对转移,rel是偏移量,8位有符号数,跳转范围-128~127

JMP @A+DPTR ;散转指令,无条件转向A与DPTR内容相加后形成的新地址

(8)条件转移指令

功能:根据某种特定条件转移的指令,条件满足时转移,条件不满足时则按顺序执行下面的指令。

JZ rel ;A=0则转向PC+2+rel→PC;A≠0则顺序执行

注:在 8051 中,指令长度为 2 字节(包括操作码和偏移量)。因此,在计算跳转目标地址时,需要将当前指令地址加上 2,才能正确计算跳转目标地址。

JNC rel ;CY≠0则转向PC+2+rel→PC;CY=0则顺序执行

CJNE A,#data,rel; A≠data,则转向PC+3+rel→PC;更详细点就是,当A>data,CY=0;当A<data,CY=1;当A=data,PC+3→PC顺序执行

注:在 8051 中,指令长度为 3 字节(包括操作码、立即数和偏移量)。因此,在计算跳转目标地址时,需要将当前指令地址加上 3,才能正确计算跳转目标地址。

DJNZ Rn,rel ;Rn-1→Rn,Rn≠0转向PC+2+rel→PC;Rn=0,PC+2→PC顺序执行

(9)调用、返回、空操作指令

LCALL addr16 ;调用入口地址为addr16的子程序,可调用64KB范围内的子程序

ACALL addr11 ;调用入口地址为addr11的子程序,可调用2KB范围内的子程序

RET ;放在子程序最后,使程序返回到主程序断点处


((SP))-->(PCH) (SP)-1-->(SP) ((SP))-->(PCL) (SP)-1-->(SP)


就是将SP指向的地址的值赋给PC的高八位,再将(SP-1)的值,赋给PC的低八位,再把SP的值-1

RETI ;中断返回指令,该指令用于中断服务程序,使中断结束后返回主程序断点处

NOP ;空操作,执行该指令CPU只进行取指令、译码,不进行其他操作


(10)取反、清0指令

CPL A ;累加器A内容按位取反;(A取反)->(A)

CLR A ;累加器A清0;0->(A)


(11)置0/1指令

CLP C ;累加器清/置0;0->(C)

SETB C;C置1;1->(C)

综合题型:


已知MCS-51单片机的外部RAM中地址2000H开始连续存储了100个字节数据,求其最大值保存于内部RAM的30H单元,最小值保存于内部RAM的31H单元。试用汇编语言编写完整程序。


   ORG 0000H

   LJMP MAIN


   ORG 0100H

MAIN:    MOV DPTR,#2000H        ;指针初始化

   MOV R2,#99                              ;循环次数

   MOVX A,@DPTR                       ;取第一个字节数据

   MOV 30H,A                                ;将累加器A的值存储到内存地址30H中,初始化最大值。

   MOV 31H,A                                ;将累加器A的值存储到内存地址31H中,初始化最小值。

   INC DPTR                                  ;指针+1指向第二个数据


NEXT:    MOVX A,@DPTR             ;取一个字节数据

   MOV B,A                                    ;暂存该数据

   CLR C                                        ;CY=0清除借位标志

   SUBB A,30H                              ;A-30H-CY->A

   JC X1                                         ;CY=1,即A<30H转移到X1

   MOV 30H,B                               ;更新最大值

X1:    MOV A,B                              ;恢复该数据

   CLR C

   SUBB A,31H                               ;A-31H-CY->A

   JNC X2                                       ;CY=0,即A>=31H则转移到X2

   MOV 31H,B                                ;更新最小值

X2:    INC DPTR                             ;指针+1指向下一个数据

   DJNZ R2,NEXT                          ;R2-1,不等于零则循环


WAIT:    SJMP  WAIT

   END

(三)常见指令集合

•数据传送类指令
1.内部数据传送指令MOV

(1)以累加器为目的操作数


      MOV A,Rn       ;Rn→A


      MOV A,direct     ;(direct)→A


      MOV A,@Ri       ;(Ri)→A


      MOV A,#data    ;data→A


将源操作数指定内容送到A中。

(2)以寄存器Rn为目的操作数

       MOV Rn,A

   MOV Rn,direct

   MOV Rn,#data

这组指令功能是把源操作数指定的内容送入当前工作寄存器,源操作数不变。(注:两个操作数不能同时出现Rn)

(3) 以寄存器间接地址为目的字节


       MOV @Ri,A                   ;A →(Ri)


       MOV @Ri,direct             ;(direct) →(Ri)


       MOV @Ri,#data             ; data →(Ri)


  功能:把源操作数指定的内容送入以R0或R1为地址指针的片内存储单元中。

举个例子:

      MOV @R0,A

      MOV @R1,20H

      MOV @R0,#34H

(4)以直接地址为目的操作数


      MOV direct,A


      MOV direct,Rn


      MOV direct1,direct2


      MOV direct,@Ri


      MOV direct,#data


这组指令功能是把源操作数指定的内容送入由直接地址指出的片内存储单元。

举个例子:

      MOV 20H,A

      MOV 20H,R1

      MOV 20H,30H

      MOV 20H,@R1

      MOV 0A0H,#34H

      MOV P2,#34H

(5)16位数据传送指令

MOV  DPTR,#data16

注:8051是一种8位机,这是唯一的一条16位立即数传递指令。

功能:将一个16位的立即数送入DPTR中去。其中高8位送入DPH,低8位送入DPL。

举个例子:


MOV DPTR,#1234H


执行完了之后DPH中的值为12H,DPL中的值为34H。


如果我们分别向DPH,DPL送数,则结果也一样。


  如下面两条指令:  MOV DPH,#35H


                                 MOV DPL,#12H。


  则就相当于执行了  MOV DPTR,#3512H。  

(6)查表指令

   MOVC    A,@A+DPTR      ;A←((A)+(DPTR))

   MOVC    A,@A+PC   ;A←((A)+(PC))

举个例子:


已知RAM单元40H中有一个0~5范围内的数,而ROM中0200H开始保存有一个立方表,用查表指令编出能查出该数立方值的程序。程序及执行后的结果如下:


             MOV      A,40H


             MOV  DPTR,#LAB


             MOVC    A,@A+DPTR


             … …


             LAB: DB  0,1,8,27,64,125


若(40H)为2,查表得8并存于A中  

2.外部数据传送指令MOVX

           MOVX  A,@Ri

           MOVX  @Ri,A

           MOVX  A,@DPTR

           MOVX  @DPTR,A

注:


(1)在51中,与外部存储器RAM打交道的只可以是A累加器。所有需要送入外部RAM的数据必需要通过A送去,而所有要读入的外部RAM中的数据也必需通过A读入。


在此我们可以看出内外部RAM的区别了,内部RAM间可以直接进行数据的传递,而外部则不行。


比如,要将外部RAM中某一单元(设为0100H单元的数据)送入另一个单元(设为0200H单元),也必须先将0100H单元中的内容读入A,然后再送到0200H单元中去。


(2)要读或写外部的RAM,当然也必须要知道RAM的地址,在后两条指令中,地址是被直接放在DPTR中的。而前两条指令,由于Ri(即R0或R1)只是8位的寄存器,所以只提供低8位地址。高8位地址由P2口来提供。

(3)使用时应先将要读或写的地址送入DPTR或Ri中,然后再用读写命令。


 例:将外部RAM中100H单元中的内容送入外部RAM中200H单元中。


      MOV   DPTR,#0100H


      MOVX  A,@DPTR


      MOV   DPTR,#0200H


      MOVX  @DPTR,A

3.堆栈操作指令

      PUSH direct  ;SP<---SP+1,(SP)<---(direct)


      POP direct   ; (direct) <---(SP), SP<---SP-1


第一条为压入指令,就是将direct中的内容送入堆栈中,第二条为弹出指令,就是将堆栈中的内容送回到direct中。


例:          MOV  SP,#5FH


                MOV  A,#100


                MOV  B,#20


                PUSH  ACC


                PUSH  B


则执行第一条PUSH ACC指令是这样的:将SP中的值加1,即变为60H,然后将A中的值送到60H单元中,因此执行完本条指令后,内存60H单元的值就是100,同样,执行PUSH B时,是将SP+1,即变为61H,然后将B中的值送入到61H单元中,即执行完本条指令后,61H单元中的值变为20。

4.数据交换指令

      XCH  A, Rn          ;A←→Rn


      XCH  A, direct      ;A←→(direct)


      XCH  A, @Ri        ;A←→(Ri)


      XCHD A, @Ri        ;A.3~A.0←→(Ri).3~(Ri).0


      SWAP A             ;A.3~A.0←→A.7~A.4

举个例子:


      已知A中的内容为34H


      MOV  R6, #29H        ;R6=29H


      XCH  A, R6               ;A=29H,R6=34H


      SWAP A                       ;A=92H


注:29H的二进制表示是0010 1001,低4位为1001,高4位为0010。经过 SWAP A 操作后,低4位和高4位被交换,低4位变为0010,高4位变为1001,即92H。因此,执行完 SWAP A 操作后,A中的值变为了92H。


      XCH  A, R6                ;A=34H,R6=92H


      XCHD A, @R0           ;A=36H,(R0)=54H(设原来R0指向的单元的内容为56H)


注:这里使用XCHD(Exchange Dual)指令,交换累加器A的低4位和R0寄存器指向的内存单元的低4位。这里假设R0指向的内存单元的内容为56H。由于A的低4位为6H,将6H与内存单元中的4H进行交换,所以A=36H,而内存单元的内容变为了92H。

•算术运算类指令

1.加法指令

(1)不带进位位的加法指令


      ADD A,#data            ; A+data→A


      ADD A,direct            ; A+(direct )→A


      ADD A,Rn                ; A+Rn→A


      ADD A,@Ri             ; A+(Ri)→A


用途:将A中的值与源操作数所指内容相加,最终结果存在A中。

举个例子:

      ADD A,#47H

      ADD A,34H

      ADD A,R7

      ADD A,@R0

MOV A,#0AEH  ;-82D


ADD A,#81H   ;-127D


说明:


首先,使用了汇编指令 MOV A, #0AEH,这将立即数 0xAE 装入寄存器 A 中,它的二进制表示是 10101110。


接着,使用了汇编指令 ADD A, #81H,这是对寄存器 A 执行加法运算,加上立即数 0x81,它的二进制表示是 10000001。


结果:C=1,AC=0,OV=1,P=1


解释:


C(进位标志位)用于指示加法或减法运算中最高位的进位情况。在这种情况下,C=1 表示发生了进位。


AC(辅助进位标志位)用于指示加法或减法运算中从低位到高位的辅助进位情况。在这种情况下,AC=0 表示没有发生辅助进位。


OV(溢出标志位)用于指示有符号数运算中是否发生溢出。在这种情况下,OV=1 表示发生了溢出。


P(奇偶校验标志位)用于指示结果中二进制表达式中1的个数是奇数还是偶数。在这种情况下,P=1 表示结果的二进制表达式中有偶数个1。


无符号数运算:


结果为 0xAE + 0x81 = 0x12F,或者说 174 + 129 = 303(十进制)。


带符号数运算:


0xAE 和 0x81 被解释为有符号数,分别对应 -82 和 129。


然后进行带符号加法:-82 + 129 = 47(十进制),对应的十六进制表示为 2F。


对于带符号数的运算:OV=1是有错误的

(2)带进位的加法指令


      ADDC A,Rn        ; A+Rn+CY→A


      ADDC A,direct   ; A+(direct )+CY→A


      ADDC A,@Ri      ; A+(Ri)+CY→A


      ADDC A,#data   ; A+data+CY→A


用途:将A中的值和其后面的值以及进位位C中的值相加,最终结果存在A,常用于多字节数运算中。


说明:由于51单片机是一种8位机,所以只能做8位的数学运算,但8位运算的范围只有0~255,这在实际工作中是不够的,因此就要进行扩展,一般是将2个8位(两字节)的数学运算合起来,成为一个16位的运算,这样,可以表达的数的范围就可以达到0~65535。

举个例子:

先做67H+A0H=107H,而107H显然超过了0FFH,因此最终保存在A中的是07H,而1则到了PSW中的CY位了。换言之,CY就相当于是100H。

然后再做10H + 30H + CY,结果是41H,所以最终的结果是4107H。

设:1067H存在R1R0中, 30A0H存在R3R2中,计算R1R0+R3R2,结果存在R5R4中


MOV  A,R0


ADD  A,R2   ;R0+R2→A和CY


MOV R4,A


MOV  A,R1


ADDC A,R3   ;R1+R3+CY→A和CY


MOV R5,A

再举个例子:

先做67H+20H=87H,没有超过0FFH,因此最终保存在A中的是87H,而PSW中的CY=0。

然后再做10H + 30H + CY,结果是40H,所以最终的结果是4087H。

(3)加1指令


INC  A                ;A+1→A,影响P标志


INC  Rn              ;Rn+1→Rn


INC  direct          ;(direct)+1→(direct)


INC  @Ri            ;(Rn)+1→(Rn)


INC  DPTR          ;DPTR+1→DPTR


功能很简单,就是将后面目标中的值加1。

举个例子:


A=12H,R0=33H,(21H)=32H,(34H)=22H,DPTR=1234H。


连续执行下面的指令:


  INC A        ;A=13H


  INC R0     ;R0=34H


  INC 21H   ;(21H)=33H


  INC @R0  ;(34H)=23H


  INC DPTR ;DPTR=1235H

2.减法指令

(1)带借位的减法指令


SUBB A,Rn       ; A-Rn-CY→A


SUBB A,direct   ; A-(direct )-CY→A


SUBB A,@Ri     ; A-(Ri)-CY→A


SUBB A,#data    ; A-data-CY→A


将A中的值减去源操作数所指内容以及进位位C中的


值,最终结果存在A中。


如: SUBB A,R2


设: A=C9H,R2=55H,CY=1,


执行指令之后,A中的值为73H。

注:没有不带借位的减法指令,如果需要做不带位的减法指令(在做第一次相减时),只要将CY清零即可。对带符号数,要注意OV标志。如果OV=1,则出错。


3.减1指令

DEC A                ;A-1→A,影响P标志


DEC Rn              ;Rn-1→Rn


DEC direct          ;(direct)-1→(direct)


DEC @Ri            ;(Rn)-1→(Rn)


与加1指令类似。

4.十进制调整指令

DA  A


在进行BCD码加法运算时,跟在ADD和ADDC指令之后,用来对BCD码加法运算结果进行自动修正。


例:A=0001 0101BCD(代表十进制数15)


      ADD A,#8        ; A=1DH,按二进制规律加


      DA   A                 ; A=23H,按十进制规律加

举个例子:

例:编写程序完成68+89的BCD加法程序,并对调整过程进行分析。

解:二进制加法和十进制调整过程为:这里的低4位指的是低4位相加:1000+1001>9,下面同理。

5.乘法指令

MUL AB        ;A×B→BA


此指令的功能是将A和B中的两个8位无符号数相乘,两数相乘结果一般比较大,因此最终结果用1个16位数来表达,其中高8位放在B中,低8位放在A中。在乘积大于FFH时,0V置1,否则OV为0;而CY总是0。


例:  A=4EH,B=5DH,执行指令MUL  AB后,乘积是1C56H,


所以在B中放的是1CH,而A中放的则是56H。OV=1,P=0

5.除法指令

DIV AB          ;A÷B的商→A,余数→B


此指令的功能是将A中的8位无符号数除B中的8位无符号数(A/B)。除了以后,商放在A中,余数放在B中。


CY和OV都是0。如果在做除法前B中的值是00H,也就是除数为0,那么0V=1。


如:A=11H,B=04H,执行指令DIV AB后,


结果:A=04H,B=1。其中CY=0,OV=0,P=1

算数运算类指令对标志位的影响

试编写1234H-0FA3H的程序段,将结果高8位存入51H, 低8位存入50H单元。

CLR C

MOV  A,#34H

SUBB A,#0A3H

MOV  50H,A

MOV  A,#12H

SUBB A,#0FH

MOV  51H,A

•逻辑运算指令

1.逻辑与指令

除了目的操作数为ACC的指令影响奇偶标志P外,一般不影响标志位。


ANL A,Rn                ;A∧Rn→A


ANL A,direct            ;A∧(direct)→A


ANL A,@Ri              ;A∧(Ri)→A


ANL A,#data            ;A∧data→A


影响P标志


ANL direct,A            ;(direct)∧A→(direct)


ANL direct,#data     ;(direct)∧data→(direct)


后两条指令,若直接地址为I/O端口,则为“读-改写”操作。

举个例子:

再举个例子:


MOV A,#45H         ;A=45H


MOV R1,#25H        ;R1=25H


MOV 25H,#79H       ;(25H)=79H


ANL A,@R1             ;45H∧

79H=41H-->A


ANL 25H,#15H        ;79H∧

15H=11H-->(25H)


ANL 25H,A               ;11H∧

41H=01H-->(25H)

2.逻辑或指令

ORL A,Rn          ;A∨Rn→A


ORL A,direct      ;A∨(direct)→A


ORL A,@Ri        ;A∨(Ri)→A


ORL A,#data      ;A∨data→A


影响P标志


ORL direct,A      ;(direct)∨A→(direct)


ORL direct,#data ;(direct)∨data→(direct)


后两条指令,若直接地址为I/O端口,则为“读-改写”操作。

举个例子:

再举个例子:


MOV A,#45H         ;A=45H


MOV R1,#25H       ;R1=25H


MOV 25H,#39H     ;(25H)=39H


ORL A,@R1           ;45H∨

39H=70H-->A


ORL 25H,#13H       ;39H∨

13H=3BH-->(25H)


ORL 25H,A             ;3BH∨

7DH=7FH-->(25H)

3.逻辑异或指令

XRL A,Rn                ;A ⊕Rn→A


XRL A,direct            ;A ⊕(direct)→A


XRL A,@Ri              ;A ⊕(Ri)→A


XRL A,#data            ;A ⊕ data→A


影响P标志


XRL direct,A             ;(direct) ⊕A→(direct)


XRL direct,#data      ;(direct) ⊕data→(direct)


后两条指令,若直接地址为I/O端口,则为“读-改写”操作。

再举个例子:

MOV A,#45H          ;A=45H


MOV R1,#25H        ;R1=25H


MOV 25H,#39H      ;(25H)=39H


ORL A,@R1            ;4539H=7CH-->A


ORL 25H,#13H        ;39H13H=2AH-->(25H)


ORL 25H,A               ;2AH7CH=56H-->(25H)

4.清0和取反指令

取反:CPL  A ;/A→A

例:若A=5CH,执行CPL  A

   结果:A=A3H

清0:CLR  A       ;0→A

•循环移位指令

注:后两条指令,影响P标志和CY。

举个例子:若A=5CH,CY=1,执行RLC A后,结果:A=B9H,CY=0,P=1。

对RLC、RRC指令,在CY=0时,RLC相当于乘以2,RRC相当于除以2

把累加器A中的低4位状态,通过P1口的高4位输出, P1口的低4位状态不变。


ANL  A,#0FH       ;屏蔽A的高4位


SWAP  A


ANL  P1,#0FH     ;清P1口高4位


ORL  P1,A         ;P1口高4位输出A的低4位

•控制转移类指令
1.无条件转移指令

•绝对转移类指令:AJMP addr 11

•长转移类指令:LJMP addr16

•短转移指令:SJMP rel

•间接转移指令:JMP @A+DPTR

•上面的前三条指令,统统理解成:PC值改变,即跳转到一个标号处。

跳转的范围不同:


绝对转移类指令:AJMP addr11         2KB


长转移类指令:LJMP  addr16            64KB


短转移指令:SJMP  rel                        -128~127


指令构成不同:


AJMP、LJMP后跟的是绝对地址,而SJMP后跟的是相对地址。


指令长度不同:


原则上,所有用SJMP或AJMP的地方都可以用 LJMP来替代。

•第四条指令与前三条指令相比有所不同


间接转移指令:JMP @A+DPTR


这条指令的用途也是跳转,转到什么地方去呢?这可不能由标号简单地决定了。


转移地址由A+DPTR形成,并直接送入PC。


指令对A、DPTR和标志位均无影响。本指令可代替众多的判别跳转指令,又称为散转指令,多用于多分支程序结构中。

举个例子:


MOV DPTR,#TAB ;将TAB代表的地址送入DPTR


        JMP @A+DPTR    ;跳转


TAB: AJMP ROUT0     ;跳转ROUT0开始的程序段


TAB+2: AJMP ROUT1    ;跳转ROUT1开始的程序段


TAB+4: AJMP ROUT2     ;跳转ROUT2开始的程序段


TAB+6: AJMP ROUT3     ;跳转ROUT3开始的程序段


执行该段程序后,程序将根据A中的内容转移到不同的程序段去执行散转。


A=0,转ROUT0


A=2,转ROUT1


A=4,转ROUT2


A=6,转ROUT3

2.条件转移指令

条件转移指令是指在满足一定条件时进行相对转移,否则程序继续执行本指令的下一条指令。


(1)判A内容是否为0转移指令


JZ   rel     ;如果A=0,则转移,否则顺序执行。


JNZ  rel    ;如果A≠0,就转移。


转移到相对于当前PC值的8位移量的地址去。即:新的PC值=当前PC+偏移量rel


我们在编写汇编语言源程序时,可以直接写成:


JZ   标号    ;即转移到标号处。

举个例子:


        MOV A,R0


        JZ  L1


        MOV R1,#00H


        AJMP L2


   L1:  MOV R1,#0FFH


   L2:  SJMP L2


        END


在执行上面这段程序前:


如果R0=0,结果R1=0FFH。而如果R0≠

0,则结果是R1=00H。把上面的那个例子中的JZ改成JNZ,看看程序执行的结果为:如果R0=0,结果R1=00H。如果R0≠

0,结果是R1中的值为0FFH。


(2)比较不等转移指令


CJNE A,#data,rel


CJNE A,direct,rel


CJNE Rn,#data,rel


CJNE @Ri,#data,rel


此类指令的功能是将两个操作数比较,如果两者相等,就顺序执行,如果不相等,就转移。


同样地,使用时,我们可以将rel理解成标号,即:


      CJNE A,#data,标号


      CJNE A,direct,标号


      CJNE Rn,#data,标号


      CJNE @Ri,#data,标号


利用这些指令,可以判断两数是否相等。


但有时还想得知两数比较之后哪个大,哪个小,本条指令也具有这样的功能:


如果两数不相等,则CPU还会用CY(进位位)来反映哪个数大,哪个数小。


如果前面的数大,则CY=0,否则CY=1。


因此在程序转移后再次利用CY就可判断出哪个数大,哪个数小了。


举个例子:


  MOV  A,R0


  CJNE  A,#10H,L1


  MOV  R1,#0                   ;如R0=10H,则不转移R1=00H;


        AJMP  L3


L1:JC  L2                             ;如CY=1即 R0<10H,则转移


        MOV  R1,#0AAH      ;否则CY=0即 R0>10H,则转移


        AJMP  L3


L2:MOV  R1,#0FFH


L3:SJMP  L3


因此最终结果是:本程序执行前,


如果R0=10H,则R1=00H;


如果R0>10H,则R1=0AAH;


如果R0<10H,则R1=0FFH。


(3)减1不为0转移指令


DJNZ Rn,rel


DJNZ direct,rel


DJNZ指令的执行过程是这样的:


它将第一个参数中的值减1,然后看这个值是否等于0,如果等于0,就往下执行,如果不等于0,就转移到第二个参数所指定的地方去。


例:


     DJNZ 10H,LOOP


                ...


LOOP:      ...


举个例子:


     MOV 23H,#0AH


     CLR A


LOOP: ADD A,23H


     DJNZ 23H,LOOP


     SJMP $


上述程序段的执行过程是:


将23H单元中的数连续相加,存至A中,每加一次, 23H单元中的数值减1,直至减到0,共加(23H)次。

3.子程序调用和返回

(1)调用指令


      LCALL  addr16    ;长调用指令(3字节)


      ACALL  addr11    ;绝对调用指令(2字节)


上面两条指令都是在主程序中调用子程序,两者的区别:


对短调用指令,被调用子程序入口地址必须与调用指令的下一条指令的第一字节在相同的2KB存储区之内。


使用时可以用:


      LCALL   标号    ;标号表示子程序首地址


      ACALL   标号  


来调用子程序。


指令的执行过程是:当前PC压栈,子程序首地址送 PC,实现转移。


(2)返回指令


子程序执行完后必须回到主程序,如何返回呢?只要执行一条返回指令就可以了。


RET        ;子程序返回指令


RETI       ;中断子程序返回指令


两者不能互换使用。


RET指令的执行过程是:堆栈栈顶内容(2字节,调用时保存的当前PC值)弹出给PC,实现返回。


RETI指令除了具有RET指令的功能实现程序返回外,还有对中断优先级状态触发器的清零。

4.空操作指令

NOP


空操作,就是什么事也不干,停一个周期,一般用作短时间的延时


•位操作指令

MCS-51单片机的硬件结构中,有一个位处理器(又称布尔处理器),它有一套位变量处理的指令集,包括位变量传送、逻辑运算、控制程序转移等。


在MCS-51 中,有一部分RAM和一部分SFR是具有位寻址功能的。


位操作区:内部RAM的20H-2FH这16个字节单元,即128个位单元(位地址空间位00~7FH);


可以位寻址的特殊功能寄存器:8031中有一些SFR是可以进行位寻址的,这些SFR的特点是其字节地址均可被8整除, 如A累加器,B寄存器、PSW、IP(中断优先级控制寄存器)、 IE(中断允许控制寄存器)、SCON(串行口控制寄存器)、TCON(定时器/计数器控制寄存器)、P0-P3(I/O端口锁存器)。


在进行位处理时, CY用作“位累加器” 。


位地址的表达方式:


以PSW中位4( RS1 )为例。


直接(位)地址方式:如 D4H;


点操作符号方式:如 PSW.4,D0H.4;


位名称方式:如 RS1;


用户定义名方式:如用伪指令 bit


             SUB.REG   bit  RS1


定义后,可用SUB.REG代替RS1。


1.位传送指令

MOV  C,bit       ;bit →C


MOV  bit,C       ;C →bit


这组指令的功能是实现位累加器(CY)和其它位地址之间的数据传递。


例:MOV C,P1.0       ;将P1.0的状态送给C。


      MOV P1.0,C   ;将C中的状态送到P1.0 引脚上去。


2.位清0和置位

位清0指令


 CLR C         ;使CY=0


 CLR bit       ;使指令的位地址等于0。


 例:CLR P1.0  ;即使P1.0变为0


位置1指令


 SETB C        ;使CY=1


 SETB bit      ;使指定的位地址等于1。


 例:SETB P1.0 ;使P.0变为1


 CPL    C        ;(C¯¯¯¯)

(

𝐶

¯

)


 CPL    bit        ;(bit¯¯¯¯¯¯)

(

𝑏

𝑖

𝑡

¯

)


3.位逻辑运算指令

位与指令


ANL C,bit   ;Cy与指定位的值相与,结果送Cy


ANL C,/bit  ;先将指定的位地址中的值取出后取反,再和Cy相与,结果送回Cy。但注意:指定的位地址中的值本身并不发生变化。


例:ANL C,/P1.0


位或指令


ORL C,bit


ORL C,/bit

4.位条件转移指令

(1)判Cy转移指令


JC  rel


JNC  rel


   第一条指令的功能是如果Cy=1就转移,否则就顺序执行。


   第二条指令则和第一条指令相反,即如果Cy=0就转移,否则就顺序执行。


   同样理解: JNC   标号


(2)判位直接寻址位转移指令


JB   bit,rel


JNB  bit,rel


JBC  bit,rel


第一条指令:如果指定的(bit)=1,则转移,否则顺序执行,第二条指令功能相反。


同样理解:JB bit,标号


第三条指令是如果指定的(bit)=1,则转移,并把该位清0,否则顺序执行。

举个例子:

(四)伪指令

一.起始地址伪指令


格式为: ORG   nn


定位目的程序的起始地址。


   格式:   ORG   表达式


    如:ORG 0000H


注:表达式必须为16位地址值。


二、汇编结束伪指令


格式为: END


   汇编语言程序结束伪指令。


注:一定放在程序末尾


三、数据地址赋值伪指令


格式为:       字符名   DATA     nn


四、赋值伪指令


格式为:       字符名  EQU  数值或汇编符号


例:       AA  EQU 30H


             K1   EQU 40H


             MOV A,AA         ; (30H)→A


             MOV A,K1         ;(40H)→A

五、定义字节伪指令


格式为:       [标号:] DB n1,n2,…,nn


DB(Define  Byte)


从指定单元开始定义(存储)若干个字节的数据或ASCII码字符,常用于定义数据常数表。


格式:DB  字节常数或ASCII字符


例:         ORG         1000H


             DB   34H,0DEH,'A','B'


             DB   0AH,0BH,20


六、定义字伪指令


DW(Define  Word)


从指定单元开始定义(存储)若干个字的数据或ASCII码字符。


格式为:[标号:] DW nn1,nn2,…,nnN    


例:      ORG  2000H


             DW 1234H,'B'


             DW 0AH,20


七、位地址赋值伪指令


BIT(位地址符号指令)


把位地址赋于规定的字符名称。


格式:字符名称 BIT  位地址


例:       ABC BIT  P1.1


             QQ  BIT  P3.2


八、定义存储区伪指令


用于定义在标号开始的内存单元预留一定数量的内存单元,以备源程序执行过程中使用。预留单元的数量由X决定


格式为:[标号:] DS X

总结:

7种寻址方式(立即、直接、寄存器、寄存器、间接、变址、相对、位寻址),111条指令

目录
相关文章
|
6月前
|
存储 Unix 编译器
汇编语言----X86汇编指令
汇编语言----X86汇编指令
210 2
|
27天前
|
存储 移动开发 C语言
【ARM汇编速成】零基础入门汇编语言之指令集(三)
【ARM汇编速成】零基础入门汇编语言之指令集(三)
|
27天前
|
编译器 C语言 计算机视觉
【ARM汇编速成】零基础入门汇编语言之指令集(二)
【ARM汇编速成】零基础入门汇编语言之指令集(二)
118 0
几组汇编指令的比较
几组汇编指令的比较
|
4月前
|
存储 机器学习/深度学习 芯片
8086 汇编笔记(十二):int 指令 & 端口 & 直接定址表
8086 汇编笔记(十二):int 指令 & 端口 & 直接定址表
|
4月前
|
存储 算法 安全
深入理解汇编语言:基础语法和常用指令介绍
深入理解汇编语言:基础语法和常用指令介绍
|
5月前
汇编语言(第四版) 实验一 查看CPU和内存,用机器指令和汇编指令编程
汇编语言(第四版) 实验一 查看CPU和内存,用机器指令和汇编指令编程
8086 汇编笔记(九):call 指令 和 ret 指令
8086 汇编笔记(九):call 指令 和 ret 指令
|
4月前
|
编译器
8086 汇编笔记(八):转移指令的原理
8086 汇编笔记(八):转移指令的原理
|
6月前
|
安全 编译器
8086 汇编笔记(四):[BX] 和 loop 指令
8086 汇编笔记(四):[BX] 和 loop 指令