您当前的位置:首页 > 自动化 > 单片机

8051的指令

发布时间:2008-12-21 17:20:10  来源:    作者:   更新20250114 070337

程序状态字组(PSW,Program Status Word)

 

CY
AC
F0
RS1
RS0
OV
-
P

PSW里存着一些反应目前CPU执行过程的状态.PSW如图所示,它是在SFR里一个位元组,它包含有进位旗号(CY) 、辅助进位旗号(AC)、(在BCD运算时使用)、两个暂存器库选择位元(RS1和RS0)、溢位旗号(0V)、同位元(P,parity)和两个由使用者定义的旗号(F0和PSW.1).

进位旗号除了作算数运算的进位位元外,也当作布林代数运算的'累加器'(Boolean Accumulator).同位元(P)的作用是反应累加器内的八个位元为"1"的个数,如果P=1,则累加器内有其数个"1",若P=0则累加器内有偶数个"1".也就是偶同位(累加器为"1"的个数+P=偶数)之义.PSW的另两个位元,CPU未使用,因此可当作一般旗号使用.

所有MCS-51族的微处理机都执行相同的指令集.MCS-51的指令集是设计给控制应用.它提供了一些快速且多种定址模式以存取内部RAM之资料,使得在这一小小的结构里更容易做位元组操作.另外指令集更支援了单一位元变数的资料型态,以帮助需要作布林代数运算的控制和逻辑系统里直接作位元运算.

定址法

       定址法就是资料所在处的表示方法,MCS-51指令集之定址法有下列六种:

       直接定址法--直接定址模式时,运算元是由一个八位元的位址所指定.其中只有内部记忆体(低128位元)和SFR才可以使用直接定址法.
间接定址法--间接定址法是指令指定一个暂存器,而此暂存器的内容即为运算元的位址.无论内部或外部的RAM都可以使用间接定址法.被选择到的暂存器库中的R0 、 R1和堆叠指标(SP)可当作此8位元位址之暂存器.16位元的位址站存器只能使用16位元的"资料指标"暂存器,DPTR.
       暂存器指令--暂存器库内的R0至R7暂存器,可以被某些指令直接定址,其定址法是由指令的运算码(OP Code)里的3个位元所指定,使用这种指定法去存取暂存器会使得指令码减少,而显得相当有效率,因为这种方法减少了一个位元组的位址位元组.当执行这种指令时,被选择到的暂存器库中的一个暂存器的资料会被存取.但四组暂存器库可以在程序执行时由PSW里的两个位元加以选择.
       暂存器指定指令--有些指令只针对所指定的暂存器运作,例如:有些指令,只操作累加器或资料指标(DPTR)等,因此就不须位址位元组去定址它,只要运算码本身就可以指到它了
       立即常数--在程序记忆体里一个常数的值可以紧跟在操作码之后,例如:将一个十进制100这个值载入累加器中,也可以使用十六进制64H.
       索引定址法--只有程序记忆体可以使用索引定址法,且只能读入.这种定址法的最主要用途是作为程序记忆体查表.此法是以16位元的基底暂存器( DPTR或程序计数器PC)指到表的基底,而累加器则指出表的进入点.也就是进入程序记忆体的表的位址是将累加器的值加上基底指标的值所组成.
另一个索引定址的型式是使用在"条件跳跃指令",在此情况下跳跃指令的目的位址是由基底指标加上累加器的值所计算出的值.

ADD A,7FH  直接寻址  7FH代表数据所在之内部RAM地址
ADD A,@R0 间接寻址   R0内所存的是数据所在之内部RAM地址,间接寻址须加"@"符号
ADD A,R7  缓存器寻址 可使用R0至R7,数据在缓存器中
ADD A,#127 立即寻址  127为要运算的数据,闲接寻址须加"#"符号
 下表是其后指令表格所使用之缩写符号
<>

缩写符号说明

缩写符号说明备注
Rn缓存器R0-R7 
direct8bit内部数据存储器,包括
1.内部数据存储器(00-7F)的地址
2.特殊功能缓存器(80-FF)的地址,如P0,PSW,TMOD..等
 
@Ri由缓存器R0或R1所寻址的内部RAM数据 
#data8bit常数 
#data 1616bit常数 
addr 1616bit的目的地址,可使跳跃指令跳跃64k 
addr 1111bit的目的地址,可使跳跃指令跳跃2k 
rel具正负号的8位地址偏移量,用于相对地址的跳跃 
bit1个bit:只所有可以位寻址的位。 
A累加器(累积器) 
C或CY进位旗号 
AC辅助进位旗号 
PC程序计数器 
P0I/O port 0 
P1I/O port 1 
P2I/O port 2 
P3I/O port 3 
PSW程序状态字组(类似于旗号缓存器) 
SP堆栈指针缓存器 
B缓存器B 
DPTR数据指针缓存器 
@间接地址符号 
$程序计数迄目前的值 
reg缓存器 
<>

算数运算指令

指令说明周期
ADD A,RnA←A+Rn12
ADD A,directA←A+direct12
ADD A,@RiA←A+Ri12
ADD A,#dataA←A+data12
ADDC A,RnA←A+Rn+C12
ADDC A,directA←A+direct+C12
ADDC A,@RiA←A+Ri+C12
ADDC A,#dataA←A+data+C12
SUBB A,RnA←A-Rn-C12
SUBB A,directA←A-direct-C12
SUBB A,@RiA←A-Ri-C12
SUBB A,#dataA←A-data-C12
INC AA←A+112
INC RnRn←Rn+112
INC directdirect←direct+112
INC @Ri@Ri←@Ri+112
INC DPTRDPTR←DPTR+112
DEC AA←A-112
DEC RnRn←Rn-112
DEC directdirect←direct-112
DEC @Ri@Ri←@Ri-112
MUL AB两个无符号的8位数据相乘,其中高阶8位放入B缓存器,低阶8位则放入累积器ACC24
DIV AB两个无符号的8位数据相除,把ACC值除以B缓存器值,商数放回ACC,余数放在B48

INC指令可以直接操作16位元的资料指标.而资料指标是用来产生16位元的外部资料记忆体位址,因此可以直接对16位元的暂存器加1是很有用的功能.

MUL AB指令是将累加器的内容乘上B暂存器的内容,且将16位元的乘积的低8位元放到A,高8位元放到B中.

DIV AB指令是将累加器的内容除以B暂存器的内容,而8位元的商放在累加器,但8位元余数则放在B暂存器.说也奇怪,DIV AB指令却很少使用在数学的"除法"程序中,而它却常使用在数字的基底(radix)转换和程序化的位移操作中.在稍后会举例如何使用DIV AB指俴作基底的转换.在位移操作里,被2n除后,会将n个位元向右移,使用DIV AB指令,作位移动作时,可在4μS的时间里将n个位元右移至B暂存器里.

DA A指令是用在BCD算术运算;在作BCD运算时,ADD和ADDC指令之后必须紧跟着DA A指令,以保证运算后的结果也是BCD,请特别注意DA A指令并不能直将一个二进制数字转换成BCD码.DA A指令只有在执行两个BCD码的加算后再执行才有意义.

<><>

逻辑运算指令

指令说明周期
ANL A,RnA←A and Rn12
ANL A,directA←A and direct12
ANL A,@RiA←A and Ri12
ANL A,#dataA←A and data12
ANL direct,Adirect←direct and A12
ANL direct,#datadirect←direct and data24
ORL A,RnA←A or Rn12
ORL A,directA←A or direct12
ORL A,RnA←A or Rn12
ORL A,@RiA←A or Ri12
ORL A,#dataA←A or data12
ORL direct,Adirect←direct or A12
ORL direct,#datadirect←direct or data24
XRL A,RnA←A xor Rn12
XRL A,directA←A xor direct12
XRL A,@RiA←A xor Ri12
XRL A,#dataA←A xor data12
XRL direct,Adirect←direct xor A12
XRL direct,#datadirect←direct xor data12
CLR A清除累加器12
CPL A累加器反相12
RL A累加器向左旋转12
RLC A累加器和C左旋12
RR A累加器向右旋转12
RRC A累加器和C右旋12

这些指令是以位元组里的位元对位元执行逻辑运算,例如:累加器的内容为01010101B而<byte>的内容为10101010B,则ANL A,<byte>会使得累加器的内容变成00000000B 。

请注意:在内部资料记忆空间里的任一位元组都可直接执行逻辑运算,而不需透过累加器。如XRL <byte>,#data这个指令可以提供很快速得将P1上的位元资料做转换,例如: XRL P1,#0FFH

旋转指令( RL A、RLC A等)将累加器位移1位元至左边或右边,对一个左旋转指令是将MSB转至LSB之位置,而右旋转指令将LSB转至MSB位置。

SWAP A指令是将累加器的高4位元和低4位元的资料交换,这对于BCD的操作相当有用.

若累加器的内容为一个二进制数字,且已知其值小于十进制之100,则它可以很快地用如下列程序转换成BCD码:
        MOV B,#10
        DIV A,B
        SWAP A
        ADD A,B
将其除已10,会使得10位数落在累加器的低4位里,其各位数则在B缓存器里,而SWAP和ADD指令则十位数移到高4位而个位数则移至4位。

<><>

数据转移指令

指令说明周期
MOV A,RnA←Rn12
MOV A,directA←direct12
MOV A,@RiA←Ri12
MOV A,#dataA←data12
MOV Rn,ARn←A12
MOV Rn,directRn←direct24
MOV Rn,#dataRn←data12
MOV direct,Adirect←A12
MOV direct,Rndirect←Rn24
MOV direct,directdirect←direct24
MOV direct,@Ridirect←Ri24
MOV direct,#datadirect←data24
MOV @Ri,ARi←A12
MOV @Ri,directRi←direct24
MOV @Ri,#dataRi←data12
MOV DPTR,#data 16Ri←16bit data24
MOVC A,@A+DPTRA←程序内存的数据24
MOVC A,@A+PCA←程序内存的数据24
MOVX A,@RiA←外部RAM的数据(8bit地址)24
MOVX A,@DPTRA←外部RAM的数据(16bit地址)24
MOVX @Ri,A外部的RAM(8bit)←A24
MOVX @DPTR,A外部的RAM(16bit)←A24
PUSH direc推迭区←direct24
POP direcdirect←堆栈区24
XCH A,RnA和Rn互换12
XCH A,directA和direct互换12

资料转移

SFR内的暂存器则只能使用直接定址法。注意到所有MCS-51的堆叠区都是芯片内部的RAM里,PUSH指令首先将堆叠指标(SP)加1,然后将一个位元组拷贝进去堆叠区。 PUSH和POP都只能使用直接定址法来指出被存入或取出的位元组,但是堆叠本身只能使用SP暂存器的间接定址法加以存取。这意思是说,堆叠区可以使用较高的128位元组,如果他们有的话,但却不是在SFR空间里。在8051、80C51BH;或内部没有ROM的8031或EPROM版本的8751都没有较高的128位元组的RAM,使用这些版本时,如果SP指向较高128位元组时,若PUSH一个位元组,此资料将遗失,而POP一个位元组时将会得到一个不确定的资料。

资料转移指令里包含了一个16位元的MOV,它可以用来设定资料指标(DPTR)的初值,以当作在程序记忆体查表支用,或作为16位元的外部资料记忆存取。

XCH A,<byte>指令可以将累加器的内容与被定址到位元组的内容互换。 XCHD A,@Ri指令也类似,只不过是交换其中的低4位元(Low Nibble)。


外部RAM

外部资料记忆体资料转移指令,只能使用间接定址法。但有两种方式可供选择,那就是使用单位元组定址或是两位元组定址,单位元组位址的产生是使用暂存器库中的R0或R1。双位元组位址则由DPTR所产生。使用16位元位址较不方便的地方是,假如只有几K位元组的外部RAM时,16位元不只是使用了接口2里的所有八位元当作位址汇流排。然而,使用八位元的位址也可以定址到几K位元组的外部RAM,而不须使用接口2的所有位元。请注意:所有的外部资料存取时,累加器都是当作指令资料的目的地(destination)或来源地(source)。对外部RAM的读(RD)和写(WR)的激发信号只有在执行MOVX指令时会动作,在一般情形下这些信号不会动作。事实上如果RD和WR不再使用时,这些脚还可以当作额外的I/O现使用。

读取在程序记忆体的查表指令

这些指令只读取程序记忆体的资料,因此表中的资料只能被读而不能更改。其中MOVC是"MOVE constant"的意思。如果要读的表是再外部的程序记忆体时,则读取的激发信号是PSEN。第一个MOVC指令中容纳256位元的表,即OOH至FFH。首先将想要进入的位址在载入累加器中,再将资料指标设定指到表的开始点,然后执行:
MOVC A,@A+DPTR就会将想要的值载入累加器。

另一个MOVC指令的动作情形也相同,只不过是使用程序计数器(PC)当作表的基底,因此这个表就要透过副程序加以读取。首先将想要进入的位址载入累加器,然后作一个副程序呼叫。
MOV A,ETRY_NUMBER
CALL TABLE
而副程序"TABLE"的写法就像这样:
TABLE:MOVC A,@A+PC
RET
DB 23H
   DB 45H
这个表本身紧跟着一个RET指令,因此这种型式的表只能有255位元组,即从1到255,其中0不可以使用,因为执行MOVC指令时,PC的内容是RET这个指令的位址,所以读到的值会是RET的机械码。

< />

布尔运算指令

指令说明周期
CLR C清除进位旗标12
CLR bit清除直接位12
SETB C设定进位旗标12
SETB bit设定直接位12
CPL C进位旗标反相12
CPL bit直接位反相12
ANL C,bitC←C and bit24
ANL C,/bitC←C and bit(反相)24
ORL C,bitC←C or bit24
ORL C,/bitC←C or bit(反相)24
MOV C,bitC←bit12
MOV bit,Cbit←C24
JC rel若C=1跳至rel24
JNC rel若C=0跳至rel24
JB bit,rel若bit=1跳至rel24
JNB bit,rel若bit=0跳至rel24
JBC bit,rel若bit=1跳至rel,且清除此位24

布林指令

MCS-51内部包含有一完整的布林(单一位元)指令。在内部RAM有128个可定址位元,而SFR也提供了另128个可定址位元。因此所有I/O接口的位元都是可定址位元,且都可被当成分开的单位元接口。这些指令存取这些位元不仅只条件式跳跃指令,还有完整的转移(move)、设定(set)、清除(clear)、取补数(complement)、OR和AND指令。所以这些指令在八位元的微处理器里是很难能可贵的布林处理器的指令集如表所示。表中所有位元资料的存取都是使用直接定址法。位元位址00H至7FH是在内部RAM的较低128位元里,而位元位址80H至FFH是在SFR里。

请看:将一个内部的旗号转移至I/O接口的接脚上是多容易:
MOV C,FLAG
MOV P1.0,C
在这个例子里,FLAG是在较低128位元或SFR里的可定址位元,而I/O线上的信好是设定或清除就决定旗号位元"1"或"0"。在PSW里的进位旗号(C)位元就当作布林处理器的单位元累加器。而进位位元是个直接位址,因为它是在PSW里面的一个位元,且是个可定址位元。


 1/2    1 

程序跳跃指令

指令说明周期ACALL addr11绝对式子程序呼叫24LCALL addr16远程子程序呼叫24RET从子程序返回24RETI从中断子程序返回24AJMP addr11绝对式跳跃24LJMP addr16远程跳跃24SJMP rel短程跳跃24JMP @A+DPTR间接跳跃24JZ rel若A=0跳至rel24JNZ rel若A不等于0跳至rel24CJNE A,direct,rel若A不等于direct跳至rel24CJNE A,#data,rel若A不等于data跳至rel24CJNE Rn,#data,rel<>若Rn不等于data跳至rel24CJNE @Ri,#data,rel若Ri不等于data跳至rel24DJNZ Rn,relRn减1不等于0跳至rel24DJNZ direct,reldirect减1不等于0跳至rel24NOP没动作12
相对偏移值(Relative offset)

对于以上的条条件式跳跃指令的目的位址,可以使用标记(label)或用程序记忆体的实际位址以指定给组译器使用。然而组译出来的目的位址是一个相对偏移值的位元组,且是一个带符号(2补数)的偏移值,如果跳跃被执行的话,则这个位元组的值会以2补数的加法加入PC里。因此条件式跳跃的范围就从跳跃指令的下一个位址算起在- 128至+ 127之间。

跳跃指令:

在表中的" JMP addr"指令,实际上总共有三种------既SJMP、LJMP和AJMP------它们在目的位址的格式上有所不同,如果程序不管跳跃指令的解码方式的话,JMP这个指令可作一般指令使用。

SJMP这个指令将目的的位址编码成如上面所讨论的相对偏移位址,这个指令要使用2位元组长,既包括有操码(opcode)和偏移值(offset),此时跳跃的距离就限制在SJMP指令下一个指令位址的-128至+127之间。

LJMP指令是将目的的位址编码成16位元的常数。这个指令共占了3位元组,包括操作和两位元组的位址。如此LJMP就可跳至64K程序记忆体的任何一个位址。

AJMP指令将目的的位址编码成11位元的常数,这个指令共占2位元组,包括一个操作码,此操作码中的3个位元是11位址位元中的一部分,接下去的一个位元组就是位址的低阶八位元。当执行这个指令时,这11位元就取代了PC的低阶11位元,而PC的高阶5位元不变,因此目的位址必须在AJMP指令的下一个指令位址算起的2K区域内。

在任何情况下,写程序的人都是以标记(Label)或16位元常数去指定目的位址,组译器(Assembler)会转成正确的值给指令。如果跳跃的距离超过了指令所能达到的范围时,组译器会输出"Destinationout of rang"的讯息。

JMP @A+DPTR指令是一个间接跳跃指令。其跳跃的目的位址会在程序执行中计算16位元的DPTR和累加器的和,通常DPTR是指到一个跳跃表的位址,而累加器是表里的索引,例如:要作5条通路的跳跃时,可将整数0至4载入累加器,其程序如下面所列:

MOV  DPTR,#JUMP_TABLE
    MOV  A,INDEX_NUMBER
    RL   A
    JMP  @A+DPTR
       :
       :
       :
JUMP_TABLE:
    AJMP  CASE_0
    AJMP  CASE_1
    AJMP  CASE_2
    AJMP  CASE_3
    AJMP  CASE_4

上面程序的RL A指令是将索引值(0~4)转换成0至8的偶数值范围,因为在跳跃表里的每个进入点是2位元长.

表里所列的"CALL addr"指令也包括有两种指令----LCALL和ACALL,它们只是位址格式不同。 CALL是使用在不在乎什么位址编码方式时。 LCALL指令使用16位址格式,此时副程序可以在64K程序记忆体李的任一位址。而ACALL指令是使用11位元的格式,因此副程序必须在ACALL的下一位址算起的2K区域范围。在任何一种情况下,写程序的人可以以相同的方法指定副程序的位址给组译器:既使用标记或16位元的常数。组译器会放入正确的格式给组译令。

副程序必须以RET指令作结束,它会反回CALL的下一个指令去执行。 RETI是在中断服务程序反回使用,RET和RETI之间仅有的不同点是RETI会告诉中断控制系统,中断事件以作完,如果在没中断的情况下执行了RETI指令时,则RETI与RET在功能上是相同的。

MCS-51的条件跳跃指令所有跳跃指令所跳到的目的位址都是以相对偏移的方法指定,因此跳跃的距离是从这个指令的下一位址算起的-128至+127之间。重要一点是,写程序时只要告诉组译器直接位址或标记(label)就可以了,与其他的跳跃指令一样,组译器会算出正确的偏移值。

在PSW里并没有零旗号位址,因此MCS-51使用JZ和JNZ指令去测试累加器的内容是否为零。

DJNZ指令(递减且不为零时跳跃)是用来作回路控制用,要执行N次的回圈时,可将N载入计数器,然后用DJNZ结束这个回圈,如下所示,若N =10:

<>
MOV  COUNTER,10
LOOP:(循环开始)
       :
       :
       :
    DJNZ COUNTER,LOOP

CJNE指令(比较且不相等时跳跃)也可以使用在回圈控制上,在指令的运算元(operand)栏里共指定了两的位元组,只有在这两个位元组不相等时会产生跳跃。这个指令的另一功能是"大于、小于"的比较,在运算元里的两个位元组被看成无号数(Unsign)的整数,如果第一个位元组小于第二个,则进位旗号C=1,而如果第一个大于或等于第二个位元组则C=0。

" href="/IC/IC/2008-12-21/122_2.html">2
 

程序跳跃指令

指令说明周期ACALL addr11绝对式子程序呼叫24LCALL addr16远程子程序呼叫24RET从子程序返回24RETI从中断子程序返回24AJMP addr11绝对式跳跃24LJMP addr16远程跳跃24SJMP rel短程跳跃24JMP @A+DPTR间接跳跃24JZ rel若A=0跳至rel24JNZ rel若A不等于0跳至rel24CJNE A,direct,rel若A不等于direct跳至rel24CJNE A,#data,rel若A不等于data跳至rel24CJNE Rn,#data,rel<>若Rn不等于data跳至rel24CJNE @Ri,#data,rel若Ri不等于data跳至rel24DJNZ Rn,relRn减1不等于0跳至rel24DJNZ direct,reldirect减1不等于0跳至rel24NOP没动作12
相对偏移值(Relative offset)

对于以上的条条件式跳跃指令的目的位址,可以使用标记(label)或用程序记忆体的实际位址以指定给组译器使用。然而组译出来的目的位址是一个相对偏移值的位元组,且是一个带符号(2补数)的偏移值,如果跳跃被执行的话,则这个位元组的值会以2补数的加法加入PC里。因此条件式跳跃的范围就从跳跃指令的下一个位址算起在- 128至+ 127之间。

跳跃指令:

在表中的" JMP addr"指令,实际上总共有三种------既SJMP、LJMP和AJMP------它们在目的位址的格式上有所不同,如果程序不管跳跃指令的解码方式的话,JMP这个指令可作一般指令使用。

SJMP这个指令将目的的位址编码成如上面所讨论的相对偏移位址,这个指令要使用2位元组长,既包括有操码(opcode)和偏移值(offset),此时跳跃的距离就限制在SJMP指令下一个指令位址的-128至+127之间。

LJMP指令是将目的的位址编码成16位元的常数。这个指令共占了3位元组,包括操作和两位元组的位址。如此LJMP就可跳至64K程序记忆体的任何一个位址。

AJMP指令将目的的位址编码成11位元的常数,这个指令共占2位元组,包括一个操作码,此操作码中的3个位元是11位址位元中的一部分,接下去的一个位元组就是位址的低阶八位元。当执行这个指令时,这11位元就取代了PC的低阶11位元,而PC的高阶5位元不变,因此目的位址必须在AJMP指令的下一个指令位址算起的2K区域内。

在任何情况下,写程序的人都是以标记(Label)或16位元常数去指定目的位址,组译器(Assembler)会转成正确的值给指令。如果跳跃的距离超过了指令所能达到的范围时,组译器会输出"Destinationout of rang"的讯息。

JMP @A+DPTR指令是一个间接跳跃指令。其跳跃的目的位址会在程序执行中计算16位元的DPTR和累加器的和,通常DPTR是指到一个跳跃表的位址,而累加器是表里的索引,例如:要作5条通路的跳跃时,可将整数0至4载入累加器,其程序如下面所列:

MOV  DPTR,#JUMP_TABLE
    MOV  A,INDEX_NUMBER
    RL   A
    JMP  @A+DPTR
       :
       :
       :
JUMP_TABLE:
    AJMP  CASE_0
    AJMP  CASE_1
    AJMP  CASE_2
    AJMP  CASE_3
    AJMP  CASE_4

上面程序的RL A指令是将索引值(0~4)转换成0至8的偶数值范围,因为在跳跃表里的每个进入点是2位元长.

表里所列的"CALL addr"指令也包括有两种指令----LCALL和ACALL,它们只是位址格式不同。 CALL是使用在不在乎什么位址编码方式时。 LCALL指令使用16位址格式,此时副程序可以在64K程序记忆体李的任一位址。而ACALL指令是使用11位元的格式,因此副程序必须在ACALL的下一位址算起的2K区域范围。在任何一种情况下,写程序的人可以以相同的方法指定副程序的位址给组译器:既使用标记或16位元的常数。组译器会放入正确的格式给组译令。

副程序必须以RET指令作结束,它会反回CALL的下一个指令去执行。 RETI是在中断服务程序反回使用,RET和RETI之间仅有的不同点是RETI会告诉中断控制系统,中断事件以作完,如果在没中断的情况下执行了RETI指令时,则RETI与RET在功能上是相同的。

MCS-51的条件跳跃指令所有跳跃指令所跳到的目的位址都是以相对偏移的方法指定,因此跳跃的距离是从这个指令的下一位址算起的-128至+127之间。重要一点是,写程序时只要告诉组译器直接位址或标记(label)就可以了,与其他的跳跃指令一样,组译器会算出正确的偏移值。

在PSW里并没有零旗号位址,因此MCS-51使用JZ和JNZ指令去测试累加器的内容是否为零。

DJNZ指令(递减且不为零时跳跃)是用来作回路控制用,要执行N次的回圈时,可将N载入计数器,然后用DJNZ结束这个回圈,如下所示,若N =10:

<>
MOV  COUNTER,10
LOOP:(循环开始)
       :
       :
       :
    DJNZ COUNTER,LOOP

CJNE指令(比较且不相等时跳跃)也可以使用在回圈控制上,在指令的运算元(operand)栏里共指定了两的位元组,只有在这两个位元组不相等时会产生跳跃。这个指令的另一功能是"大于、小于"的比较,在运算元里的两个位元组被看成无号数(Unsign)的整数,如果第一个位元组小于第二个,则进位旗号C=1,而如果第一个大于或等于第二个位元组则C=0。

" href="/IC/IC/2008-12-21/122_2.html">下一页
 

程序跳跃指令

指令说明周期ACALL addr11绝对式子程序呼叫24LCALL addr16远程子程序呼叫24RET从子程序返回24RETI从中断子程序返回24AJMP addr11绝对式跳跃24LJMP addr16远程跳跃24SJMP rel短程跳跃24JMP @A+DPTR间接跳跃24JZ rel若A=0跳至rel24JNZ rel若A不等于0跳至rel24CJNE A,direct,rel若A不等于direct跳至rel24CJNE A,#data,rel若A不等于data跳至rel24CJNE Rn,#data,rel<>若Rn不等于data跳至rel24CJNE @Ri,#data,rel若Ri不等于data跳至rel24DJNZ Rn,relRn减1不等于0跳至rel24DJNZ direct,reldirect减1不等于0跳至rel24NOP没动作12
相对偏移值(Relative offset)

对于以上的条条件式跳跃指令的目的位址,可以使用标记(label)或用程序记忆体的实际位址以指定给组译器使用。然而组译出来的目的位址是一个相对偏移值的位元组,且是一个带符号(2补数)的偏移值,如果跳跃被执行的话,则这个位元组的值会以2补数的加法加入PC里。因此条件式跳跃的范围就从跳跃指令的下一个位址算起在- 128至+ 127之间。

跳跃指令:

在表中的" JMP addr"指令,实际上总共有三种------既SJMP、LJMP和AJMP------它们在目的位址的格式上有所不同,如果程序不管跳跃指令的解码方式的话,JMP这个指令可作一般指令使用。

SJMP这个指令将目的的位址编码成如上面所讨论的相对偏移位址,这个指令要使用2位元组长,既包括有操码(opcode)和偏移值(offset),此时跳跃的距离就限制在SJMP指令下一个指令位址的-128至+127之间。

LJMP指令是将目的的位址编码成16位元的常数。这个指令共占了3位元组,包括操作和两位元组的位址。如此LJMP就可跳至64K程序记忆体的任何一个位址。

AJMP指令将目的的位址编码成11位元的常数,这个指令共占2位元组,包括一个操作码,此操作码中的3个位元是11位址位元中的一部分,接下去的一个位元组就是位址的低阶八位元。当执行这个指令时,这11位元就取代了PC的低阶11位元,而PC的高阶5位元不变,因此目的位址必须在AJMP指令的下一个指令位址算起的2K区域内。

在任何情况下,写程序的人都是以标记(Label)或16位元常数去指定目的位址,组译器(Assembler)会转成正确的值给指令。如果跳跃的距离超过了指令所能达到的范围时,组译器会输出"Destinationout of rang"的讯息。

JMP @A+DPTR指令是一个间接跳跃指令。其跳跃的目的位址会在程序执行中计算16位元的DPTR和累加器的和,通常DPTR是指到一个跳跃表的位址,而累加器是表里的索引,例如:要作5条通路的跳跃时,可将整数0至4载入累加器,其程序如下面所列:

MOV  DPTR,#JUMP_TABLE
    MOV  A,INDEX_NUMBER
    RL   A
    JMP  @A+DPTR
       :
       :
       :
JUMP_TABLE:
    AJMP  CASE_0
    AJMP  CASE_1
    AJMP  CASE_2
    AJMP  CASE_3
    AJMP  CASE_4

上面程序的RL A指令是将索引值(0~4)转换成0至8的偶数值范围,因为在跳跃表里的每个进入点是2位元长.

表里所列的"CALL addr"指令也包括有两种指令----LCALL和ACALL,它们只是位址格式不同。 CALL是使用在不在乎什么位址编码方式时。 LCALL指令使用16位址格式,此时副程序可以在64K程序记忆体李的任一位址。而ACALL指令是使用11位元的格式,因此副程序必须在ACALL的下一位址算起的2K区域范围。在任何一种情况下,写程序的人可以以相同的方法指定副程序的位址给组译器:既使用标记或16位元的常数。组译器会放入正确的格式给组译令。

副程序必须以RET指令作结束,它会反回CALL的下一个指令去执行。 RETI是在中断服务程序反回使用,RET和RETI之间仅有的不同点是RETI会告诉中断控制系统,中断事件以作完,如果在没中断的情况下执行了RETI指令时,则RETI与RET在功能上是相同的。

MCS-51的条件跳跃指令所有跳跃指令所跳到的目的位址都是以相对偏移的方法指定,因此跳跃的距离是从这个指令的下一位址算起的-128至+127之间。重要一点是,写程序时只要告诉组译器直接位址或标记(label)就可以了,与其他的跳跃指令一样,组译器会算出正确的偏移值。

在PSW里并没有零旗号位址,因此MCS-51使用JZ和JNZ指令去测试累加器的内容是否为零。

DJNZ指令(递减且不为零时跳跃)是用来作回路控制用,要执行N次的回圈时,可将N载入计数器,然后用DJNZ结束这个回圈,如下所示,若N =10:

<>
MOV  COUNTER,10
LOOP:(循环开始)
       :
       :
       :
    DJNZ COUNTER,LOOP

CJNE指令(比较且不相等时跳跃)也可以使用在回圈控制上,在指令的运算元(operand)栏里共指定了两的位元组,只有在这两个位元组不相等时会产生跳跃。这个指令的另一功能是"大于、小于"的比较,在运算元里的两个位元组被看成无号数(Unsign)的整数,如果第一个位元组小于第二个,则进位旗号C=1,而如果第一个大于或等于第二个位元组则C=0。

" href="/IC/IC/2008-12-21/122_2.html">尾页
来顶一下
近回首页
返回首页

上一篇:8051的记忆体

下一篇:8051的引脚说明

分享到:
发表评论

 共有人参与,请您也说几句看法

 
   验证码: 看不清楚,点击刷新 看不清楚,点击刷新