#STC89C51# #STC89C52# #AT89S51# #AT89C52#--8051内核单片机原理及汇编(五):指令系统(中)

成就更好的自己

 

 

目录

3.4.4  控制转移类指令

1.长转移指令

2.相对转移指令

3.绝对转移指令

4.间接跳转指令

5.条件转移指令

6.比较不相等转移指令

7.减1不为0转移指令

8.调用子程序指令

9.子程序的返回指令

10.中断返回指令

11.空操作指令

3.4.5  位操作类指令   

1.数据位传送指令

2.位变量修改指令

3.位变量逻辑与指令

4.位变量逻辑或指令

5.条件转移类指令

3.5   AT89S51指令汇总

3.6  某些指令的说明

3.7.1  编程语言概述

3.7.2  汇编语言语句和格式

3.7.3  伪指令

3.7.4  汇编语言源程序的汇编


 

 

3.4.4  控制转移类指令

1.长转移指令

                     LJMP     addr16

指令执行时,把转移的目的地址,即指令的第二和第三字节分别装入PC的高位和低位字节中,无条件地转向addr16指定的目的地址:64KB程序存储器地址空间的任何位置。

2.相对转移指令

                     SJMP     rel

无条件转移,rel为相对偏移量,是一单字节的带符号8位二进制补码数,因此程序转移是双向的。rel如为正,向地址增大的方向转移;rel如为负,向地址减小的方向转移。

执行时,在PC加2(本指令为2B)之后,把指令的有符号的偏移量rel加到PC上,并计算出目的地址。

编程时,只需写上目的地址标号, 相对偏移量由汇编程序自动计算。例如:

              LOOP: MOV       A,R6

              ……                          

                     SJMP    LOOP

                     ……

汇编时,跳到LOOP处的偏移量由汇编程序自动计算和填入。

3.绝对转移指令

              AJMP     addr11

指令双字节,格式如下:

指令提供11位地址A10~A0(即addr11),其中A10~A8则位于第1字节的高3位,A7~A0在第2字节。操作码只占第1字节的低5位。

指令构造转移目的地址:执行本指令,PC加2,然后把指令中的11位无符号整数地址addr11(A10~A0)送入PC.10~PC.0,PC.15~PC.11保持不变,形成新的16位转移目的地址。

需注意,目标地址必须与AJMP指令的下一条指令首地址的高5位地址码A15~A11相同,否则将混乱。所以,是2KB范围内的无条件跳转指令。

4.间接跳转指令

                     JMP   @A+DPTR

单字节转移指令,目的地址由A中8位无符号数与DPTR的16位无符号数内容之和来确定。以DPTR内容为基址,A的内容作为变址。给A赋予不同值,即可实现多分支转移。

5.条件转移指令

执行指令时,如条件满足,则转移;不满足,则顺序执行下一指令。转移目的地址在以下一条指令首地址为中心的256B范围内(-128~+127)。

              JZ    rel   ;如果累加器内容为0,则执行转移

              JNZ rel   ;如果累加器内容非0,则执行转移

6.比较不相等转移指令

              CJNE     A,direct,rel

              CJNE     A,#data,rel

              CJNE         Rn,#data,rel

              CJNE         @Ri,#data,rel

比较前两个操作数大小,如果值不相等则转移,并转向目的地址。

如果第一操作数(无符号整数)小于第二操作数(无符号整数),则进位标志位Cy置1,否则Cy清0。该指令的执行不影响任何一个操作数的内容。

7.减1不为0转移指令

把减1与条件转移两种功能合在一起。两条:

                     DJNZ     Rn,rel        ;n =0~7

                     DJNZ     direct,rel

用于控制程序循环。预先装入循环次数,以减1后是否为“0”作为转移条件,即实现按次数控制循环。

8.调用子程序指令

(1)长调用指令

                     LCALL      addr16

可调用64KB范围内程序存储器中的任何一个子程序。执行时,先把PC加3获得下一条指令的地址(断点地址),并压入堆栈(先低位字节,后高位字节),堆栈指针加2。

接着把指令的第二和第三字节(A15~A8,A7~A0)分别装入PC的高位和低位字节中,然后从PC指定的地址开始执行程序。执行后不影响任何标志位。

(2)绝对调用指令

                     ACALL     addr11

与AJMP指令类似,为兼容MCS–48的CALL指令而设,不影响标志位。格式如下:

2KB范围内的调用子程序的指令。子程序地址必须与ACALL指令下一条指令的16位首地址中的高5位地址相同,否则将混乱。

9.子程序的返回指令

                     RET

执行本指令时

       (SP)→PCH,然后(SP)-1→SP

       (SP)→PCL,然后(SP)-1→SP

功能: 从堆栈中退出PC的高8位和低8位字节,把栈指针减2,从PC值处开始继续执行程序。不影响任何标志位。

10.中断返回指令

                     RETI

与RET指令相似,不同处:该指令清除了中断响应时被置1的内部中断优先级寄存器的中断优先级状态,其他相同。

11.空操作指令

                     NOP

不进行任何操作,耗一个机器周期时间,执行(PC)+1→PC操作

3.4.5  位操作类指令   

内部有一个位处理机,对应位操作指令。

1.数据位传送指令

                     MOV     C,bit

                     MOV     bit,C

把源操作数指定的位变量送到目的操作数指定处。一个操作数必须为进位标志,另一个可以是任何直接寻址位。不影响其他寄存器或标志位。

例如:          MOV         C,06H        ;(20H).6→Cy

06H是位地址,20H是内部RAM字节地址。06H是内部RAM 20H字节位6的位地址。

                     MOV         P1.0,C ;Cy→P1.0

2.位变量修改指令

                     CLR C            ;Cy位清0

                     CLR   bit          ;bit位清0

                     CPL     C            ;Cy位求反

                     CPL     bit          ;bit位求反

                     SETB    C            ;Cy位置1

                     SETB    bit          ;bit位置1

这组指令将操作数指定的位清0、求反、置1,不影响其他标志位。例如:

              CLR C                   ;Cy位清0

              CLR   27H             ;0→(24H).7位

              CPL     08H             ; →(21H).0位

              SETB    P1.7                   ; P1.7位置1

3.位变量逻辑与指令

              ANL     C,bit                  ;bit∧Cy→Cy

              ANL     C,/bit                   ; ∧Cy→Cy

第2条指令先对直接寻址位求反,然后与进位标志位C进行“逻辑与”运算,结果送回到位累加器中。

4.位变量逻辑或指令

                     ORL       C,bit

                     ORL       C,/bit

第1条指令是直接寻址位与进位标志位Cy(位累加器)进行“逻辑或”运算,结果送回到进位标志位中。

第2条指令先对直接寻址位求反,然后与位累加器(进位标志位)进行“逻辑或”运算,结果送回到进位标志位中。

5.条件转移类指令

              JC       rel               ;如进位标志位Cy=1,则转移

              JNC     rel               ;如进位标志位Cy=0,则转移

              JB        bit,rel          ;如直接寻址位=1,则转移

              JNB      bit,rel          ;如直接寻址位=0,则转移

              JBC      bit,rel          ;如直接寻址位=1,转移,并把寻址位

                                    ;清0

3.5   AT89S51指令汇总

表3-2列出了按功能排列的全部的指令助记符及功能简要说明,以及指令长度、执行时间和指令代码(机器代码)。

由于指令条数多,读者不宜死记硬背,应在程序的编写中多加练习,在实践中不断掌握和巩固常用的指令。读者应熟练地查阅下表,正确地理解指令的功能及特性并正确地使用指令。

3.6  某些指令的说明

    111条指令介绍完毕。一些细节问题,还需要说明。

1. 关于并行I/O口的“读引脚”和“读锁存器”指令的区别

    例如,当P1口的P1.0引脚外接一个发光二极管LED的阳极,LED的阴极接地。

若想查看一下单片机刚才向P1.0脚输出的信息是0还是1,不能直接从P1.0脚读取,因为单片机刚才向P1.0输出的信息如果是1的话,则LED导通点亮,此时P1.0引脚就为0电平,如果直接读引脚,结果显然错误。

    正确的做法是读D锁存器的Q端状态,那里储存的才是前一时刻送给P1.0的真实值。就是说,凡遇“读取P1口前一状态以便修改后再送出”的情形,都应当“读锁存器”的Q端信息,而不是读取引脚的信息。

    当P1口外接输入设备时,要想P1口引脚上反映的是真实的输入信号,必须要设法先让该引脚内部的场效应管截止才行,否则当场效应管导通时,P1口引脚上将永远为低电平,无法正确反映外设的输入信号。让场效应管截止,就是用指令给P1口的相应位送一个“1”电平,这就是为什么读引脚之前,一定要先送出1的原因。

指令“MOV   C,P1.0”读的是P1.0脚,同样,指令“MOV  A,P1”也是读引脚指令,读引脚指令之前一定要有向P1.0写“1”的指令。

而指令“CPL  P1.0”则是“读锁存器”,也即“读—修改—写”指令,它会先读P1.0的锁存器的Q端状态,接着取反,然后再送到P1.0引脚上。而指令“ANL  P1,A” 也是“读锁存器”命令。类似的“读—修改—写”指令举例如下:

                     INC P1

                     XRL P3,A

                     ORL       P2,A

                     ANL       P1,A

                     CPL P3.0

2. 关于操作数的字节地址和位地址的区分问题

如何区别指令中出现的字节变量和位变量?

例如指令“MOV  C,40H”和指令“MOV  A,40H”两条指令中源操作数“40H”都是以直接地址形式给出的,“40H” 是字节地址还是位地址?对于助记符相同指令,观察操作数就可看出。

显然前条指令中的“40H”肯定是位地址,因为目的操作数C是位变量。

 后条指令的“40H” 是字节地址,因为目的操作数A是字节变量。

3. 关于累加器A与Acc的书写问题

     累加器可写成A或Acc,区别是什么?

     Acc汇编后的机器码必有一个字节的操作数是累加器的字节地址E0H,A汇编后则隐含在指令操作码中。

      例如: “INC  A”的机器码,查表3-2是04H。

     如写成“INC  Acc”后,则成了“INC  direct”的格式,再查表3-2,对应机器码为“05H  E0H”。在对累加器A直接寻址和累加器A的某一位寻址要用Acc,不能写成A。

例如,指令“POP  Acc”不能写成“POP  A”;

              指令“SETB  Acc.0”,不能写成“SETB  A.0”。

 

4.书写2位十六进制数据前要加“0”

经常遇到必须在某些数据或地址的前面多填一个“前导”0。否则汇编就通不过?这是汇编语言的严格性和规范性的体现。

由于部分十六进制数是用字母来表示的,而程序内的标号也常用字母表示,为了将标号和数据区分开,几乎所有的汇编语言都规定,凡是以字母开头(对十六进制数而言,就是A~F开头)的数字量,应当在前面添加一个数字0。

至于地址量,它也是数据量的一种,前面也应该添加“0”。

例如:

              MOV     A,#0F0H        ;“F0”以字母开头的数据量

              MOV     A,0F0H     ;“F0”以字母开头的地址量

如不加“前导”0,就会把字母开头的数据量当作标号来处理,从而出错以及不能通过汇编。

3.7   8051汇编语言程序设计概述

    程序是指令的有序集合。

    单片机运行就是执行指令序列的过程。

    编写这一指令序列的过程称为程序设计。

 

3.7.1  编程语言概述

  常用的编程语言是汇编语言和高级语言。

1.汇编语言

  用英文字符来代替机器语言,这些英文字符被称为助记符

    汇编语言:用助记符表示的指令。

汇编语言源程序:用汇编语言编写的程序。

   “汇编”:汇编语言源程序需转换(翻译)成为二进制代码表示的机器语言程序,才能识别和执行。

   完成“翻译”的程序称为汇编程序。经汇编程序“汇编”得到的以“0”、“1”代码形式表示的机器语言程序称为目标程序。

      优点:用汇编语言编写程序效率高,占用存储空间小,运行速度快,能编写出最优化的程序,

      缺点:可读性差,离不开具体的硬件,是面向“硬件”的语言通用性差。

2.高级语言

不受具体“硬件”的限制,优点:通用性强,直观、易懂、易学,可读性好。

目前多数的51单片机用户使用C语言(C51)来进行程序设计,已公认为高级语言中高效简洁而又贴近51单片机硬件的编程语言。

将C语言向单片机上移植,始于20世纪80年代的中后期。

经过十几年努力,C51已成为单片机的实用高级编程语言。

尽管目前已有不少设计人员使用C51来进行程序开发,但在对程序的空间和时间要求较高的场合,汇编语言仍必不可少。

在这种场合下,可使用C语言和汇编语言混合编程。在很多需要直接控制硬件且对实时性要求较高的场合,则更是非用汇编语言不可。

掌握汇编语言并能进行程序设计,是学习和掌握单片机程序设计的基本功之一。

3.7.2  汇编语言语句和格式

两种基本语句:指令语句和伪指令语句。

(1)指令语句

已在第3章介绍。每一指令语句在汇编时都产生一个指令代码(机器代码),执行该指令代码对应着机器的一种操作。

(2)伪指令语句

是控制汇编(翻译)过程的一些控制命令。在汇编时没有机器代码与之对应。

汇编语言语句是符合典型的汇编语言的四分段格式:

标号字段和操作码字段之间要有冒号“:”分隔;

操作码字段和操作数字段间的分界符是空格;

双操作数之间用逗号相隔;

操作数字段和注释字段之间的分界符用分号“;”。

任何语句都必须有操作码字段,其余各段为任选项。

【例4-1】下面是一段程序的四分段书写格式。

标号字段  操作码字段   操作数字段   注释字段

START:MOV    A,#00H             ;0→A

       MOV     R1,#10                       ;10→R1

              MOV     R2,#00000011B         ;03H→R2

LOOP:  ADD  A,R2                    ;(A)+(R2)→A

              DJNZ     R1,LOOP  ;R1减1不为零,则跳LOOP处

              NOP

HERE:  SJMP  HERE

上述4个字段应该遵守的基本语法规则如下。

1.标号字段

  语句所在地址的标志符号,才能被访问。如标号“START”和“LOOP”等。有关标号规定如下:

(1)标号后必须跟冒号“:”。

(2)标号由1~8个ASCII码字符组成,第一个字符必须是字母。

(3)同一标号在一个程序中只能定义一次,不能重复定义。

(4)不能使用汇编语言已经定义的符号作为标号,如指令助记符、伪指令以及寄存器的符号名称等。

(5)标号的有无,取决于本程序中的其他语句是否访问该条语句。如无其他语句访问,则该语句前不需标号。

2.操作码字段

操作码字段规定了语句执行的操作,操作码是汇编语言指令中唯一不能空缺的部分。

3.操作数字段

指令的操作数或操作数地址。

在本字段中,操作数的个数因指令的不同而不同。通常有单操作数、双操作数和无操作数三种情况。

如果是多操作数,则操作数之间要以逗号隔开。

操作数表示时,几种情况需注意:

(1)十六进制、二进制和十进制形式的操作数表示

  多数情况,操作数或操作数地址是采用十六进制形式来表示的。则需加后缀“H”。

  在某些特殊场合用二进制表示,需加后缀“B”

  若操作数采用十进制形式,则需加后缀“D”,也可省略。

  若十六进制操作数以字符A~F开头,需在它前面加一个 “0”,以便汇编时把它和字符A~F区别开。

(2)工作寄存器和特殊功能寄存器的表示

   当操作数为工作寄存器或特殊功能寄存器时,允许用工作寄存器和特殊功能寄存器的代号表示。

   例如,工作寄存器用R7~R0,累加器用A(或Acc)表示。另外,工作寄存器和特殊功能寄存器也可用其地址来表示,如累加器A可用其地址E0H来表示。

4.注释字段

  用于解释指令或程序的含义,对可读性非常有用。

  使用时须以分号开头,长度不限,一行写不下可换行书写,但注意也要以分号开头。

  汇编时,遇到“;” 就停止“翻译”。因此,注释字段不会产生机器代码。

3.7.3  伪指令

  在汇编语言源程序中应有向汇编程序发出的指示信息,告诉它如何完成汇编工作,这是通过伪指令来实现。

  伪指令不属于指令系统中的汇编语言指令,它是程序员发给汇编程序的命令,也称为汇编程序控制命令。

  只有在汇编前的源程序中才有伪指令。 “伪”体现在汇编后,伪指令没有相应的机器代码产生。

  伪指令具有控制汇编程序的输入/输出、定义数据和符号、条件汇编、分配存储空间等功能。

不同汇编语言的伪指令有所不同,但基本内容相同。

介绍常用的伪指令。

1.ORG(ORiGin)汇编起始地址命令

    源程序的开始,用一条ORG伪指令规定程序的起始地址。如果不用ORG,则汇编得到的目标程序将从0000H地址开始。例如:

              ORG      2000H

START:      MOV     A,#00H

                     ……

即规定标号START代表地址为2000H开始。

     在一源程序中,可多次用ORG指令,规定不同的程序段的起始地址。但是,地址必须由小到大排列,且不能交叉、

重叠。例如:

ORG      2000H

……

ORG      2500H

……

ORG      3000H

……

这种顺序是正确的。若按下面顺序的排列则是错误的,因为地址出现了交叉。

ORG      2500H

……

ORG      2000H

……

ORG      3000H

……

2.  END(END of Assembly)汇编终止命令

    源程序结束标志,终止源程序的汇编工作。整个源程序中只能有一条END命令,且位于程序的最后。如果END出现在程序中间,其后的源程序,将不进行汇编处理。

3.EQU(EQUate)标号赋值命令

    用于给标号赋值。赋值后,标号值在整个程序有效。

例如:TEST:    EQU  2000H     

表示TEST=2000H,汇编时,凡是遇到TEST时,均以2000H来代替。

4.DB(Define Byte)定义数据字节命令

      用于从指定的地址开始,在程序存储器连续单元中定义字节数据。例如:

              ORG      2000H

DB  30H,40H,24,"C","B"

汇编后

(2000H)=30H

(2001H)=40H

(2002H)=18H(十进制数24)

(2003H)=43H(字符“C”的ASCII码)

(2004H)=42H(字符“B”的ASCII码)

显然,DB功能是从指定单元开始定义(存储)若干字节,十进制数自然转换成十六进制数,字母按ASCII码存储。

5.DW(Define Word)定义数据字命令

该命令用于从指定的地址开始,在程序存储器的连续单元中定义16位的数据字。例如:

ORG      2000H

DW 1246H,7BH,10

汇编后

(2000H)=12H            ;第1个字

(2001H)=46H

(2002H)=00H            ;第2个字

(2003H)=7BH

(2004H)=00H            ;第3个字

(2005H)=0AH

6.DS(Define Storage)定义存储区命令

     从指定地址开始,保留指定数目的字节单元作为存储区,供程序运行使用。例如:

              TABEL:DS  10

     表示从TABEL代表的地址开始,保留10个连续的地址单元。又例如:

              ORG      2000H

              DS  10 H

     表示从2000H地址开始,保留16个连续地址单元。

   注意:DB、DW和DS命令只能对程序存储器有效,不能对数据存储器使用。

7.BIT 位定义命令

   用于给字符名称赋以位地址,位地址可以是绝对位地址,也可是符号地址。例如:

       QA  BIT  P1.6

功能是把P1.6的位地址赋给变量QA。

3.7.4  汇编语言源程序的汇编

   “汇编”----可分为手工汇编和机器汇编两类。

1.手工汇编

    通过查指令的机器代码表(表3-2),逐个把助记符指令“翻译”成机器代码,再进行调试和运行。

手工汇编遇到相对转移偏移量的计算时,较麻烦,易出错,只有小程序或受条件限制时才使用。实际中,多采用“汇编程序”来自动完成汇编。

2. 机器汇编

   用微型计算机上的软件(汇编程序)来代替手工汇编。 在微机上用编辑软件进行源程序编辑,然后生成一个ASCII码文件,扩展名为 “.ASM”。在微机上运行汇编程序,译成机器码。

   机器码通过微机的串口(或并口)传送到用户样机(或在线仿真器),进行程序的调试和运行。

   有时,在分析某些产品的程序的机器代码时,需将机器代码翻译成汇编语言源程序,称为“反汇编”。

【例3-13】 表3-3是一段源程序的汇编结果,可手工汇编,来验证下面的汇编结果是否正确。机器码从1000H单元开始存放。

 

  • 4
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值