数据传送类指令是最常用,最基本的一类指令。它们可以实现寄存器与寄存器之间、寄存器与片内RAM之间、片内RAM单元之间的数据传送等。
MOV 目的,源
指令中,源操作数是指带传送的数据源,它可以是立即数、累加器A,工作寄存器或片内RAM存储单元;目的操作数是指数据源传送到的目的地,不能是立即数。
指令执行后,源操作数不变,目的操作数被改变。
累加器A为目的的操作数的指令
MOV A,Rn;A<-Rn
MOV A,direct;A<-(direct)
MOV A,@Ri;A<-(Ri)
MOV A,#data;A<-data
工作寄存器Rn为目的的操作数的指令
MOV Rn,A;Rn<-A 传送的是A中保存的数
MOV Rn,direct;Rn<-(direct)
MOV Rn,#data;Rn<-data
;把源操作数的累加器A,片内RAM单元,SFR内容或立即数传送到R0~R7的某个寄存器中
直接地址为目的操作数的指令
MOV direct,A;(direct)<-A
MOV direct,Rn;(direct)<-Rn
MOV direct,direct;(direct)<-(direct)
MOV direct,@Ri;(direct)<-Ri
MOV direct,#data;(direct)<-data
;需要注意的是:MOV direct,direct和MOV direct,#data均为三字节指令,但汇编后,它们的指令机器代码排列顺序不同。
;操作码 源direct 目的direct(源地址在前,目的地址在后)
;操作码 direct data 目的地址在前,源操作数在后
间接地址为目的操作数的指令
MOV @Ri,A;(Ri)<-A 把A中的数传送给(Ri)地址下保存的数。比如Ri=30H,A=20H,则操作后(30H)=20H
MOV @Ri,direct;(Ri)<-(direct)
MOV @Ri,#data;(Ri)<-data
MOV DPTR,#data 16
;唯一的16位立即数传送指令
;DPTR是一个16位的地址寄存器,所以通常称16位立即数为目标地址
;这也是一个三字节的指令。汇编成机器码的时候,立即数的高位字节在前,低位字节在后
MOV DPTR,#2068H
;机器代码 90 20 68
PUSH direct ;SP<-SP+1,(SP)<-(direct)
POP direct ;(direct)<-(SP),SP<-SP-1
;SP始终指向栈顶,PUSH是入栈指令,POP是出栈指令
;eg:设SP=30H,(50H)=80H
PUSH 50H ;SP从30H变为31H,同时把(50H)->(31H)
POP 40H ;把(31H)->(40H),同时SP从31H变为30H
主要有两条
查表指令(以PC作为基址)
MOVC A,@A+PC ;PC<-PC+1,A<-(A+PC)
;通过将PC当前值与累加器A中的地址偏移量相加,将得到的地址中间的数取给A
;步骤如下:
;1.将地址偏移量(待查数据表的项数)送累加器A
;2.用加法指令(ADD A,#data)对累加器A进行修正,修正量data由PC(CURRENT)+data=数据表首地址计算出
;若data=1,则可以采用INC A指令对A进行修正
;这里主要是通过参考PC地址在PC后面进行查表。这里面数据只能存放在PC的后面,且需要与命令保持一定的间距
查表指令(以DPTR作为基址)
MOVC A,@A+DPTR ;A<-A+DPTR
;这是一条单字节指令,以DPTE为基址寄存器,存放数据表的首地址
;由于DPTR为一个十六位的寄存器,可以任意设定初值,因此数据表可以随意设置。
ORG 0200H
HEXABC: MOV DPTR,#DTAB ;置数据表首地址
MOVC A,@A+DPTR ;查表
RET
DTAB: DB 30H
;...
DB 39H
;...
DB 46H
;这里面取DTAB的值就是DTAB所在的地址
CPU访问片外数据存储器RAM时,只能通过累加器A进行,包括读取片外RAM的数据和把数据写到片外RAM存储单元中。指令如下:
MOVX A,@Ri ;A<-(Ri)
MOVX A,@DPTR ;A<-(DPTR)
MOVX @Ri,A ;(Ri)<-A
MOVX @DPTR,A ;(DPTR)<-A
例如,把片内RAM 40H单元中的内容送到片外RAM2000H单元中去:
MOV A,40H
MOV DPTR,#2000H
MOVX @DPTR,A
;访问外部只有上面的四个操作,其他操作都是违规的
交换指令
交换指令一共有五条:
字节交换指令
XCH A,Rn ;A<->Rn
XCH A,direct ;A<->direct
XCH A,@Rn ;A<->(Ri)
;XCH的功能是将累加器A中的内容与源操作数所指的数据互相交换
半字节交换指令
XCHD A,@Ri ;A.3~A.0<->(Ri.3~Ri.0)
;该指令的功能是,将累加器A中的低四位与Ri间接寻址单元内容的低四位相互交换,而各自的高四位的内容不变。
;对于十六进制位来说,就是只交换个位的数字
累加器A的高四位与低四位内容呼唤指令
SWAP A ;A.3~A.0<->A.7~A.4
;将A的高、低两半字节相互交换。本指令也可以看作4位循环移位指令
MCS-51算数运算类指令主要是对8位无符号二进制数进行加减乘除四则运算。增一,减一;实现对BCD码的压缩。一共有24条
在加法,带进位的假发和带借位的剑法的指令中,累加器A中总是存放着目的操作数,并存放操作的中间结果。这些指令都影响程序状态字寄存器PSW的进位位CY,溢出位OV,半进位位AC和奇偶标志位P。乘法和除法只影响标志位OV和P
主要有四条
ADD A,Rn ;A<-A+Rn
ADD A,direct ;A<-A+(direct)
ADD A,@Ri ;A<-A+(Ri)
ADD A,#data ;A<-A+data
ADDC A,Rn ;A<-A+Rn+CY
ADD A,direct ;A<-A+(direct)+CY
ADD A,@Ri ;A<-A+(Ri)+CY
ADD A,#data ;A<-A+data+CY
INC A
INC Rn
INC direct
INC @Ri
INC DPTR
;把操作数所指定单元的内容加一。其操作除了第一条指令影响奇偶标志位外,其余指令操作均不影响PSW。程序设计中,+1指令的使用十分频繁,通常配合寄存器间址指令使用,用于修改地址指针。
带借位的减法指令
SUBB A,Rn
SUBB A,direct
SUBB A,@Ri
SUBB A,#data
;A<-A-Rn-CY
减一指令
DEC A ;A<-A-1
DEC Rn
DEC direct
DEC @Ri
;这组指令的功能是把操作数所指定的单元内容减一,其操作除了第一条指令影响奇偶标志外,其余指令操作均不影响PSW标志
乘法指令
MUL AB
;将A,B,两个八字节位的无符号数相乘。结果为16字节数。结果的高八位保存在B中,低八位保存在A中。如果B中有数,则OV(溢出位)置为一。
除法指令
DIV AB ;A/B 商保存在A中,余数保存在B中
;如果被除数B为零,则OV置为1,否则置为零
这类指令主要用于对八字节数进行逻辑运算。包括逻辑与,或,异或,取反,以及逻辑移位指令。
逻辑“与”指令
ANL A,Rn
ANL A,direct
ANL A,@Ri
ANL A,#data
ANL direct,A
ANL direct,#data
;前四条指令的目的操作数是累加器A,源操作数可以是工作寄存器,片内RAM和立即数。指令的功能是,将A中的内容和源操作数所指定的内容按位逻辑与,结果存入目的操作数中。
;逻辑与指令常用于屏蔽某些位
逻辑“或”指令
ORL A,Rn
ORL A,direct
ORL A,@Ri
ORL A,#data
ORL direct,A
ORL direct,#dataORL
;使用逻辑和逻辑与一样。两个的缩写也可以看出,一个是AND LOGICAL 一个是OR LOGICAL
逻辑异或指令
XRL A,Rn
XRL A,direct
XRL A,@Ri
XRL A,#data
XRL direct,A
XRL direct,#dataORL
;使用逻辑与上面一样。 X OR LOGICAL
累加器A清零指令
CLR A;A<-0
累加器A取反指令
CPL A ;A<-!A
;这条指令的功能是将累加器A的内容逐位取反
累加器A循环移位指令
RL A ;(REMOVE LEFT的缩写),循环向左移动一位。比如说0000 1111B移动之后变成0001 1110B 后面的操作同理
RR A ;循环向右移动一位
RLC A ; REMOVE LEFT C 将累加器A的内容连同进位位CY向左循环移动一位(CY D0~D7)可以看成九位数的循环移位
RRC A ;带进位位的循环向右移位
控制转移类指令属于程序控制指令。其作用是改变程序执行的方向,或者调用子程序,或者从子程序返回。这些都是通过改变程序计数器PC实现的。
这类指令可以分为转移指令,调用子程序指令和返回指令。
转移类指令
转移类指令通过改变PC的内容,以改变正在执行的指令顺序,转向新的地址继续执行下去,从而实现程序的分支。根据指令转移的条件,转移指令可以分为无条件转移指令和条件转移指令。前者CPU无条件的转移到指定位置执行程序,后者只有当条件满足的时候才能实现程序的转移,否则继续执行下一条指令。
无条件转移指令
LJMP addr16 ;PC<-addr16
AJMP addr11 ;PC<-PC+2,PC.10~PC.0<-addr11
JMP @A+DPTR ;PC<-A+DPTR
SJMP rel ;PC<-PC+rel
;第一条指令(LJMP LONG J MOVE POSITION)是长转移指令。它的功能是把转移地址addr16送入程序计数器PC,CPU便会无条件转移到addr16处执行程序。由于addr16是16位二进制数,因此,程序可以转移到64KB范围内的任何地址单元去执行(2^16=64K).
;第二条指令(AJMP addr11)叫绝对转移指令,因为指令中只提供了低11位的地址。所以程序只能转移到下一条指令开始的2KB范围内执行。AJMP是二字节指令。执行过程为:先进行取指令操作,PC中的内容加一两次。PC+2,形成PC的当前地址;第二步是PC当前值的高五位地址PC.15~PC.11和指令机器码中的低11位地址一起构成16位的转移地址。(+2的步骤不能省)
;第三条指令(JMP @A+DPTR)是编制寻址转移指令,为单字节无条件转移指令。在指令执行之前,应该预先把目标地址的基本地址送入DPTR,目标转移地址对基本地址的偏移量放在累加器A中,在指令执行的时候,CPU把DPTR中的基地址和累加器A中的地址偏移量相加,形成目标转移地址送入程序计数器PC.如果结果超过64KB,那么会从最后一位转向零重新开始计数。
;第四条指令(SJMP)是短转移指令(short JMP),是无条件相对转移指令。指令的操作数是相对地址。该指令执行后,程序便转移到当前PC值与REL值之和所只是的地址单元。
MCS-51单片机的指令系统中没有停机指令,但在程序中,为了等待中断或者程序结束,需要使程序“原地踏步”,通常可以使用SJMP指令来完成,即反复让CPU执行SJMP指令,这就是动态停机。如果有中断发生,或者CPU复位,就可以脱离该状态。
SJMP $
条件转移指令
多数情况下,程序的转移是有条件的。根据给定的条件进行检测,若条件得到满足,则程序转向指定的目标地址去执行;否则,不转移,继续往下执行程序。这类条件转移指令都是相对转移指令,其转移的范围是以 转移指令的下一条指令的第一个字节地址为起始地址的-128~127个字节内。
判0转移指令
JZ rel ;(J ZERO)
JNZ rel ;(J NOT ZERO)
;上述两条指令都是对累加器A的内容进行检测,根据A中的内容是否为0来决定程序是否转移。指令执行后,A的内容不变。
判CY转移指令
JC rel ;J CY
JNC rel ;J NOT CY
;这两条指令是以PSW中的进位标志CY作为检测条件,根据CY标志的情况来决定程序是否转移。程序流程与JZ类似
比较转移指令
CJNE A,direct,rel ;COMPARE J NOT EQUATION 比较A和DIRECT是否相等判断是否转移
CJNE A,#data,rel
CJNE Rn,#data,rel
CJNE @Ri,#data,rel
;值得注意的是,CJNE是三字节指令,所以判断为不转移之后,PC<-PC+3.
;三字节的相对转移指令的偏移量计算规则如下:
;向后转移: 偏移量=目的地址-(源地址+3)
;向前转移: 偏移量=(目的地址+0100H)-(源地址+3)
循环转移指令
DJNZ Rn,rel
DJNZ direct,rel
;在程序设计时,可以设置一个计数器,计数器的值就是要重复执行的次数,每执行一次某段程序,计数器的值减一;若计数器的值不为零,则循环转移继续进行,直到计数器的值减为零为止,循环转移结束。指令执行示意图如下图
;注意,在使用DJNZ指令之前,应该将循环次数赋值给计数器,即Rn或(direct)
;EG:
CLR A
MOV 50H,#64H ;设置循环次数
L1: INC A
DJNZ 50H,L1 ;50H不为零则转L1
调用子程序以及返回指令
调用子程序指令
LCALL addr16 ;PC<-PC+3,SP<-SP+1,(SP)<-PC.7~PC.0 SP<-SP+1,(SP)<-PC.15~PC.8,PC<-addr16
ACALL addr11 ;PC<-PC+2,SP<-SP+1,(SP)<-PC.7~PC.0 SP<-SP+1,(SP)<-PC.15~PC.8,PC.10~PC.0<-addr11
;第一条指令LCALL为长调用指令,addr16是子程序入口地址。执行的时候,先将断口处分成两部分压入堆栈。子程序执行完之后,需要返回到主程序原来的断口地址处。其实也就是说,堆栈起到保存初始地址的作用。
;ACALL的执行逻辑和LCALL类似,只不过ACALL只有两个字节大小,同时转移范围只有PC的前11位。
返回指令
RET ;PC.15~PC.8<-(SP),SP<-SP-1 PC.7~PC.0<-(SP),SP<-SP-1
RETI ;PC.15~PC.8<-(SP),SP<-SP-1 PC.7~PC.0<-(SP),SP<-SP-1
;子程序返回指令,功能是将堆栈内的断口地址弹出送入PC,CPU返回到原断口地址处,继续执行原程序。
;第二条指令为中断返回指令。这条指令除了执行RET指令的功能之外,还会清除内部相应的中断状态寄存器(该寄存器由CPU相应中断时置位)的内容。所以这条指令只能用于中断服务程序,返回之后原程序不会继续向下运行。
空操作指令
NOP ;(NONE POINTER)PC<-PC+1
;单字节指令。无任何影响。这条指令通常用于产生一个机器周期的延迟或者在程序中补空,便于程序调试时指令的增删。
单片机从硬件到软件构成了完整的按位操作的不二处理器,也称为位处理器。在这里面,CPU不是以字节或者字而是以位作为处理对象进行操作的。进行位操作的时候,以进位标志CY作为位累加器,具有一套按位处理指令集,包括数据传送,位逻辑运算和位条件控制转移等指令。
MSC-51单片机内部诗句存储器中,有两部分按位寻址的存储地址空间:一部分是片内RAM的20H~2FH共16个字节单元128位,位地址为00H-7FH,各位地址相应于从20H字节单元的最低位开始,到2FH字节单元的最高位;另一部分是特殊功能寄存器区,字节地址能被8整除的专用寄存器也具有位地址,其位地址从80H-F7H.中间有极少数位没有被定义,这部分不能按位寻址。
在汇编语言中,位地址的表达方式有以下几种:
直接用位地址表示,如
D4H,2FH
用点操作符号表示。点操作符前面部分是字节地址或者是可以被位寻址的专用寄存器,后面部分的数字表示它们的位。
例如:(D0H).4,PSW.4
寄存器的位定义名称。如:RS1.0V
用户定义的位符号地址。例如:L1 BIT PSW.4,将PSW.4定义为位符号地址L1之后,允许在指令中使用L1代替PSW.4
位数据传送指令
MOV C,bit ;CY<-(bit)
MOV bit,C
;注意的是,其中的一个操作数必须是位累加器CY,另一个操作数可以是任何可以被直接寻址的位
位状态修改指令
CLR C ;清零
CLR bit
CPL C ;逻辑取反
CPL bit
SETB C ;重置位1
SETB bit
位逻辑运算指令
ANL C,bit ;C AND BIT
ANL C,/bit ;C AND !BIT
ORL C,bit
ORL C,/bit
位条件转移指令
JB bit,rel ;若(bit)=1,则PC<-PC+rel,否则,PC<-PC+3 J BIT
JNB bit,rel ;若(bit)=0,则PC<-PC+rel,否则,PC<-PC+3 J NOT BIT
JBC bit,rel ;若(bit)=1,则PC<-PC+rel,同时bit清零;否则,PC<-PC+3,bit清零 J B CLR