单片机汇编jnc_单片机jnc指令 - CSDN
  •  数据传递类指令  以累加器为目的操作数的指令  MOV A,Rn  MOV A,direct  MOV A,@Ri ...第二条指令中,direct就是指的直接地址,而第三条指令中,就是我们刚才讲过的。... 下面我们通过一些
    

    数据传递类指令

        以累加器为目的操作数的指令

           MOV A,Rn

           MOV A,direct

           MOV A,@Ri

           MOV A,#data

       第一条指令中,Rn代表的是R0-R7。第二条指令中,direct就是指的直接地址,而第三条指令中,就是我们刚才讲过的。第四条指令是将立即数data送到A中。

     下面我们通过一些例子加以说明:

           MOV A,R1 ;将工作寄存器R1中的值送入A,R1中的值保持不变。

           MOV A,30H ;将内存30H单元中的值送入A,30H单元中的值保持不变。

           MOV A,@R1 ;先看R1中是什么值,把这个值作为地址,并将这个地址单元中的值送入A中。如执行命令前R1中的值为20H,则是将20H单元中的值送                          入A中。

            MOV A,#34H ;将立即数34H送入A中,执行完本条指令后,A中的值是34H。

     

        以寄存器Rn为目的操作的指令

           MOV Rn,A

           MOV Rn,direct

           MOV Rn,#data

           这组指令功能是把源地址单元中的内容送入工作寄存器,源操作数不变。

     

        以直接地址为目的操作数的指令

           MOV direct,A 例: MOV 20H,A

           MOV direct,Rn MOV 20H,R1

           MOV direct1,direct2 MOV 20H,30H

           MOV direct,@Ri MOV 20H,@R1

           MOV direct,#data MOV 20H,#34H

     

        以间接地址为目的操作数的指令

           MOV @Ri,A 例:MOV @R0,A

           MOV @Ri,direct MOV @R1,20H

           MOV @Ri,#data MOV @R0,#34H

     

        十六位数的传递指令

           MOV DPTR,#data16

           8051是一种8位机,这是唯一的一条16位立即数传递指令,其功能是将一个16位的立即数送入DPTR中去。其中高8位送入DPH(083H),低8位送入DPL(082H)。例:MOV DPTR,#1234H,则执行完了之后DPH中的值为12H,DPL中的值为34H。反之,如果我们分别向DPH,DPL送数,则结果也一样。如有下面两条指令:MOV DPH,#35H,MOV DPL,#12H。则就相当于执行了MOV DPTR,#3512H。

     

        累加器A与片外RAM之间的数据传递类指令

           MOVX A,@Ri

           MOVX @Ri,A

           MOVX #9; 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位地址。因为有时扩展的外部RAM的数量比较少,少于或等于256个,就只需要提供8位地址就够了。

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

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

             MOV DPTR,#0100H

             MOVX A,@DPTR

             MOV DPTR,#0200H

             MOVX @DPTR,A

     

        程序存储器向累加器A传送指令

              MOVC A,@A+DPTR

              本指令是将ROM中的数送入A中。本指令也被称为查表指令,常用此指令来查一个已做好在ROM中的表格(类似C语言中的指针)

         说明:

             此条指令引出一个新的寻址方法:变址寻址。本指令是要在ROM的一个地址单元中找出数据,显然必须知道这个单元的地址,这个单元的地址是这样确定的:在执行本指令立脚点DPTR中有一个数,A中有一个数,执行指令时,将A和DPTR中的数加起为,就成为要查找的单元的地址。

             1)查找到的结果被放在A中,因此,本条指令执行前后,A中的值不一定相同。

                 例:有一个数在R0中,要求用查表的方法确定它的平方值(此数的取值范围是0-5)

                 MOV DPTR,#TABLE

                 MOV A,R0

                 MOVC A,@A+DPTR

                 TABLE: DB 0,1,4,9,16,25

     

            设R0中的值为2,送入A中,而DPTR中的值则为TABLE,则最终确定的ROM单元的地址就是TABLE+2,也就是到这个单元中去取数,取到的是4,显然它正是2的平方。其它数据也可以类推。

             标号的真实含义:从这个地方也可以看到另一个问题,我们使用了标号来替代具体的单元地址。事实上,标号的真实含义就是地址数值。在这里它代表了,0,1,4,9,16,25这几个数据在ROM中存放的起点位置。而在以前我们学过的如LCALL DELAY指令中,DELAY 则代表了以DELAY为标号的那段程序在ROM中存放的起始地址。事实上,CPU正是通过这个地址才找到这段程序的。

               可以通过以下的例子再来看一看标号的含义:

                 MOV DPTR,#100H

                 MOV A,R0

                 MOVC A,@A+DPTR 

                 ORG 0100H.

                 DB 0,1,4,9,16,25

                 如果R0中的值为2,则最终地址为100H+2为102H,到102H单元中找到的是4。这个可以看懂了吧?

                 那为什么不这样写程序,要用标号呢?不是增加疑惑吗?

                 答:如果这样写程序的话,在写程序时,我们就必须确定这张表格在ROM中的具体的位置,如果写完程序后,又想在这段程序前插入一段程序,那么这张表格的位置就又要变了,要改ORG 100H这句话了,我们是经常需要修改程序的,那多麻烦,所以就用标号来替代,只要一编译程序,位置就自动发生变化,我们把这个麻烦事交给计算机��指PC机去做了。

     

        堆栈操作

           PUSH direct

           POP #9; direct

           第一条指令称之为推入,就是将direct中的内容送入堆栈中,第二条指令称之为弹出,就是将堆栈中的内容送回到direct中。推入指令的执行过程是,首先将SP中的值加1,然后把SP中的值当作地址,将direct中的值送进以SP中的值为地址的RAM单元中。例:

             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。

             POP指令的执行是这样的,首先将SP中的值作为地址,并将此地址中的数送到POP指令后面的那个direct中,然后SP减1。

            接上例:

             POP B

             POP ACC

             则执行过程是:将SP中的值(现在是61H)作为地址,取61H单元中的数值(现在是20),送到B中,所以执行完本条指令后B中的值是20,然后将SP减1,因此本条指令执行完后,SP的值变为60H,然后执行POP ACC,将SP中的值(60H)作为地址,从该地址中取数(现在是100),并送到ACC中,所以执行完本条指令后,ACC中的值是100。

           这有什么意义呢?ACC中的值本来就是100,B中的值本来就是20,是的,在本例中,的确没有意义,但在实际工作中,则在PUSH B后往往要执行其他指令,而且这些指令会把A中的值,B中的值改掉,所以在程序的结束,如果我们要把A和B中的值恢复原值,那么这些指令就有意义了。

           还有一个问题,如果我不用堆栈,比如说在PUSH ACC指令处用MOV 60H,A,在PUSH B处用指令MOV 61H,B,然后用MOV A,60H,MOV B,61H来替代两条POP指令,不是也一样吗?是的,从结果上看是一样的,但是从过程看是不一样的,PUSH和POP指令都是单字节,单周期指令,而MOV指令则是双字节,双周期指令。更何况,堆栈的作用不止于此,所以一般的计算机上都设有堆栈,而我们在编写子程序,需要保存数据时,通常也不采用后面的方法,而是用堆栈的方法来实现。

             例:写出以下程序的运行结果

               MOV 30H,#12

               MOV 31H,#23

               PUSH 30H

               PUSH 31H

               POP 30H

               POP 31H

               结果是30H中的值变为23,而31H中的值则变为12。也就两者进行了数据交换。从这个例子可以看出:使用堆栈时,入栈的书写顺序和出栈的书写顺序必须相反,才能保证数据被送回原位,否则就要出错了。

     

        算术运算类指令

         1.不带进位位的加法指令

           ADD A,#DATA ;例:ADD A,#10H

           ADD A,direct ;例:ADD A,10H

           ADD A,Rn ;例:ADD A,R7

           ADD A,@Ri ;例:ADD A,@R0

           用途:将A中的值与其后面的值相加,最终结果否是回到A中。

          例:

           MOV A,#30H

           ADD A,#10H

           则执行完本条指令后,A中的值为40H。

     

        2.带进位位的加法指令

           ADDC A,Rn

           ADDC A,direct

           ADDC A,@Ri

           ADDC A,#data

           用途:将A中的值和其后面的值相加,并且加上进位位C中的值。

           说明:由于51单片机是一种8位机,所以只能做8位的数学运算,但8位运算的范围只有0-255,这在实际工作中是不够的,因此就要进行扩展,一般是将2个8位的数学运算合起来,成为一个16位的运算,这样,可以表达的数的范围就可以达到0-65535。如何合并呢?其实很简单,让我们看一个10进制数的例子:

             66+78。

           这两个数相加,我们根本不在意这的过程,但事实上我们是这样做的:先做6+8(低位),然后再做6+7,这是高位。做了两次加法,只是我们做的时候并没有刻意分成两次加法来做罢了,或者说我们并没有意识到我们做了两次加法。之所以要分成两次来做,是因为这两个数超过了一位数所能表达的范置(0-9)。

           在做低位时产生了进位,我们做的时候是在适当的位置点一下,然后在做高位加法是将这一点加进去。那么计算机中做16位加法时同样如此,先做低8位的,如果两数相加产生了进位,也要“点一下”做个标记,这个标记就是进位位C,在PSW中。在进行高位加法是将这个C加进去。例:1067H+10A0H,先做67H+A0H=107H,而107H显然超过了0FFH,因此最终保存在A中的是7,而1则到了PSW中的CY位了,换言之,CY就相当于是100H。然后再做10H+10H+CY,结果是21H,所以最终的结果是2107H。

     

     

        3.带借位的减法指令

          SUBB A,Rn

           SUBB A,direct

           SUBB A,@Ri

           SUBB A,#data

           设(每个H,(R2)=55H,CY=1,执行指令SUBB A,R2之后,A中的值为73H。

           说明:没有不带借位的减法指令,如果需要做不带位的减法指令(在做第一次相减时),只要将CY清零即可。

     

        4.乘法指令

           MUL AB

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

           例:(A)=4EH,(B)=5DH,执行指令

           MUL AB后,乘积是1C56H,所以在B中放的是1CH,而A中放的则是56H。

     

        5.除法指令

           DIV AB

           此指令的功能是将A中的8位无符号数除以B中的8位无符号数(A/B)。除法一般会出现小数,但计算机中可没法直接表达小数,它用的是我们小学生还没接触到小数时用的商和余数的概念,如13/5,其商是2,余数是3。除了以后,商放在A中,余数放在B中。CY和OV都是0。如果在做除法前B中的值是00H,也就是除数为0,那么0V=1。

     

        6.加1指令

           INC A

           INC Rn

           INC direct

           INC @Ri

           INC DPTR

           用途很简单,就是将后面目标中的值加1。例:(A)=12H,(R0)=33H,(21H)=32H,(34H)=22H,DPTR=1234H。执行下面的指令:

           INC A (A)=13H

           INC R2 (R0)=34H

           INC 21H (21H)=33H

           INC @R0 (34H)=23H

           INC DPTR 9; ( DPTR)=1235H

           结果如上所示。

           说明:从结果上看INC A和ADD A,#1差不多,但INC A是单字节,单周期指令,而ADD #1则是双字节,双周期指令,而且INC A不会影响PSW位,如(A)=0FFH,INC A后(A)=00H,而CY依然保持不变。如果是ADD A ,#1,则(A)=00H,而CY一定是1。因此加1指令并不适合做加法,事实上它主要是用来做计数、地址增加等用途。另外,加法类指令都是以A为核心的��其中一个数必须放在A中,而运算结果也必须放在A中,而加1类指令的对象则广泛得多,可以是寄存器、内存地址、间址寻址的地址等等。

     

        7.减1指令

           DEC A

           DEC RN

           DEC direct

           DEC @Ri

           与加1指令类似,就不多说了

     

        逻辑运算类指令:

        1. 对累加器A的逻辑操作:

           CLR A ;将A中的值清0,单周期单字节指令,与MOV A,#00H效果相同。

           CPL A ;将A中的值按位取反

           RL A ;将A中的值逻辑左移

           RLC A ;将A中的值加上进位位进行逻辑左移

           RR A ;将A中的值进行逻辑右移

           RRC A ;将A中的值加上进位位进行逻辑右移

           SWAP A ;将A中的值高、低4位交换。

     

          例:(A)=73H,则执行CPL A,这样进行:

           73H化为二进制为01110011,

           逐位取反即为 10001100,也就是8CH。

           RL A是将(A)中的值的第7位送到第0位,第0位送1位,依次类推。

     

          例:A中的值为68H,执行RL A。68H化为二进制为01101000,按上图进行移动。01101000化为11010000,即D0H。

           RLC A,是将(A)中的值带上进位位(C)进行移位。

     

          例:A中的值为68H,C中的值为1,则执行RLC A

           1 01101000后,结果是0 11010001,也就是C进位位的值变成了0,而(A)则变成了D1H。

           RR A和RRC A就不多谈了,请大家参考上面两个例子自行练习吧。

           SWAP A,是将A中的值的高、低4位进行交换。

     

          例:(A)=39H,则执行SWAP A之后,A中的值就是93H。怎么正好是这么前后交换呢?因为这是一个16进制数,每1个16进位数字代表4个二进位。注意,如果是这样的:(A)=39,后面没H,执行SWAP A之后,可不是(A)=93。要将它化成二进制再算:39化为二进制是10111,也就是0001,0111高4位是0001,低4位是0111,交换后是01110001,也就是71H,即113。

     

        2.逻辑与指令

           ANL              A,Rn        ;A与Rn中的值按位'与',结果送入A中

           ANL              A,direct ;A与direct中的值按位'与',结果送入A中

           ANL              A,@Ri ;A与间址寻址单元@Ri中的值按位'与',结果送入A中

           ANL              A,#data ;A与立即数data按位'与',结果送入A中

           ANL              direct,A ;direct中值与A中的值按位'与',结果送入direct中

           ANL              direct,#data ;direct中的值与立即数data按位'与',结果送入direct中。

     

          这几条指令的关键是知道什么是逻辑与。这里的逻辑与是指按位与

           例:71H和56H相与则将两数写成二进制形式:

           (71H) 01110001

           (56H) 00100110

           结果 00100000 即20H,从上面的式子可以看出,两个参与运算的值只要其中有一个位上是0,则这位的结果就是0,两个同是1,结果才是1。

           理解了逻辑与的运算规则,结果自然就出来了。看每条指令后面的注释

          下面再举一些例子来看。

             MOV              A,#45H ;(A)=45H

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

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

             ANL              A,@R1 ;45H与79H按位与,结果送入A中为 41H (A)=41H

             ANL              25H,#15H ;25H中的值(79H)与15H相与结果为(25H)=11H)

             ANL              25H,A ;25H中的值(11H)与A中的值(41H)相与,结果为(25H)=11H

           在知道了逻辑与指令的功能后,逻辑或和逻辑异或的功能就很简单了。逻辑或是按位“或”,即有“1”为1,全“0”为0。例:

             10011000

            或 01100001

          结果 11111001

             而异或则是按位“异或”,相同为“0”,相异为“1”。例:

             10011000

           异或 01100001

           结果 11111001

           而所有的或指令,就是将与指令中的ANL 换成ORL,而异或指令则是将ANL       换成XRL。

         

        3..逻辑或指令:

           ORL              A,Rn        ;A和Rn中的值按位'或',结果送入A中

           ORL              A,direct ;A和与间址寻址单元@Ri中的值按位'或',结果送入A中

           ORL              A,#data ;A和立direct中的值按位'或',结果送入A中

           ORL              A,@Ri ;A和即数data按位'或',结果送入A中

           ORL              direct,A ;direct中值和A中的值按位'或',结果送入direct中

           ORL              direct,#data ;direct中的值和立即数data按位'或',结果送入direct中。

     

        4.逻辑异或指令:

           XRL              A,Rn        ;A和Rn中的值按位'异或',结果送入A中

           XRL              A,direct ;A和direct中的值按位'异或',结果送入A中

           XRL              A,@Ri ;A和间址寻址单元@Ri中的值按位'异或',结果送入A中

           XRL              A,#data ;A和立即数data按位'异或',结果送入A中

           XRL              direct,A ;direct中值和A中的值按位'异或',结果送入direct中

           XRL              direct,#data ;direct中的值和立即数data按位'异或',结果送入direct中。

     

         控制转移类指令

       一、无条件转移类指令

         1.短转移类指令

           AJMP       addr11

     

        2.长转移类指令

           LJMP       addr16

     

        3.相对转移指令

           SJMP       rel

     

          上面的三条指令,如果要仔细分析的话,区别较大,但初学时,可不理会这么多,统统理解成:JMP标号,也就是跳转到一个标号处。事实上,LJMP标号,在前面的例程中我们已接触过,并且也知道如何来使用了。而AJMP和SJMP也是一样。那么他们的区别何在呢?在于跳转的范围不一样。好比跳远,LJMP一下就能跳64K这么远(当然近了更没关系了)。而AJMP最多只能跳2K距离,而SJMP则最多只能跳256这么远。原则上,所有用SJMP或AJMP的地方都可以用LJMP来替代。因此在初学时,需要跳转时可以全用LJMP,除了一个场合。什么场合呢?先了解一下AJMP,AJMP是一条双字节指令,也就说这条指令本身占用存储器(ROM)的两个单元。而LJMP则是三字节指令,即这条指令占用存储器(ROM)的三个单元。下面是第四条跳转指令。

     

        二、间接转移指令

           JMP         @A+DPTR

           这条指令的用途也是跳转,转到什么地方去呢?这可不能由标号简单地决定了。让我们从一个实际的例子入手吧。

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

           MOV    A,R0                  ;从R0中取数(详见下面说明)

           MOV    B,#2                        

           MUL    A,B           ;A中的值乘2(详见下面的说明)

           JMP    A,@A+DPTR      ;跳转

           TAB:      AJMP     S1          ;跳转表格

           AJMP     S2

           AJMP     S3

     

          应用背景介绍:在单片机开发中,经常要用到键盘,见上面的9个按键的键盘。我们的要求是:当按下功能键A………..G时去完成不同的功能。这用程序设计的语言来表达的话,就是:按下不同的键去执行不同的程序段,以完成不同的功能。怎么样来实现呢?

          前面的程序读入的是按键的值,如按下'A'键后获得的键值是0,按下'B'键后获得的值是'1'等等,然后根据不同的值进行跳转,如键值为0就转到S1执行,为1就转到S2执行。。。。如何来实现这一功能呢?

          先从程序的下面看起,是若干个AJMP语句,这若干个AJMP语句最后在存储器中是这样存放的,也就是每个AJMP语句都占用了两个存储器的空间,并且是连续存放的。而AJMP S1存放的地址是TAB,到底TAB等于多少,我们不需要知道,把它留给汇编程序来算好了。

          下面我们来看这段程序的执行过程:第一句MOV DPTR,#TAB执行完了之后,DPTR中的值就是TAB,第二句是MOV A,R0,我们假设R0是由按键处理程序获得的键值,比如按下A键,R0中的值是0,按下B键,R0中的值是1,以此类推,现在我们假设按下的是B键,则执行完第二条指令后,A中的值就是1。并且按我们的分析,按下B后应当执行S2这段程序,让我们来看一看是否是这样呢?第三条、第四条指令是将A中的值乘2,即执行完第4条指令后A中的值是2。下面就执行JMP @A+DPTR了,现在DPTR中的值是TAB,而A+DPTR后就是TAB+2,因此,执行此句程序后,将会跳到TAB+2这个地址继续执行。看一看在TAB+2这个地址里面放的是什么?就是AJMP    S2这条指令。因此,马上又执行AJMP              S2指令,程序将跳到S2处往下执行,这与我们的要求相符合。

          请大家自行分析按下键“A”、“C”、“D”……之后的情况。

          这样我们用JMP     @A+DPTR就实现了按下一键跳到相应的程序段去执行的这样一个要求。再问大家一个问题,为什么取得键值后要乘2?如果例程下面的所有指令换成LJMP,即:

              LJMP      S1,LJMP        S2……这段程序还能正确地执行吗?如果不能,应该怎么改?

     

        三、条件转移指令:

     条件转移指令是指在满足一定条件时进行相对转移。 

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

           JZ rel

           JNZ rel

           第一指令的功能是:如果(A)=0,则转移,否则顺序执行(执行本指令的下一条指令)。转移到什么地方去呢?如果按照传统的方法,就要算偏移量,很麻烦,好在现在我们可以借助于机器汇编了。因此这第指令我们可以这样理解:JZ 标号。即转移到标号处。下面举一例说明:

           MOV A,R0

           JZ L1

           MOV R1,#00H

           AJMP L2

           L1: MOV R1,#0FFH

           L2: SJMP L2

           END

           在执行上面这段程序前如果R0中的值是0的话,就转移到L1执行,因此最终的执行结果是R1中的值为0FFH。而如果R0中的值不等于0,则顺序执行,也就是执行 MOV R1,#00H指令。最终的执行结果是R1中的值等于0。

           第一条指令的功能清楚了,第二条当然就好理解了,如果A中的值不等于0,就转移。把上面的那个例子中的JZ改成JNZ试试吧,看看程序执行的结果是什么?

     

        2.比较转移指令

           CJNE A,#data,rel

           CJNE A,direct,rel

           CJNE Rn,#data,rel

           CJNE @Ri,#data,rel

           第一条指令的功能是将A中的值和立即数data比较,如果两者相等,就顺序执行(执行本指令的下一条指令),如果不相等,就转移,同样地,我们可以将rel理解成标号,即:CJNE A,#data,标号。这样利用这条指令,我们就可以判断两数是否相等,这在很多场合是非常有用的。但有时还想得知两数比较之后哪个大,哪个小,本条指令也具有这样的功能,如果两数不相等,则CPU还会反映出哪个数大,哪个数小,这是用CY(进位位)来实现的。如果前面的数(A中的)大,则CY=0,否则CY=1,因此在程序转移后再次利用CY就可判断出A中的数比data大还是小了。

           例:

             MOV A,R0

             CJNE A,#10H,L1

             MOV R1,#0FFH

             AJMP L3

             L1: JC L2

             MOV R1,#0AAH

             AJMP L3

             L2: MOV R1,#0FFH

             L3: SJMP L3

             上面的程序中有一条指令我们还没学过,即JC,这条指令的原型是JC rel,作用和上面的JZ类似,但是它是判CY是0,还是1进行转移,如果CY=1,则转移到JC后面的标号处执行,如果CY=0则顺序执行(执行它的下面一条指令)。

             分析一下上面的程序,如果(A)=10H,则顺序执行,即R1=0。如果(A)不等于10H,则转到L1处继续执行,在L1处,再次进行判断,如果(A)>10H,则CY=1,将顺序执行,即执行MOV R1,#0AAH指令,而如果(A)<10H,则将转移到L2处指行,即执行MOV R1,#0FFH指令。因此最终结果是:本程序执行前,如果(R0)=10H,则(R1)=00H,如果(R0)>10H,则(R1)=0AAH,如果(R0)<10H,则(R1)=0FFH。

             弄懂了这条指令,其它的几条就类似了,第二条是把A当中的值和直接地址中的值比较,第三条则是将直接地址中的值和立即数比较,第四条是将间址寻址得到的数和立即数比较,这里就不详谈了,下面给出几个相应的例子。

             CJNE A,10H ;把A中的值和10H中的值比较(注意和上题的区别)

             CJNE 10H,#35H ;把10H中的值和35H中的值比较

             CJNE @R0,#35H ;把R0中的值作为地址,从此地址中取数并和35H比较

     

        3.循环转移指令

           DJNZ Rn,rel

           DJNZ direct,rel

           第一条指令在前面的例子中有详细的分析,这里就不多谈了。第二条指令,只是将Rn改成直接地址,其它一样,也不多说了,给一个例子。

           DJNZ 10H,LOOP

     

              调用与返回指令

           (1)主程序与子程序 在前面的灯的实验中,我们已用到过了子程序,只是我们并没有明确地介绍。子程序是干什么用的,为什么要用子程序技术呢?举个例子,我们数据老师布置了10道算术题,经过观察,每一道题中都包含一个(3*5+2)*3的运算,我们可以有两种选择,第一种,每做一道题,都把这个算式算一遍,第二种选择,我们可以先把这个结果算出来,也就是51,放在一边,然后要用到这个算式时就将51代进去。这两种方法哪种更好呢?不必多言。设计程序时也是这样,有时一个功能会在程序的不同地方反复使用,我们就可以把这个功能做成一段程序,每次需要用到这个功能时就“调用”一下。

     

          (2)调用及回过程:主程序调用了子程序,子程序执行完之后必须再回到主程序继续执行,不能“一去不回头”,那么回到什么地方呢?是回到调用子程序的下面一条指令继续执行(当然啦,要是还回到这条指令,不又要再调用子程序了吗?那可就没完没了了……)。 

     

        位及位操作指令

          通过前面那些流水灯的例子,我们已经习惯了“位”一位就是一盏灯的亮和灭,而我们学的指令却全都是用“字节”来介绍的:字节的移动、加法、减法、逻辑运算、移位等等。用字节来处理一些数学问题,比如说:控制冰箱的温度、电视的音量等等很直观,可以直接用数值来表在。可是如果用它来控制一些开关的打开和合上,灯的亮和灭,就有些不直接了,记得我们上次课上的流水灯的例子吗?我们知道送往P1口的数值后并不能马上知道哪个灯亮和来灭,而是要化成二进制才知道。工业中有很多场合需要处理这类开关输出,继电器吸合,用字节来处理就显示有些麻烦,所以在8031单片机中特意引入一个位处理机制。

        一、.位寻址区

          在8031中,有一部份RAM和一部份SFR是具有位寻址功能的,也就是说这些RAM的每一个位都有自已的地址,可以直接用这个地址来对此进行操作。

    字节地址

    位地址

    2FH

    7FH

     

     

     

     

     

     

    78H

    2EH

    77H

     

     

     

     

     

     

    70

    2DH

    6FH

     

     

     

     

     

     

    68H

    2CH

    67H

     

     

     

     

     

     

    60H

    2BH

    5FH

     

     

     

     

     

     

    58H

    2AH

    57H

     

     

     

     

     

     

    50H

    29H

    4FH

     

     

     

     

     

     

    48H

    28H

    47H

     

     

     

     

     

     

    40H

    27H

    3FH

     

     

     

     

     

     

    38H

    26H

    37H

     

     

     

     

     

     

    30H

    25H

    2FH

     

     

     

     

     

     

    28H

    24H

    27H

     

     

     

     

     

     

    20H

    23H

    1FH

     

     

     

     

     

     

    18H

    22H

    17H

     

     

     

     

     

     

    10H

    21H

    0FH

     

     

     

     

     

     

    08H

    20H

    07H

    06H

    05H

    04H

    03H

    02H

    01H

    00H

    图1

            内部RAM的20H-2FH这16个字节,就是8031的位寻址区。看图1。可见这里面的每一个RAM中的每个位我们都可能直接用位地址来找到它们,而不必用字节地址,然后再用逻辑指令的方式。

     

         二、可以位寻址的特殊功能寄存器

          8031中有一些SFR是可以进行位寻址的,这些SFR的特点是其字节地址均可被8整除,如A累加器,B寄存器、PSW、IP(中断优先级控制寄存器)、IE(中断允许控制寄存器)、SCON(串行口控制寄存器)、TCON(定时器/计数器控制寄存器)、P0-P3(I/O端口锁存器)。以上的一些SFR我们还不熟,等我们讲解相关内容时再作详细解释。

        三、位操作指令

          MCS-51单片机的硬件结构中,有一个位处理器(又称布尔处理器),它有一套位变量处理的指令集。在进行位处理时,CY(就是我们前面讲的进位位)称“位累加器”。有自已的位RAM,也就是我们刚讲的内部RAM的20H-2FH这16个字节单元即128个位单元,还有自已的位I/O空间(即P0.0…..P0.7,P1.0…….P1.7,P2.0……..P2.7,P3.0……..P3.7)。当然在物理实体上它们与原来的以字节寻址用的RAM,及端口是完全相同的,或者说这些RAM及端口都可以有两种用法。

            1..位传送指令

              MOV C,BIT

              MOV BIT,C

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

            例:MOV P1.0,CY ;将CY中的状态送到P1.0引脚上去(如果是做算术运算,我们就可以通过观察知道现在CY是多少啦)。

              MOV P1.0,CY ;将P1.0的状态送给CY。

     

          2..位修正指令

              位清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 ;使CY等于原来的相反的值,由1变为0,由0变为1。

                CPL bit ;使指定的位的值等于原来相反的值,由0变为1,由1变为0。

                例:CPL P1.0

                以我们做过的实验为例,如果原来灯是亮的,则执行本指令后灯灭,反之原来灯是灭的,执行本指令后灯亮。

        四、位逻辑运算指令

        1..位与指令

          ANL C,bit ;CY与指定的位地址的值相与,结果送回CY

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

          例:ANL C,/P1.0

          设执行本指令前,CY=1,P1.0等于1(灯灭),则执行完本指令后CY=0,而P1.0也是等于1。

          可用下列程序验证:

            ORG 0000H

            AJMP START

            ORG 30H

            START: MOV SP,#5FH

            MOV P1,#0FFH

            SETB C

            ANL C,/P1.0

            MOV P1.1,C ;将做完的结果送P1.1,结果应当是P1.1上的灯亮,而P1.0上的灯还是不亮。

        2..位或指令

          ORL C,bit

          ORL C,/bit

          这个的功能大家自行分析吧,然后对照上面的例程,编一个验证程序,看看你相得对吗?

        五、位条件转移指令

        1..判CY转移指令

          JC rel

          JNC rel

          第一条指令的功能是如果CY等于1就转移,如果不等于1就顺序执行。那么转移到什么地方去呢?我们可以这样理解:JC 标号,如果等于1就转到标号处执行。这条指令我们在上节课中已讲到,不再重复。

          第二条指令则和第一条指令相反,即如果CY=0就转移,不等于0就顺序执行,当然,我们也同样理解: JNC 标号

     

        2..判位变量转移指令

          JB bit,rel

          JNB bit,rel

          第一条指令是如果指定的bit位中的值是1,则转移,否则顺序执行。同样,我们可以这样理解这条指令:JB bit,标号

          第二条指令请大家先自行分析

          下面我们举个例子说明:

            ORG 0000H

            LJMP START

            ORG 30H

            START:MOV SP,#5FH

            MOV P1,#0FFH

            MOV P3,#0FFH

            L1: JNB P3.2,L2 ;P3.2上接有一只按键,它按下时,P3.2=0

            JNB P3.3,L3 ;P3.3上接有一只按键,它按下时,P3.3=0

            LJM P L1

            L2: MOV P1,#00H

            LJMP L1

            L3: MOV P1,#0FFH

            LJMP L1

            END

            把上面的例子写入片子,看看有什么现象………

            按下接在P3.2上的按键,P1口的灯全亮了,松开或再按,灯并不熄灭,然后按下接在P3.3上的按键,灯就全灭了。这像什么?这不就是工业现场经常用到的“启动”、“停止”的功能吗?

            怎么做到的呢?一开始,将0FFH送入P3口,这样,P3的所有引线都处于高电平,然后执行L1,如果P3.2是高电平(键没有按下),则顺序执行JNB P3.3,L3语句,同样,如果P3.3是高电平(键没有按下),则顺序执行LJMP L1语句。这样就不停地检测P3.2、P3.3,如果有一次P3.2上的按键按下去了,则转移到L2,执行MOV P1,#00H,使灯全亮,然后又转去L1,再次循环,直到检测到P3.3为0,则转L3,执行MOV P1,#0FFH,例灯全灭,再转去L1,如此循环不已。

            改程序还可以用JB来写 略

    展开全文
  • 51单片机学习之汇编语言实验一 学51单片机的时候老师上课是用汇编语言教的,但实际应用中很少用到汇编语言,本次将学习期间做的实验分享出来,和刚刚学习51汇编的朋友一起学习,新手一个,有错望指正。 实验内容如下...

    51单片机学习之汇编语言实验一

    学51单片机的时候老师上课是用汇编语言教的,但实际应用中很少用到汇编语言,本次将学习期间做的实验分享出来,和刚刚学习51汇编的朋友一起学习,新手一个,有错望指正。

    实验内容如下:

    • 实验一 P1口的应用
      在单片机的P1口的低四位接了四个LED灯,灯的接法是共阳极,高四位接了四个开关,开关闭和,相应管脚被拉成低电平。
      要求:
      K3 K2 K1 K0
      0 0 0 0 灯全亮
      0 0 0 1 灯全灭
      0 0 1 0 一灯亮其余灯灭并左循环
      0 0 1 1 一灯亮其余灯灭并右循环
      0 1 0 0 一灯灭其余灯亮并左循环
      0 1 0 1 一灯灭其余灯亮并右循环
      1 X X X 显示状态开关Ki为0,Li亮

    我的代码如下:
    ;***** 2019-5-7 DXZ *******
    ;汇编语言作业-P1口的应用

    ;*****    2019-5-7 DXZ   *******      
    ;****汇编语言作业-P1口的应用****
    
     ORG    000H
    		  
        Key_state  EQU 40H
        Key_data  EQU 41H
        Led_data  EQU 42H		
    STRT: MOV    A, P1             ;取P1的值放入ACC
          SWAP   A                 ;ACC本身高低四位互换
    	   ANL    A, #0FH           ;取原来A(也就是P1)的高四位,即开关的状态
    	   MOV    Key_data, A            ;将A的值送入41H地址单元
    	   MOV    Key_state, #0FFH        ;将0xFF送入40H,(开关状态改变,置1)
    	  
    MLP0: CJNE   A, #6, $ + 3       ;A中数据与6比较,是否相等都执行JNC那条指令
    	                            ;即判断开关状态代表的值是否大于6
    	  JNC    PK6                ;判断CY,为0则转移执行PK6处代码
    	  MOV    DPTR, #CTAB       ;将CTAB数据表首地址传入DPTR
    	  MOV    R1, A             ;把ACC的值送入R1
    	  RL     A                 ;左移一位
    	  ADD    A, R1             ;将A与R1的值相加后送回A(偏移量*3,三字节指令)
    	  JMP    @A+DPTR           ;变址寻址,根据开关状态取CTAB对应指令
    	  
    	                           ;转移指令组成的指令表
    CTAB: LJMP   PK0               ;灯全亮
          LJMP   PK1               ;灯全灭
    	   LJMP   PK2               ;一个灯亮其他灯灭并循环左移
    	   LJMP   PK3               ;一个灯亮其他灯灭并循环右移
    	   LJMP   PK4               ;一个灯灭其他灯亮并循环左移
    	   LJMP   PK5               ;一个灯灭其他灯亮并循环右移
    	  
    PK6:  MOV    Led_data, A            ;开关Kn闭合,电灯Ln亮(n为0-3)
          LJMP   MLP1
    	  
    PK5:  MOV    A, Key_state            ;0
          CJNE   A, #0FFH, PK51    ;比较转移,判断开关状态是否发生改变,未改变则跳转
          MOV    Led_data, #08H         ;05初状态,D3灭,其它亮
          LJMP   MLP1
    	  
    PK51: MOV    A, Led_data
          MOV    P2, Led_data
          RR     A                 ;X  
    	  ANL    A, #0FH
    	  JNZ    PK52              ;判断ACC是否不为0,即是否移位到0x01
    	  MOV    A, #08H           ;重设初值
    	  
    PK52: MOV    Led_data, A
          LJMP   MLP1
    	  
    PK4:  MOV    A, Key_state 
          CJNE   A, #0FFH, PK41    ;比较转移,判断开关状态是否发生改变,
    	  MOV    Led_data, #1           ;;04初状态,D0灭,其它亮
    	  LJMP   MLP1     
    PK41: MOV    A, Led_data
          RL     A
    	  ANL    A, #0FH
    	  JNZ    PK42              ;判断A是否为不为0,是则跳转
    	  MOV    A, #1             ;04初状态,D0灭,其它亮
    PK42: MOV    Led_data, A
          LJMP   MLP1
    	  
    PK3:  MOV    A, Key_state
          CJNE   A, #0FFH, PK31     ;比较转移,判断开关状态是否发生改变,
    	  MOV    Led_data, #0F7H         ;03初状态,D3亮其它灯灭
    	  LJMP   MLP1
    	  
    PK31: MOV    A, Led_data
          RR     A
    	  ANL    A, #0FH
    	  CJNE   A, #0FH, PK32
    	  MOV    A, #0F7H
    	  
    PK32: ORL    A, #0F0H
          MOV    Led_data, A
    	  LJMP   MLP1
    	  
    PK2:  MOV    A, Key_state            ;40H单元数据送A
          CJNE   A, #0FFH, PK21    ;比较转移,判断开关状态是否发生改变,
    	                           ;未变则跳转执行PK21
    	  MOV    Led_data, #0FEH        ;改变送0xFE至42H地址单元
          LJMP   MLP1              ;长跳转
    
    PK21: MOV    A, Led_data            ;
          RL     A                 ;A中数据向左移位
    	  ANL    A, #0FH           ;位与,结果放A(取低四位)
    	  CJNE   A, #0FH, PK22     ;
    	  MOV    A, #0FEH          ;
    	  
    PK22: ORL    A, #0F0H
          MOV    Led_data, A
    	  LJMP   MLP1
    
    PK1:  MOV    Led_data, #0FH          ;将16进制数0x0F送入42H地址单元
          LJMP   MLP1               ;跳转至MLP1代码段入口
    	  
    PK0:  MOV    Led_data, #0            ;42H储存灯的状态,4个灯全亮
    
                                       ;MLP1实现状态输出功能
    MLP1: MOV    A, Led_data             ;将42H单元数据送A
          ORL    A, #0F0H             ;取低四位(并使高四位置1)
    	   MOV    P1, A                 ;送P1口
    	   MOV    R7, #3                ;延时外层(共三层)定初值,
    	   MOV    R6, #0	               ;延时次外层层(共三层)定初值,
    	   MOV    R5, #0
    DEL1: DJNZ   R5, DEL1               ;本指令(内层)循环256次,共循环256*256*3次
          DJNZ   R6, DEL1               ;
    	   DJNZ   R7, DEL1
    	  MOV    A, P1                   ;取P1口状态
    	  SWAP   A                       ;
    	  ANL    A, #0FH                 ;高低位交换,取P1高位(读取开关状态)
    	  CJNE   A, Key_data, MLP2       ;比较跳转,A与41H所存数据不相等则跳转至MLP2
    	                                  ;即判断开关状态是否改变
    	  MOV    Key_state, #0            ;开关状态没有改变,则往40H单元写0
    	  LJMP   MLP0                   ;长跳转
    	  
    MLP2: MOV    Key_data, A            ;写入新的开关状态
          MOV    Key_state, #0FFH        ;开关状态发生改变,则往40H单元写1
    	   LJMP   MLP0                  ;跳转至MLP0
    	  	                            
         END                             ;伪指令,结束汇编程序
    	  
    
    

    下次分分享剩下的实验内容

    展开全文
  • 本文以AT89C51为例,列举51单片机汇编语言指令集。 AT89C51单片机的汇编指令共有111条,可按功能分为5大类: 数据传送类指令28条; 算数操作类指令24条; 逻辑运算类指令25条; 控制转移类17条; 位操作类17条。 ...

    本文以AT89C51为例,列举51单片机汇编语言指令集。
    AT89C51单片机的汇编指令共有111条,可按功能分为5大类:

    数据传送类指令28条;
    算数操作类指令24条;
    逻辑运算类指令25条;
    控制转移类17条;
    位操作类17条。

    在此约定下列指令中各符号的意义:

    Rn:当前寄存器区的8个工作寄存器(n=0~7)
    Ri:当前寄存器区中可作间接寻址寄存器的2个寄存器(i=0 1)
    Direct:直接地址
    #data:包含在指令中的8位立即数
    rel:相对转移指令中的偏移量,为8位带符号补码数
    DPTR:数据指针,16位数据地址寄存器
    bit:直接寻址位
    C:进位标志位
    addr11:11位目的地址
    addr16:16位目的地址
    @:间接寻址寄存器前缀

    一、数据传送类指令

    1.以累加器为目的操作数指令

    MOV A,Rn
    MOV A,@Ri
    MOV A,direct
    MOV A,#data

    2.以Rn为目的操作数的指令

    MOV Rn,A
    MOV Rn,direct
    MOV Rn,#data

    3.以直接地址为目的操作数指令

    MOV direct,A
    MOV direct,Rn
    MOV direct1,direct2
    MOV direct,@Ri
    MOV direct,#data

    4.以寄存器间接地址为目的操作数指令

    MOV @Ri,A
    MOV @Ri,direct
    MOV @Ri,#data

    5.16位传送指令

    MOV DPTR,#data16

    6.堆栈操作指令

    进栈:PUSH direct
    出栈:POP direct

    7.累加器A与外部数据存储器传送指令

    MOVX A,@DPTR
    MOVX A,@Ri
    MOVX @DPTR,A
    MOVX @Ri,A

    8.查表指令

    MOVC A,@A+PC
    MOVC A,@A+DPTR

    9.字节交换命令

    XCH A,Rn
    XCH A,direct
    XCH A,@Ri

    10.半字节交换指令

    XCHD @Ri

    二、算数操作类指令

    1.加法指令

    ADD A,Rn
    ADD A,direct
    ADD A,@Ri
    ADD A,#data

    2.带进位加法指令

    ADDC A,Rn
    ADDC A,direct
    ADDC A,@Ri
    ADDC A,#data

    3.增1指令

    INC A
    INC Rn
    INC direct
    INC @Ri
    INC DPTR

    4.十进制调整指令

    DA A

    5.带借位减法

    SUBB A,Rn
    SUBB A,direct
    SUBB A,@Ri
    SUBB A,#data

    6.减1指令

    DEC A
    DEC Rn
    DEC direct
    DEC @Ri

    7.乘法指令

    MUL AB

    8.除法指令

    DIV AB

    三、逻辑操作类指令

    1.简单逻辑操作指令

    累加器A清零:
    CLR A
    累加器A按位取反:
    CPL A

    2.左循环指令

    RL A

    3.带进位左移指令

    RLC A

    4.右移指令

    RR A

    5.带进位循环指令

    RRC A

    6.累加器半字节交换指令

    SWAP A

    7.逻辑与指令

    ANL A,Rn
    ANL A,direct
    ANL A,#data
    ANL A,@Ri
    ANL direct,A
    ANL direct,#data

    7.逻辑或指令

    ORL A,Rn
    ORL A,direct
    ORL A,#data
    ORL A,@Ri
    ORL direct,A
    ORL direct,#data

    7.逻辑异或指令

    XRL A,Rn
    XRL A,direct
    XRL A,#data
    XRL A,@Ri
    XRL direct,A
    XRL direct,#data

    四、控制转移类指令

    1.无条件转移指令

    AJMP addr11

    2.相对转移指令

    SJMP rel

    3.长跳转指令

    LJMP addr16

    4.间接跳转指令

    JMP @A+DPTR

    5.条件转移指令

    若累加器为0则转移:
    JZ rel
    若累加器非0则转移:
    JNZ rel

    6.比较不相等转移指令

    CJNE A,direct,rel
    CJNE A,#data,rel
    CJNE Rn,#data,rel
    CJNE @Ri,#data,rel

    7.减1不为0转移指令

    DJNZ Rn,rel
    DJNZ direct,rel

    8.调用子程序指令

    ACALL addr11
    LCALL addr16

    9.子程序返回指令

    RET

    10.中断返回指令

    RETI

    11.空操作指令

    NOP

    五、位操作指令

    1.数据位传送指令

    MOV C,bit
    MOV bit,C

    2.位变量修改指令

    清0:
    CLR C
    CLR bit
    求反:
    CPL C
    CPL bit
    置1:
    SETB C
    SETB bit

    3.位变量逻辑与指令

    ANL C,bit
    ANL C,/bit

    3.位变量逻辑或指令

    ORL C,bit
    ORL C,/bit

    4.条件转移类指令

    JC rel
    JNC rel
    JB bit,rel
    JNB bit,rel
    JBC bit,rel

    展开全文
  • 51单片机汇编指令 ;汇编语言指令格式 [标号:] 操作码 [第一操作数] [,第二操作数] [,第三操作数] [;注释] 操作码 操作数 字节数 周期数 数据传递类指令 MOV A,Rn 寄存器传送到累加器 1 MOV A...

    实验基础

    51单片机

    本门课程硬件平台为ATMEL公司的AT89C52单片机,在Proteus软件进行仿真实验。

    51单片机是8位单片机、8k ROM 、256bytes RAM、四个8位并行I/O口在这里插入图片描述

    汇编语言

    本门课程使用汇编语言编程。

    51单片机汇编指令

    ;汇编语言指令格式
    [标号:]  操作码 [第一操作数] [,第二操作数] [,第三操作数] [;注释] 
    
    操作码 操作数 字节数 周期数
    数据传递类指令
    MOV A,Rn 寄存器传送到累加器 1
    MOV A,direct 直接地址传送到累加器 2
    MOV A,@Ri 累加器传送到外部RAM(8 地址) 1
    MOV A,#data 立即数传送到累加器 2
    MOV Rn,A 累加器传送到寄存器 1
    MOV Rn,direct 直接地址传送到寄存器 2
    MOV Rn,#data 累加器传送到直接地址 2
    MOV direct,Rn 寄存器传送到直接地址 2
    MOV direct,direct 直接地址传送到直接地址 3
    MOV direct,A 累加器传送到直接地址 2
    MOV direct,@Ri 间接RAM 传送到直接地址 2
    MOV direct,#data 立即数传送到直接地址 3
    MOV @Ri,A 直接地址传送到直接地址 1
    MOV @Ri,direct 直接地址传送到间接RAM 2
    MOV @Ri,#data 立即数传送到间接RAM 2
    MOV DPTR,#data16 16 位常数加载到数据指针 3
    MOVC A,@A+DPTR 代码字节传送到累加器 1
    MOVC A,@A+PC 代码字节传送到累加器 1
    MOVX A,@Ri 外部RAM(8 地址)传送到累加器 1
    MOVX A,@DPTR 外部RAM(16 地址)传送到累加器 1
    MOVX @Ri,A 累加器传送到外部RAM(8 地址) 1
    MOVX @DPTR,A 累加器传送到外部RAM(16 地址) 1
    PUSH direct 直接地址压入堆栈 2
    POP direct 直接地址弹出堆栈 2
    XCH A,Rn 寄存器和累加器交换 1
    XCH A, direct 直接地址和累加器交换 2
    XCH A, @Ri 间接RAM 和累加器交换 1
    XCHD A, @Ri 间接RAM 和累加器交换低4 位字节 1
    (算术运算类指令)
    INC A 累加器加1 1
    INC Rn 寄存器加1 1
    INC direct 直接地址加1 2
    INC @Ri 间接RAM 加1 1
    INC DPTR 数据指针加1 1
    DEC A 累加器减1 1
    DEC Rn 寄存器减1 1
    DEC direct 直接地址减1 2
    DEC @Ri 间接RAM 减1 1
    MUL AB 累加器和B 寄存器相乘 1
    DIV AB 累加器除以B 寄存器 1
    DA A 累加器十进制调整 1
    ADD A,Rn 寄存器与累加器求和 1
    ADD A,direct 直接地址与累加器求和 2
    ADD A,@Ri 间接RAM 与累加器求和 1
    ADD A,#data 立即数与累加器求和 2
    ADDC A,Rn 寄存器与累加器求和(带进位) 1
    ADDC A,direct 直接地址与累加器求和(带进位) 2
    ADDC A,@Ri 间接RAM 与累加器求和(带进位) 1
    ADDC A,#data 立即数与累加器求和(带进位) 2
    SUBB A,Rn 累加器减去寄存器(带借位) 1
    SUBB A,direct 累加器减去直接地址(带借位) 2
    SUBB A,@Ri 累加器减去间接RAM(带借位) 1
    SUBB A,#data 累加器减去立即数(带借位) 2
    (逻辑运算类指令)
    ANL A,Rn 寄存器“与”到累加器 1
    ANL A,direct 直接地址“与”到累加器 2
    ANL A,@Ri 间接RAM“与”到累加器 1
    ANL A,#data 立即数“与”到累加器 2
    ANL direct,A 累加器“与”到直接地址 2
    ANL direct, #data 立即数“与”到直接地址 3
    ORL A,Rn 寄存器“或”到累加器 1
    ORL A,direct 直接地址“或”到累加器 2
    ORL A,@Ri 间接RAM“或”到累加器 1
    ORL A,#data 立即数“或”到累加器 2
    ORL direct,A 累加器“或”到直接地址 2
    ORL direct, #data 立即数“或”到直接地址 3
    XRL A,Rn 寄存器“异或”到累加器 1
    XRL A,direct 直接地址“异或”到累加器 2
    XRL A,@Ri 间接RAM“异或”到累加器 1
    XRL A,#data 立即数“异或”到累加器 2
    XRL direct,A 累加器“异或”到直接地址 2
    XRL direct, #data 立即数“异或”到直接地址 3
    CLR A 累加器清零 1
    CPL A 累加器求反 1
    RL A 累加器循环左移 1
    RLC A 带进位累加器循环左移 1
    RR A 累加器循环右移 1
    RRC A 带进位累加器循环右移 1
    SWAP A 累加器高、低4 位交换 1
    (控制转移类指令)
    JMP @A+DPTR 相对DPTR 的无条件间接转移 1
    JZ rel 累加器为0 则转移 2
    JNZ rel 累加器为1 则转移 2
    CJNE A,direct,rel 比较直接地址和累加器,不相等转移 3
    CJNE A,#data,rel 比较立即数和累加器,不相等转移 3
    CJNE Rn,#data,rel 比较寄存器和立即数,不相等转移 2
    CJNE @Ri,#data,rel 比较立即数和间接RAM,不相等转移 3
    DJNZ Rn,rel 寄存器减1,不为0 则转移 3
    DJNZ direct,rel 直接地址减1,不为0 则转移 3
    NOP 空操作,用于短暂延时 1
    ACALL add11 绝对调用子程序 2
    LCALL add16 长调用子程序 3
    RET 从子程序返回 1
    RETI 从中断服务子程序返回 1
    AJMP add11 无条件绝对转移 2
    LJMP add16 无条件长转移 3
    SJMP rel 无条件相对转移 2
    (布尔指令)
    CLR C 清进位位 1
    CLR bit 清直接寻址位 2
    SETB C 置位进位位 1
    SETB bit 置位直接寻址位 2
    CPL C 取反进位位 1
    CPL bit 取反直接寻址位 2
    ANL C,bit 直接寻址位“与”到进位位 2
    ANL C,/bit 直接寻址位的反码“与”到进位位 2
    ORL C,bit 直接寻址位“或”到进位位 2
    ORL C,/bit 直接寻址位的反码“或”到进位位 2
    MOV C,bit 直接寻址位传送到进位位 2
    MOV bit, C 进位位位传送到直接寻址 2
    JC rel 如果进位位为1 则转移 2
    JNC rel 如果进位位为0 则转移 2
    JB bit,rel 如果直接寻址位为1 则转移 3
    JNB bit,rel 如果直接寻址位为0 则转移 3
    JBC bit,rel 直接寻址位为1 则转移并清除该位 2
    伪指令 格式
    DS 〔标号:〕 DS 表达式值 预留存储区命令
    BIT 字符名称 BIT 位地址 定义位命令
    USING 再定位段名 SEGMENT 段类型〔再定位类型〕 用来声明一个再定位段和一个可选的再定位类型。
    RSEG RSEG 段名 再定位段选择指令
    CSEG CSEG [AT 绝对地址表达式] 绝对代码段
    DSEG DSEG [AT 绝对地址表达式] 内部绝对数据段
    XSEG XSEG [AT 绝对地址表达式] 外部绝对数据段
    ISEG ISEG [AT 绝对地址表达式] 内部间接寻址数据段
    BSEG BSEG [AT 绝对地址表达式] 绝对位寻址数据段
    ORG ORG 表达式 设定一个新的程序起始地址
    END
    EQU 符号名 EQU 表达式 将一个数值或寄存器名赋给一个指定的符号名
    DATA 符号名 DATA 表达式 将一个内部 RAM 的地址赋给指定的符号名
    DB 标号:] DB 表达式表 以表达式的值的字节形式初始化代码空间

    keil4在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    这里进行说明,提示是否添加.s文件,这个是51单片机的启动文件。在用c语言进行编程的时候,是要电机“是”来添加一个启动文件的。在实验课上用汇编语言编写程序并不需要这个启动文件。在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    这样之后就可以在右侧的编辑页面进行编程了

    Proteus仿真软件

    因为手上没有开发板,实验课都是用的proteus仿真软件进行51单片机的仿真。

    老师给的软件版本是8.7SP3但是因为我这里破解出了问题总是闪退还没解决,就用了8.6版本。在这里附上一个Proteus8.7闪退解决办法,可以作为参考。可能是因为盗版系统的原因,这个办法似乎在我的电脑上面并不适用。

    下面开始使用在这里插入图片描述
    在这里插入图片描述
    然后一路点击下一步直到出现原理图界面,中间的选项全部保持默认即不创建pcb,不创建pcb布板设计,没有固件项目在这里插入图片描述
    在原理图界面鼠标中键单击一下可以移动界面,再次单击退出移动。

    鼠标左键单击元件可以选中元件,再次单击可更改元件属性,右键可进行元件的旋转等操作。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    单击元件可选中,再次单击编辑元件在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    实验内容

    第一节课

    第一节课内容为安装和认识keil4集成开发环境。上文已经详细记录。

    第二节课

    万物始于LED。

    第二节课的内容是学会使用Proteus进行仿真和点亮一个LED。

    Proteus软件的简单使用在上文已经记录。

    汇编程序如下:

    ORG 0100H
    SETB  P2.0
    SJMP $        ;无条件相对转移     $就是本句语言的指针地址
     				;SJMP $,就是硬件部分
    END
    

    硬件部分在这里插入图片描述
    在这里插入图片描述

    第三节课

    点亮一个灯之后就是点亮流水灯了。

    汇编程序:

    ORG 0000H
    LJMP MAIN
    
    ORG 0100H
    MAIN:
    MOV A,#80H
    LOOP:
    MOV P2,A
    LCALL DELAY
    RR A  
    LJMP LOOP
    
    DELAY:
    MOV R2,#255
    D1:MOV R3,#250
    D2:DJNZ R3,D2       ;寄存器减1,不为0 则转移
    DJNZ R2,D1
    RET
    
    END
    

    要实现流水灯效果,只需要让累加器A中的1000 0000循环右移,中间加 以延时即可。延时要足够长,否则会看到所有的灯都是亮的。

    延时程序分为两层的循环,D1和D2,分别用到R2、R3两个寄存器。两个八位寄存器,那对应的数字就是0~255注意给寄存器传送立即数时不要超过255。在这里插入图片描述
    硬件连接如图。

    在用Proteus进行仿真时,不需要搭建完整的实验电路,只需要搭建本次实验所需的部分的功能电路即可进行仿真。所以可以不搭建晶振和复位等电路。

    第四节课

    第四节课是用单片机驱动数码管。

    数码管实质上就是LED灯的并联。abcdefg七段显示数字,八段数码管比七段数码管多了一个小数点段h。分为共阴数码管和共阳数码管,在Proteus软件中有这么多数码管可供选择
    在这里插入图片描述
    带有anode描述的即为共阳数码管,其com端接地,输入高电平使对应的段发光。

    带有cathode描述的即为共阴数码管,其com端接vcc,输入低电平使对应的段发光。

    在这里插入图片描述
    汇编程序:

    ORG 0000H
    LJMP MAIN
    
    ORG 0100H
    MAIN:
    MOV DPTR,#TAB
    MOV R2,#0
    MOV R3,#17
    LOOP:
    MOV A,R2
    MOVC A,@A+DPTR
    MOV P2,A
    CPL A     ;累加器求反
    MOV P3,A
    LCALL DELAY
    LCALL DELAY
    LCALL DELAY
    LCALL DELAY
    LCALL DELAY
    LCALL DELAY
    INC R2
    DJNZ R3,LOOP
    LJMP MAIN
    
    DELAY:
    MOV R4,#250
    D1:MOV R5,#250
    D2:DJNZ R5,D2
    DJNZ R4,D1
    RET
    
    TAB:
    DB 0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0X08,0X03,0X46,0X21,0X06,0x0e
    END
    

    各个数字的显示使用查表的方式,下图为各段对应的引脚图。
    img


    前四节课的内容大概就是这些,欢迎指正其中的错误,欢迎各路大佬给些学习意见
    后面的几节课笔记也发出来咯单片机实验笔记(汇编、Proteus仿真)(下)
    在这里插入图片描述

    展开全文
  • 51单片机汇编

    2013-07-18 16:32:29
    单片机使用的机器语言、汇编语言及高级语言,但不管使用是何种语言,最终还是要“翻译”成为机器码,单片机才能执行之。现在有很多半导体厂商都推出了自己的单片机单片机种类繁多,品种数不胜数,值得注意的是不同...
    一个单片机所需执行指令的集合即为单片机的指令系统。单片机使用的机器语言、汇编语言及高级语言,但不管使用是何种语言,最终还是要翻译成为机器码,单片机才能执行之。现在有很多半导体厂商都推出了自己的单片机,单片机种类繁多,品种数不胜数,值得注意的是不同的单片机它们的指令系统不一定相同,或不完全相同。但不管是使用机器语言、汇编语言还是高级语言都是使用指令编写程序的。
    

      所谓机器语言即指令的二进制编码,而汇编语言则是指令的表示符号。在指令的表达式上也不会直接使用二进制机器码,最常用的是十六进制的形式。但单片机并不能直接执行汇编语言和高级语言,都必须通过汇编器翻译成为二进制机器码方能执行,但如果直接使用二进制来编写程序,那将十分不便,也很难记忆和识别,不易编写、难于辨读,极易出错,同时出错了也相当难查找。所以现在基本上都不会直接使用机器语言来编写单片机的程序。最好的办法就是使用易于阅读和辨认的指令符号来代替机器码,我们常称这些符号为助记符,用助记符的形式表示的单片机指令就是汇编语言,为便于记忆和阅读,助记符号通常都使用易于理解的英文单词和拼音字母来表示。

      每种单片机都有自己独特的指令系统,那么指令系统是开发和生产厂商定义的,如要使用其单片机,用户就必须理解和遵循这些指令标准,要掌握某种(类)单片机,指令系统的学习是必须的。

      MCS-51共有111条指令,可分为5类:

      [1].数据传送类指令(共29条)
      [2].算数运算类指令(共24条)
      [3].逻辑运算及移位类指令(共24条)
      [4].控制转移类指令(共17条)
      [5].布尔变量操作类指令(共17条)

      一些特殊符号的意义

      在介绍指令系统前,我们先了解一些特殊符号的意义,这对今后程序的编写都是相当有用的。

      Rn——当前选中的寄存器区的8个工作寄存器R0—R7n=0-7)。
      Ri——当前选中的寄存器区中可作为地址寄存器的两个寄存器R0R1i=0,1
      direct—内部数据存储单元的8位地址。包含0—127(255)内部存储单元地址和特殊功能寄存地址。
      #data—指令中的8位常数。
      #data16—指令中的16位常数。
      addr16—用于LCALLLJMP指令中的16目的地地址,目的地址的空间为64kB程序存储器地址。
      #addr11—用于ACALLAJMP指令中的11目的地地址,目的地址必须放在与下条指令第一个字节同一个2kB程序存储器空间之中。
      rel—8位带符号的偏移字节,用于所有的条件转移和SJMP等指令中,偏移字节对于下条指令的第一个字节开始的-128——+127范围内。
      @—间接寄存器寻址或基址寄存器的前缀。
      /—为操作的前缀,声明对该位操作书取反。
      DPTR—数据指针。
      bit—内部RAM和特殊功能寄存器的直接寻址位。
      A—累加器。
      B—累加器B。用于乘法和除法指令中。
      C—进位标志位。
      (x)—某地址单元中的内容。
      ((x))—X寻址单元中的内容。

      MCS-51的寻址方式

      寻址的地址即为操作数所在单元的地址,绝大部分指令执行时都需要用到操作数,那么到哪里去取得操作数呢?最易想到的就是告诉CPU操作数所在的地址单元,从那里可取得响应的操作数,这便是寻址之意。MCS-51的寻址方式很多,使用起来也相当方便,功能也很强大,灵活性强。这便是MCS-51指令系统好用的原因之一。下面我们分别讨论几种寻址方式的原理。

      [1].直接寻址
      指令中操作数直接以单元地址形式出现,例如:

      MOV A,68H

      这条指令的意义是把内部RAM中的68H单元中的数据内容传送到累加器A中。值得注意的是直接寻址方式只能使用8位二进制地址,因此这种寻址方式仅限于内部RAM进行寻址。低128位单元在指令中直接以单元地址的形式给出。对于特殊功能寄存器可以使用其直接地址进行访问,还可以以它们的符号形式给出,只是特殊功能寄存器只能用直接寻址方式访问,而无其它方法。

      [2].寄存器寻址
      寄存器寻址对选定的8个工作寄存器R0-R7进行操作,也就是操作数在寄存器中,因此指定了寄存器就得到了操作数,寄存器寻址的指令中以寄存器的符号来表示寄存器,例如:

      MOV A,R1

      这条指令的意义是把所用的工作寄存器组中的R3的内容送到累加器A中。
    值得一提的是工作状态寄存器的选择是通过程序状态字寄存器来控制的,在这条指令前,应通过PSW设定当前工作寄存器组。

      [3].寄存器间接寻址
      寄存器寻址方式,寄存器中存放的是操作数,而寄存器间接寻址方式,寄存器中存放的则为操作数的地址,也即操作数是通过寄存器指向的地址单元得到的,这便是寄存器间接寻址名称的由来。
    例如指令:

      MOV A,@R0

      这条指令的意义是R0寄存器指向地址单元中的内容送到累加器A中。假如R0=#56H,那么是将56H单元中的数据送到累加器A中。
    寄存器间接寻址方式可用于访问内部RAM或外部数据存储器。访问内部RAM或外部数据存储器的低256字节时,可通过R0R1作为间接寄存器。然而有必要指出,内部RAM的高128字节地址与专用积存器的地址是重叠的,所以这种寻址方式不能用于访问特殊功能寄存器。

      外部数据存储器的空间为64kB,这时可采用DPTR作为间址寄存器进行访问,指令如下:

      MOVX A,@DPTR

      这条指令的意义是与上述类似,不再赘述。

      [4].立即寻址
      立即寻址就是把操作数直接在指令中给出,即操作数包含在指令中,指令操作码的后面紧跟着操作数,一般把指令中的操作数称为立即数,因此而得名。为了与直接寻址方式相区别,在立即数前加上“#”符号,例如:

      MOVX A,#0EH

      这条指令的意义是将0EH这个操作数送到累加器A中。

      [5].变址寻址
      变址寻址是以DPTRPC作为基址寄存器,以累加器A作为变址寄存器,将两寄存器的内容相加形成16位地址形成操作数的实际地址。例如:

      MOV A,@A+DPTR
      MOVX A,@A+PC
      JMP @A+DPTR

      在这三条指令中,A作为偏移量寄存器,DPTRPC作为变址寄存器,A作为无符号数与DPTRPC的内容相加,得到访问的实际地址。其中前两条是程序存储器读指令,后一条是无条件转移指令。

      [6].位寻址
      在MCS-51单片机中,RAM中的20H—2FH字节单元对应的位地址为00H—7FH,特殊功能寄存器中的某些位也可进行为寻址,这些单元既可以采用字节方式访问它们,也可采用位寻址的方式访问它们。

      [7].相对寻址
      相对寻址方式是为了程序的相对转移而设计的,其夜里是以PC的内容为基址,加上给出的偏移量作为转移地址,从而实现程序的转移。转移的目的地址可参见如下表达式:

      目的地址=转移指令地址+转移指令字接数+偏移量

      值得注意的是,偏移量是有正负号之分的,偏移量的取值范围是当前PC值的-128—+127之间。

      MCS-51数据传送指令

      数据传送指令共有29条,数据传送指令一般的操作是把源操作数传送到目的操作数,指令执行完成后,源操作数不变,目的操作数等于源操作数。如果要求在进行数据传送时,目的操作数不丢失,则不能用直接传送指令,而采用交换型的数据传送指令,数据传送指令不影响标志C,ACOV,但可能会对奇偶标志P有影响。

      [1]. 以累加器A为目的操作数类指令(4条)
      这4条指令的作用是把源操作数指向的内容送到累加器A。有直接、立即数、寄存器和寄存器间接寻址方式:

      MOV A,data ;dataA)直接单元地址中的内容送到累加器A
      MOV A,#data ;#data→A)立即数送到累加器A
      MOV A,Rn ;RnA Rn中的内容送到累加器A
      MOV A,@Ri ;((Ri))A Ri内容指向的地址单元中的内容送到累加器A

      [2]. 以寄存器Rn为目的操作数的指令(3条)
    3条指令的功能是把源操作数指定的内容送到所选定的工作寄存器Rn中。有直接、立即和寄存器寻址方式:

      MOV Rn,data ;dataRn)直接寻址单元中的内容送到寄存器Rn
      MOV Rn,#data ;#data→Rn)立即数直接送到寄存器Rn
      MOV Rn,A ;ARn)累加器A中的内容送到寄存器Rn

      [3]. 以直接地址为目的操作数的指令(5条)
      这组指令的功能是把源操作数指定的内容送到由直接地址data所选定的片内RAM中。有直接、立即、寄存器和寄存器间接4种寻址方式:

      MOV data,data ;datadata)直接地址单元中的内容送到直接地址单元
      MOV data,#data ;#data→data)立即数送到直接地址单元
      MOV data,A ;Adata)累加器A中的内容送到直接地址单元
      MOV data,Rn ;Rndata)寄存器Rn中的内容送到直接地址单元
      MOV data,@Ri ;((Ri))data)寄存器Ri中的内容指定的地址单元中数据送到直接地址单元

      [4]. 以间接地址为目的操作数的指令(3条)
      这组指令的功能是把源操作数指定的内容送到以Ri中的内容为地址的片内RAM中。有直接、立即和寄存器3种寻址方式:

      MOV @Ri,data ;data((Ri))直接地址单元中的内容送到以Ri中的内容为地址的RAM单元
      MOV @Ri,#data ;#data→((Ri))立即数送到以Ri中的内容为地址的RAM单元
      MOV @Ri,A ;A((Ri))累加器A中的内容送到以Ri中的内容为地址的RAM单元

      [5]. 查表指令(2条)
      这组指令的功能是对存放于程序存储器中的数据表格进行查找传送,使用变址寻址方式:

      MOVC A,@A+DPTR ;((A))+DPTRA)表格地址单元中的内容送到累加器A
      MOVC A,@A+PC ;((PC))+1→A),((A))+PCA)表格地址单元中的内容送到累加器A

      [6]. 累加器A与片外数据存储器RAM传送指令(4条)
      这4条指令的作用是累加器A与片外RAM间的数据传送。使用寄存器寻址方式:

      MOVX @DPTR,A ;A((DPTR))累加器中的内容送到数据指针指向片外RAM地址中
      MOVX A, @DPTR ;((DPTR))A)数据指针指向片外RAM地址中的内容送到累加器A
      MOVX A, @Ri ;((Ri))A)寄存器Ri指向片外RAM地址中的内容送到累加器A
      MOVX @Ri,A ;A((Ri))累加器中的内容送到寄存器Ri指向片外RAM地址中

      [7]. 堆栈操作类指令(2条)
      这4类指令的作用是把直接寻址单元的内容传送到堆栈指针SP所指的单元中,以及把SP所指单元的内容送到直接寻址单元中。这类指令只有两条,下述的第一条常称为入栈操作指令,第二条称为出栈操作指令。需要指出的是,单片机开机复位后,(SP)默认为07H,但一般都需要重新赋值,设置新的SP首址。入栈的第一个数据必须存放于SP+1所指存储单元,故实际的堆栈底为SP+1所指的存储单元。

      PUSH data ;SP+1→SP),(dataSP)堆栈指针首先加1,直接寻址单元中的数据送到堆栈指针SP所指的单元中
      POP data ;SPdata)(SP-1→SP),堆栈指针SP所指的单元数据送到直接寻址单元中,堆栈指针SP再进行减1操作
      [8]. 交换指令(5条)
      这5条指令的功能是把累加器A中的内容与源操作数所指的数据相互交换。

      XCH A,Rn ;A←→Rn)累加器与工作寄存器Rn中的内容互换
      XCH A,@Ri ;A←→((Ri))累加器与工作寄存器Ri所指的存储单元中的内容互换
      XCH A,data ;A←→data)累加器与直接地址单元中的内容互换
      XCHD A,@Ri ;A3-0←→((Ri3-0)累加器与工作寄存器Ri所指的存储单元中的内容低半字节互换
      SWAP A ;A3-0←→A7-4)累加器中的内容高低半字节互换

      [9]. 16位数据传送指令(1条)
      这条指令的功能是把16位常数送入数据指针寄存器。

      MOV DPTR,#data16 ;#dataH→DPH),#dataL→DPL16位常数的高8位送到DPH,低8位送到DPL

      MCS-51算术运算指令

      算术运算指令共有24条,算术运算主要是执行加、减、乘、除法四则运算。另外MCS-51指令系统中有相当一部分是进行加、减1操作,BCD码的运算和调整,我们都归类为运算指令。虽然MCS-51单片机的算术逻辑单元ALU仅能对8位无符号整数进行运算,但利用进位标志C,则可进行多字节无符号整数的运算。同时利用溢出标志,还可以对带符号数进行补码运算。需要指出的是,除加、减1指令外,这类指令大多数都会对PSW(程序状态字)有影响。这在使用中应特别注意。

      [1]. 加法指令(4条)
      这4条指令的作用是把立即数,直接地址、工作寄存器及间接地址内容与累加器A的内容相加,运算结果存在A中。

      ADD A,#data ;A+#data→A)累加器A中的内容与立即数#data相加,结果存在A
      ADD A,data ;A+dataA)累加器A中的内容与直接地址单元中的内容相加,结果存在A
      ADD A,Rn ;A+RnA)累加器A中的内容与工作寄存器Rn中的内容相加,结果存在A
      ADD A,@Ri ;A+((Ri))A)累加器A中的内容与工作寄存器Ri所指向地址单元中的内容相加,结果存在A

      [2]. 带进位加法指令(4条)
      这4条指令除与[1]功能相同外,在进行加法运算时还需考虑进位问题。

      ADDC A,data ;A+data+CA)累加器A中的内容与直接地址单元的内容连同进位位相加,结果存在A
      ADDC A,#data ;A+#data +CA)累加器A中的内容与立即数连同进位位相加,结果存在A
      ADDC A,Rn ;A+Rn+CA)累加器A中的内容与工作寄存器Rn中的内容、连同进位位相加,结果存在A
      ADDC A,@Ri ;A+((Ri))+CA)累加器A中的内容与工作寄存器Ri指向地址单元中的内容、连同进位位相加,结果存在A

      [3]. 带借位减法指令(4条)
      这组指令包含立即数、直接地址、间接地址及工作寄存器与累加器A连同借位位C内容相减,结果送回累加器A中。
      
      这里我们对借位位C的状态作出说明,在进行减法运算中,CY=1表示有借位,CY=0则无借位。OV=1声明带符号数相减时,从一个正数减去一个负数结果为负数,或者从一个负数中减去一个正数结果为正数的错误情况。在进行减法运算前,如果不知道借位标志位C的状态,则应先对CY进行清零操作。

      SUBB A,data ;A-data - CA)累加器A中的内容与直接地址单元中的内容、连同借位位相减,结果存在A
      SUBB A,#data ;A-#data -CA)累加器A中的内容与立即数、连同借位位相减,结果存在A
      SUBB A,Rn ;A-Rn -CA)累加器A中的内容与工作寄存器中的内容、连同借位位相减,结果存在A
      SUBB A,@Ri ;A-((Ri)) -CA)累加器A中的内容与工作寄存器Ri指向的地址单元中的内容、连同借位位相减,结果存在A

      [4]. 乘法指令(1条)
      这个指令的作用是把累加器A和寄存器B中的8位无符号数相乘,所得到的是16位乘积,这个结果低8位存在累加器A,而高8位存在寄存器B中。如果OV=1,说明乘积大于FFH,否则OV=0,但进位标志位CY总是等于0

      MUL AB ;A×BA)和(B)累加器A中的内容与寄存器B中的内容相乘,结果存在AB

      [5]. 除法指令(1条)
      这个指令的作用是把累加器A8位无符号整数除以寄存器B中的8位无符号整数,所得到的商存在累加器A,而余数存在寄存器B中。除法运算总是使OV和进位标志位CY等于0。如果OV=1,表明寄存器B中的内容为00H,那么执行结果为不确定值,表示除法有溢出。

      DIV AB ;A÷BA)和(B)累加器A中的内容除以寄存器B中的内容,所得到的商存在累加器A,而余数存在寄存器B中。

      [6]. 1指令(5条)
      这5条指令的的功能均为原寄存器的内容加1,结果送回原寄存器。上述提到,加1指令不会对任何标志有影响,如果原寄存器的内容为FFH,执行加1后,结果就会是00H。这组指令共有直接、寄存器、寄存器减间址等寻址方式:

      INC A ;A+1→A)累加器A中的内容加1,结果存在A
      INC data ;data+1→data)直接地址单元中的内容加1,结果送回原地址单元中
      INC @Ri ;((Ri))+1→((Ri))寄存器的内容指向的地址单元中的内容加1,结果送回原地址单元中
      INC Rn ;Rn+1→Rn)寄存器Rn的内容加1,结果送回原地址单元中
      INC DPTR ;DPTR+1→DPTR)数据指针的内容加1,结果送回数据指针中

      在INC data这条指令中,如果直接地址是I/O,其功能是先读入I/O锁存器的内容,然后在CPU进行加1操作,再输出到I/O上,这就是修改操作。

      [7]. 1指令(4条)
      这组指令的作用是把所指的寄存器内容减1,结果送回原寄存器,若原寄存器的内容为00H,减1后即为FFH,运算结果不影响任何标志位,这组指令共有直接、寄存器、寄存器间址等寻址方式,当直接地址是I/O口锁存器时,修改操作与加1指令类似。

      DEC A ;A-1→A)累加器A中的内容减1,结果送回累加器A
      DEC data ;data-1→data)直接地址单元中的内容减1,结果送回直接地址单元中
      DEC @Ri ;((Ri))-1→((Ri))寄存器Ri指向的地址单元中的内容减1,结果送回原地址单元中

      DEC Rn ;Rn-1→Rn)寄存器Rn中的内容减1,结果送回寄存器Rn

      [8]. 十进制调整指令(1条)
      在进行BCD码运算时,这条指令总是跟在ADDADDC指令之后,其功能是将执行加法运算后存于累加器A中的结果进行调整和修正。

      DA A

      MCS-51逻辑运算及移位指令

      逻辑运算和移位指令共有25条,有与、或、异或、求反、左右移位、清0等逻辑操作,有直接、寄存器和寄存器间址等寻址方式。这类指令一般不影响程序状态字(PSW)标志。

      [1]. 循环移位指令(4条)
      这4条指令的作用是将累加器中的内容循环左或右移一位,后两条指令是连同进位位CY一起移位。

      RL A ;累加器A中的内容左移一位
      RR A ;累加器A中的内容右移一位
      RLC A ;累加器A中的内容连同进位位CY左移一位
      RRC A ;累加器A中的内容连同进位位CY右移一位

      [2]. 累加器半字节交换指令(1条)
      这条指令是将累加器中的内容高低半字节互换,这在上一节中内容已有介绍。

      SWAP A ; 累加器中的内容高低半字节互换

      [3]. 求反指令(1条)
      这条指令将累加器中的内容按位取反。

      CPL A ; 累加器中的内容按位取反

      [4]. 清零指令(1条)
      这条指令将累加器中的内容清0

      CLR A ; 0→A),累加器中的内容清0

      [5]. 逻辑与操作指令(6条)
      这组指令的作用是将两个单元中的内容执行逻辑与操作。如果直接地址是I/O地址,则为修改操作。

      ANL A,data ;累加器A中的内容和直接地址单元中的内容执行与逻辑操作。结果存在寄存器A中。
      ANL data,#data ;直接地址单元中的内容和立即数执行与逻辑操作。结果存在直接地址单元中。
      ANL A,#data ;累加器A的内容和立即数执行与逻辑操作。结果存在累加器A中。
      ANL A,Rn ;累加器A的内容和寄存器Rn中的内容执行与逻辑操作。结果存在累加器A中。
      ANL data,A ;直接地址单元中的内容和累加器A的内容执行与逻辑操作。结果存在直接地址单元中。
      ANL A,@Ri ;累加器A的内容和工作寄存器Ri指向的地址单元中的内容执行与逻辑操作。结果存在累加器A中。

      [6]. 逻辑或操作指令(6条)
      这组指令的作用是将两个单元中的内容执行逻辑或操作。如果直接地址是I/O地址,则为修改操作。

      ORL A,data ;累加器A中的内容和直接地址单元中的内容执行逻辑或操作。结果存在寄存器A中。
      ORL data,#data ;直接地址单元中的内容和立即数执行逻辑或操作。结果存在直接地址单元中。
      ORL A,#data ;累加器A的内容和立即数执行逻辑或操作。结果存在累加器A中。
      ORL A,Rn ;累加器A的内容和寄存器Rn中的内容执行逻辑或操作。结果存在累加器A中。
      ORL data,A ;直接地址单元中的内容和累加器A的内容执行逻辑或操作。结果存在直接地址单元中。
      ORL A,@Ri ;累加器A的内容和工作寄存器Ri指向的地址单元中的内容执行逻辑或操作。结果存在累加器A中。

      [7]. 逻辑异或操作指令(6条)
      这组指令的作用是将两个单元中的内容执行逻辑异或操作。如果直接地址是I/O地址,则为修改操作。

      XRL A,data ;累加器A中的内容和直接地址单元中的内容执行逻辑异或操作。结果存在寄存器A中。
      XRL data,#data ;直接地址单元中的内容和立即数执行逻辑异或操作。结果存在直接地址单元中。
      XRL A,#data ;累加器A的内容和立即数执行逻辑异或操作。结果存在累加器A中。
      XRL A,Rn ;累加器A的内容和寄存器Rn中的内容执行逻辑异或操作。结果存在累加器A中。
      XRL data,A ;直接地址单元中的内容和累加器A的内容执行逻辑异或操作。结果存在直接地址单元中。
      XRL A,@Ri ;累加器A的内容和工作寄存器Ri指向的地址单元中的内容执行逻辑异或操作。结果存在累加器A中。

      MCS-51控制转移指令
     
      控制转移指令用于控制程序的流向,所控制的范围即为程序存储器区间,MCS-51系列单片机的控制转移指令相对丰富,有可对64kB程序空间地址单元进行访问的长调用、长转移指令,也有可对2kB字节进行访问的绝对调用和绝对转移指令,还有在一页范围内短相对转移及其它无条件转移指令,这些指令的执行一般都不会对标志位有影响。

      [1]. 无条件转移指令(4条)
      这组指令执行完后,程序就会无条件转移到指令所指向的地址上去。长转移指令访问的程序存储器空间为16地址64kB,绝对转移指令访问的程序存储器空间为11位地址2kB空间。

      LJMP addr16 ;addr16→PC),给程序计数器赋予新值(16位地址)

      AJMP addr11 ;PC+2→PC),addr11→PC10-0)程序计数器赋予新值(11位地址),(PC15-11)不改变

      SJMP rel ;PC+ 2 + rel→PC)当前程序计数器先加上2再加上偏移量给程序计数器赋予新值

      JMP @A+DPTR ;A+ DPTRPC),累加器所指向地址单元的值加上数据指针的值给程序计数器赋予新值

      [2]. 条件转移指令(8条)
      程序可利用这组丰富的指令根据当前的条件进行判断,看是否满足某种特定的条件,从而控制程序的转向。

      JZ rel ; A=0,PC+ 2 + rel→PC,累加器中的内容为0,则转移到偏移量所指向的地址,否则程序往下执行

      JNZ rel ; A≠0,PC+ 2 + rel→PC,累加器中的内容不为0,则转移到偏移量所指向的地址,否则程序往下执行

      CJNE A, data, rel ; A≠data,PC+ 3 + rel→PC,累加器中的内容不等于直接地址单元的内容,则转移到偏移量所指向的地址,否则程序往下执行

      CJNE A, #data, rel ; A≠#data,PC+ 3 + rel→PC,累加器中的内容不等于立即数,则转移到偏移量所指向的地址,否则程序往下执行

      CJNE Rn, #data, rel ; A≠#data,PC+ 3 + rel→PC,工作寄存器Rn中的内容不等于立即数,则转移到偏移量所指向的地址,否则程序往下执行

      CJNE @Ri, #data, rel ; A≠#data,PC+ 3 + rel→PC,工作寄存器Ri指向地址单元中的内容不等于立即数,则转移到偏移量所指向的地址,否则程序往下执行

      DJNZ Rn, rel ; Rn-1→Rn),Rn)≠0,PC+ 2 + rel→PC)工作寄存器Rn1不等于0,则转移到偏移量所指向的地址,否则程序往下执行

      DJNZ data, rel ; Rn-1→Rn),Rn)≠0,PC+ 2 + rel→PC)直接地址单元中的内容减1不等于0,则转移到偏移量所指向的地址,否则程序往下执行

      [3]. 子程序调用指令(1条)
      子程序是为了便于程序编写,减少那些需反复执行的程序占用多余的地址空间而引入的程序分支,从而有了主程序和子程序的概念,需要反复执行的一些程序,我们在编程时一般都把它们编写成子程序,当需要用它们时,就用一个调用命令使程序按调用的地址去执行,这就需要子程序的调用指令和返回指令。

      LCALL addr16 ; 长调用指令,可在64kB空间调用子程序。此时(PC+ 3→PC),(SP+ 1→SP),(PC7-0SP),(SP+ 1→SP),(PC15-8SP),addr16→PC),即分别从堆栈中弹出调用子程序时压入的返回地址

      ACALL addr11 ; 绝对调用指令,可在2kB空间调用子程序,此时(PC+ 2→PC),(SP+ 1→SP),(PC7-0SP),(SP+ 1→SP),(PC15-8SP),addr11→PC10-0

      RET ; 子程序返回指令。此时(SPPC15-8),(SP- 1→SP),(SPPC7-0),(SP- 1→SP

      RETI ; 中断返回指令,除具有RET功能外,还具有恢复中断逻辑的功能,需注意的是,RETI指令不能用RET代替

      [4]. 空操作指令(1条)
    这条指令将累加器中的内容清0

      NOP ; 这条指令除了使PC1,消耗一个机器周期外,没有执行任何操作。可用于短时间的延时

      MCS-51布尔变量操作指令

      布尔处理功能是MCS-51系列单片机的一个重要特征,这是出于实际应用需要而设置的。布尔变量也即开关变量,它是以位(bit)为单位进行操作的。

      在物理结构上,MCS-51单片机有一个布尔处理机,它以进位标志做为累加位,以内部RAM可寻址的128个为存储位。

      既然有布尔处理机功能,所以也就有相应的布尔操作指令集,下面我们分别谈论。

      [1]. 位传送指令(2条)
      位传送指令就是可寻址位与累加位CY之间的传送,指令有两条。

      MOV C,bit ;bit→CY,某位数据送CY

      MOV bit,C ;CY→bitCY数据送某位

      [2]. 位置位复位指令(4条)
    这些指令对CY及可寻址位进行置位或复位操作,共有四条指令。

      CLR C ; 0→CY,CY

      CLR bit ; 0→bit,清某一位

      SETB C ; 1→CY,置位CY

      SETB bit ; 1→bit,置位某一位

      [3]. 位运算指令(6条)
      位运算都是逻辑运算,有与、或、非三种指令,共六条。

      ANL C,bit ;(CY)(bit)→CY

      ANL C,/bit ;(CY)()→CY

      ORL C,bit ;(CY)(bit)→CY

      ORL C,/bit ;(CY)()→CY

    CPL C ;()→CY

      CPL bit ;()→bir

      [4]. 位控制转移指令(5
      位控制转移指令是以位的状态作为实现程序转移的判断条件,介绍如下:

      JC rel ; (CY)=1转移,(PC+2+rel→PC,否则程序往下执行,(PC+2→PC
     
      JNC rel ; (CY)=0转移,(PC+2+rel→PC,否则程序往下执行,(PC+2→PC

      JB bit, rel ; 位状态为1转移。

      JNB bit, rel ; 位状态为0转移。

      JBC bit, rel ; 位状态为1转移,并使该位清“0”

      后三条指令都是三字节指令,如果条件满足,(PC+3+rel→PC,否则程序往下执行,(PC+3→PC
    展开全文
  • 以累加器为目的操作数的指令 MOV A,Rn MOV A,direct MOV A,@Ri MOV A,#data 这组指令功能是把源地址单元中的内容送入直接地址,源操作数不变。 第一条指令中,Rn代表的是R0-R7。 第二条指令中,direct...M
  • 51单片机汇编指令表

    2015-05-29 11:27:48
    助记符 指令说明 字节数 周期数 (数据传递类指令) MOV A,Rn 寄存器传送到累加器 1 1 MOV A,direct ...累加器传送到外部RAM
  • 单片机汇编指令集

    2010-02-23 14:16:00
    单片机使用的机器语言、汇编语言及高级语言,但不管使用是何种语言,最终还是要“翻译”成为机器码, 单片机才能执行之。现在有很多半导体厂商都推出了自己的单片机单片机种类繁多,品种数不胜数,值得注意的是...
  • 结果老师给了他一份汇编程序,由于自己之前做过汇编编程的工作,就胆(no)大(zuo)妄(no)为(dai)的说是给他翻译成C语言的。 当我仔细瞅了那份程序之后。额,好吧,我只能说我尽力而为吧! 东西只有一篇近2000行的汇编...
  • 运算类: 指令 操作数1 操作数2  ADD/ADDC——加法/带进位的加法  SUBB——带借位的减法 A Rn 直接地址 @Ri #立即数 MUL/DIV——乘法/除法 AB ...  INC...
  • 今天为了复习课本上面的程序,就实地检验了下这个程序,当年可是学过微机原理里的冒泡排序的,结果移植平台后又是如此麻烦,呵呵,网上贴吧,论坛,知道,文库上面拜托你们的程序能不能靠谱点!...
  • 51单片机汇编指令速查表指令格式 功能简述 字节数 周期一、数据传送类指令 MOV A, Rn 寄存器送累加器 1 1 MOV Rn,A 累加器送寄存器 1 1 MOV A ,@Ri 内部RAM单元送累加器 1 1 MOV @Ri ,A 累加器送内部RAM单元 1...
  • 数据传递类指令  以累加器为目的操作数的指令  MOV A,Rn  MOV A,direct  MOV A,@Ri  MOV A,#data ... 第一条指令中,Rn代表的是R0-R7。第二条指令中,direct就是指的直接地址,而第三条指令中,就是我们...
  • 1. 51单片机概述51单片机是对所有兼容Intel 8031指令系统的单片机的统称。目前教科书基本都是以早期的MCS-51为原型,讲解微机的原理及其接口技术的。早期的51单片机功能都较弱,需扩展rom,ram等才能组成一个较复杂...
  • 51单片机汇编指令集

    2013-05-12 19:49:28
    一、数据传送类指令(7种助记符) MOV(英文为Move):对内部数据寄存器RAM和特殊功能寄存器SFR的数据进行传送; MOVC(Move Code)读取程序存储器数据表格的数据传送; MOVX(Move External RAM) 对外部RAM的...
  • AT89C51汇编语言指令系统有42种助记符和111种指令,按指令长度可分单字节指令、双字节和三字节指令,按执行时间可分为单机器周期指令(64种)、双机器周期指令(45种)和四周期指令(只有乘、除法指令两种)。...
  • ;$$$$变量定义区(30H-)$$$$$ OUTBIT EQU P2 ; 位控制口 OUTSEG EQU P0 ; 段控制口 ROW_COLUMN EQU P1 ; 读键盘行线口 VARIABLE_DELAY1 EQU 30H ;延时变量 VARIABLE_DELAY2 EQU 31H ...存储第...
1 2 3 4 5 ... 11
收藏数 213
精华内容 85
关键字:

单片机汇编jnc