目录
(一)七大寻址方式
① 立即寻址:
② 寄存器寻址:
③ 直接寻址:
④ 寄存器间接寻址:
⑤ 变指寻址:
⑥ 相对寻址:
⑦ 位寻址:
(二)重要指令
(1)转移指令
(2)堆栈指令
(3)加减
(4)乘除
(5)位操作
(6)循环移位指令
(7)无条件转移指令
(8)条件转移指令
(9)调用、返回、空操作指令
(10)取反、清0指令
(11)置0/1指令
(三)常见指令集合
•数据传送类指令
1.内部数据传送指令MOV
2.外部数据传送指令MOVX
3.堆栈操作指令
4.数据交换指令
•算术运算类指令
1.加法指令
2.减法指令
3.减1指令
4.十进制调整指令
5.乘法指令
5.除法指令
•逻辑运算指令
1.逻辑与指令
2.逻辑或指令
3.逻辑异或指令
4.清0和取反指令
•循环移位指令
•控制转移类指令
1.无条件转移指令
2.条件转移指令
3.子程序调用和返回
4.空操作指令
•位操作指令
1.位传送指令
2.位清0和置位
3.位逻辑运算指令
4.位条件转移指令
(四)伪指令
(一)七大寻址方式
① 立即寻址:
以"#"开头,例如"#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 MAINORG 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 ;45H79H=41H-->A
ANL 25H,#15H ;79H15H=11H-->(25H)
ANL 25H,A ;11H41H=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 ;45H39H=70H-->A
ORL 25H,#13H ;39H13H=3BH-->(25H)
ORL 25H,A ;3BH7DH=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。而如果R00,则结果是R1=00H。把上面的那个例子中的JZ改成JNZ,看看程序执行的结果为:如果R0=0,结果R1=00H。如果R00,结果是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 ;
CPL 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条指令