300 likes | 544 Views
第四章 汇编语言程序设计. 第一节 汇编语言程序的格式和伪指令 第二节 汇编语言源程序汇编 第三节 汇编语言源程序设计举例. 计算机程序设计语言通常分为机器语言、汇编语言和高级语言等三类。 机器语言能被计算机直接识别和执行; 汇编语言是一种面向机器的语言 ; 高级语言是一种面向过程和问题并能独立于机器的通用程序设计语言 ;. 第一节 汇编语言源程序的格式和伪指令. 一、汇编语言源程序的格式 [ 标号: ] 操作码 [ 操作数 ] [ ;注释 ] 二、伪指令
E N D
第四章 汇编语言程序设计 • 第一节 汇编语言程序的格式和伪指令 • 第二节 汇编语言源程序汇编 • 第三节 汇编语言源程序设计举例
计算机程序设计语言通常分为机器语言、汇编语言和高级语言等三类。计算机程序设计语言通常分为机器语言、汇编语言和高级语言等三类。 • 机器语言能被计算机直接识别和执行; • 汇编语言是一种面向机器的语言 ; • 高级语言是一种面向过程和问题并能独立于机器的通用程序设计语言 ;
第一节汇编语言源程序的格式和伪指令 一、汇编语言源程序的格式 [标号:] 操作码 [操作数] [;注释] 二、伪指令 伪指令:不属于指令集中的指令,在汇编时不产生目标代码,不影响程序的执行,仅指明在汇编时执行一些特殊的操作。 例如:为程序指定一个存储区,将一些数据、表格常数存放在指定的存储单元,对位地址赋用户名称,说明源程序段或数据块起始地址等。
1、定义起始地址伪指令ORG 格式:ORG 操作数 此伪指令的操作数为一个16位的地址,它指出了下面的那条指令的目标代码的第一个字节的程序存储器地址。在一个源程序中,可以多次定义ORG伪指令,但要求规定的地址由小到大安排,各段之间地址不允许重叠。 例: ORG 0000H LJMP MAIN ┆ ORG 1000H MAIN:MOV A,#30H ADD A,#20H
2、定义赋值伪指令EQU 格式:字符名称 EQU 操作数 该伪指令用来给字符名称赋值。在同一个源程序中,任何一个字符名称只能赋值一次。赋值以后,其值在整个源程序中的值是固定的,不可改变。对所赋值的字符名称必须先定义赋值后才能使用。其操作数可以是8位或16位的二进制数,也可以是事先定义的表达式。 例:BUF EQU 58H; 字符名称BUF的值等于58H LOOP EQU 2000H;LOOP为2000H,作为16位地址
3、定义数据地址赋值伪指令DATA 格式:字符名称 DATA 操作数 DATA伪指令的功能和EQU伪指令相似,不同之处是DATA伪指令所定义的字符名称可先使用后定义,也可先定义后使用。在程序中它常用来定义数据地址。
4、定义字节数据伪指令DB 格式:[标号:] DB 数据表 该伪指令是用来定义若干字节数据从指定的地址单元开始存放在程序存储器中。数据表是由8位二进制数或由加单引号的字符组成,中间用逗号间隔。 DB伪指令确定数据表中第一个数据的单元地址有两种方法,一是由ORG伪指令规定首地址,二是由DB前一条指令的首地址加上该指令的长度。 例: ORG 1050H TAB:DB 44H,24H,00H,81H DB 24H,14H,00H,42H DB 96H,40H,’C’,’g’ 用DB定义的数据表的首地址是由TAB标号指出并由ORG伪指令规定的1050H,数据表中的各数据依次存放在从TAB开始的存储单元中。
5、定义双字节数据伪指令DW 格式:[标号:] DW 数据表 该伪指令与DB伪指令的不同之处是: DW定义的是双字节数据,而DB定义的是 单字节数据,其它用法都相同。 在汇编时,每个双字节的高8位数据要排 在低地址单元,低8位数据排在高地址 单元。
6、定义预留空间伪指令DS 格式:[标号:] DS 操作数 该伪指令是用于告诉汇编程序,从指定的地址单元开始(如由标号指定首址),保留由操作数设定的字节数空间作为备用空间。要注意的是DB、DW、DS伪指令只能用于程序存储器,而不能用于数据存储器。 例: ORG 1200H LOOP3:DS 0AH 以上伪指令经汇编后从1200H单元开始,保留10个字节的存储单元内容是空的,空间预留出来。
7、定义位地址赋值伪指令BIT 格式:字符名称BIT 位地址 该伪指令只能用于有位地址的位(片内RAM和SFR块中),把位地址赋予规定的字符名称,常用于位操作的程序中。 例:X0 BIT 00H X1 BIT 01H 以上伪指令是把片内RAM块20H单元中位地址00H和01H的2个位定义为X0和X1的位名称,这是一种由用户通过伪指令BIT来定义的位名称。定义后,对这2个位的操作,可不用给出位地址而用此位名称代替。
8、定义汇编结束伪指令END 格式:[标号:] END 汇编结束伪指令END是用来告诉汇编程序,此源程序到此结束。在一个程序中,只允许出现一条END伪指令,而且必须安排在源程序的末尾。否则,汇编程序遇到END伪指令就结束,对END伪指令后面的所有语句都不进行汇编。通常在END前不用标号。 ┆ 例: MOV A,30H ADD A,31H MOV 32H,A END
第二节汇编语言源程序汇编 用汇编语言编写的源程序称为汇编语言源程序。通过汇编将其转换成用二进制代码表示的机器语言程序,才能够识别和执行。 汇编通常由专门的汇编程序来进行,通过编译后自动得到对应于汇编源程序的机器语言目标程序,这个过程叫机器汇编。另外还可用人工汇编。 一、汇编程序的汇编过程 二、人工汇编
第三节 汇编语言程序设计举例 汇编语言程序设计通常的步骤是: 1、建立数学模型。根据课题要求,用适当的数学方法来描述和建立数学模型。 2、确定算法,绘制程序流程图。算法是程序设计的基本依据。程序流程图是编程时的思路体现。 3、编写源程序。合理选择和分配内存单元、工作寄存器。按模块结构具体编写源程序。 4、汇编及调试程序。通过汇编生成目标程序,经过多次调试,对程序运行结果进行分析,不断修正源程序中的错误,最后得到正确结果,达到预期目的。编写一个应用系统的汇编语言源程序,其程序结构一般有顺序结构、分支结构、循环结构、子程序结构等。
解:对应于0~9的十进制数的ASCII码是30H~39H,其固定差值为30H。将该BCD数除以16即使之右移4位,再将右移后的值加上30H即得到高4位BCD数的ASCII码。解:对应于0~9的十进制数的ASCII码是30H~39H,其固定差值为30H。将该BCD数除以16即使之右移4位,再将右移后的值加上30H即得到高4位BCD数的ASCII码。 MOV A,30H ; 取30H单元中的BCD码数 MOV B,#16 DIV AB ADD A,#30H MOV 31H,A ADD B,#30H MOV 32H,B 一、顺序程序设计 例4-2试用除法指令编程,将存于内部RAM 30H单元中的8位BCD码数转换成对应的ASCII码。此BCD数的高4位转换后存入31H单元中,低4位转换后存入32H单元。
二、分支程序的设计 1、单分支选择结构 例4-3设内部RAM 40H和41H单元中存放2个8位无符号二进制数,试编程找出其中的大数存入30H单元中。 解: MOV A,40H CJNE A,41H,LOOP;取2个数进行比较 LOOP:JNC LOOP1 ;根据CY值,判断单分支出口 MOV A,41H ;41H单元中是大数 LOOP1:MOV 30H,A ;40H单元中是大数
2、多分支选择结构 例4-4设内部RAM 50和51H单元中存放2个8位有符号数,试编程找出其中的大数存入60H单元中。 分析:比较两个有符号数的方法有多种,可以先判断是同号还是异号,若是同号,再判其大小,若是异号,显然正数的那个大。
MOV A,50H XRL A,51H JB ACC.7,LOOP;判是否异号,若是异号转LOOP MOV A,50H CLR C SUBB A,51H ;因是同号,比较其大小 JC LOOP1 ;若差为负数转LOOP1 MOV 60H,50H ;50H单元中的数大 SJMP EXIT LOOP1:MOV 60H,51H ;51H单元中的数大 SJMP EXIT LOOP: MOV A,50H JB ACC.7,LOOP1; 若50H单元中是负数转LOOP1 MOV 60H,50H ; 50H单元中是正数 EXIT: SJMP $
例4-5设变量X的值存放在内部RAM的30H单元中,编程求解下列函数式,将求得的函数值Y存入40H单元。例4-5设变量X的值存放在内部RAM的30H单元中,编程求解下列函数式,将求得的函数值Y存入40H单元。 X+1 (X≥100) Y = 0 (10≤X<100) X-1 (X<10)
MOV A,30H ;取自变量X值 CJNE A,#10,LOOP ;与10比较,A中值不改变 LOOP: JC LOOP2 ;若X<10,转LOOP2 CJNE A,#100,LOOP1;与100比较 LOOP1:JNC LOOP3 ;若X≥100,转LOOP3 MOV 40H,#00H ;因10≤X<100,故Y=0 SJMP EXIT LOOP2:DEC A ;因X<10,故Y=X-1 MOV 40H,A SJMP EXIT LOOP3:INC A ;若X≥100,故Y=X+1 MOV 40H,A EXIT: SJMP $
三、循环程序设计 在程序设计中实际处理问题时,有时要求某些程序段多次重复执行,可采用循环结构来实现。循环结构可使程序简练易读,并大大节省存储空间。 1、循环结构的组成 循环结构由四部分组成:初始化部分、循环处理部分、循环控制部分和循环结束部分。 根据循环程序的结构不同也可分为单重循环和多重循环。对循环次数的控制有多种。循环次数已知的,可用循环次数计数器控制循环。对循环次数未知的,可以按条件控制循环。
2、循环程序设计 (1)单重循环程序设计 例4-6设内部RAM存有一无符号数数据块,长度为128字节,在以30H单元为首址的连续单元中。试编程找出其中最小的数,并放在20H单元。 解: MOV R7,#7FH ;设置比较次数 MOV R0,#30H ;设置数据块首址 MOV A,@R0 ;取第一个数 MOV 20H,A ;第一个数暂存于20H单元,作为最小数 LOP1:INC R0 MOV A,@R0 ;依次取下一个数 CJNE A,20H,LOOP LOOP:JNC LOP2 ;两数比较后,小的数放在20H单元 MOV 20H,A LOP2:DJNZ R7,LOP1;R7中内容为零则比较完 SJMP $
(2)多重循环 一个循环程序的循环体中还包含一个或多个循环的结构,叫做双重循环或多重循环。 对于有些复杂问题,采用单循环往往不能满足要求,需要采用多重循环才能解决。当一个大循环中套一个小循环时,称为循环嵌套。MCS-51单片机对循环嵌套重数没有限制,它由堆栈空间决定。 多重循环结构,必须层次分明,循环时是从外层向内层一层层进入,从内层向外层一层层退出。两循环之间不允许交叉。严格限制用跳转指令从外层循环直接进入内层循环体内。
例4-9用软件实现10ms的延时,设晶振频率为12MHz。例4-9用软件实现10ms的延时,设晶振频率为12MHz。 • 解:此例是最典型的双重循环程序,根据实际延时需要,分别对R6和R7预置初值以控制循环次数。 • 解:MOV R6,#10 ;外层循环设置10次 • LOOP1:MOV R7,#200 ;内层循环设置200次 • LOOP:NOP ;用空操作指令调整延时值 • NOP • NOP • DJNZ R7,LOOP ;若内层循环未完转LOOP DJNZ R6,LOOP1 ;若外层循环未完转LOOP1 • SJMP $
四、子程序设计 MCS-51单片机指令系统有调用子程序的指令和子程序返回指令。一个主程序可以多次调用同一个子程序,也可以调用多个子程序。子程序也可以调用其它子程序,这叫子程序嵌套。没有规定子程序嵌套的重数,它只受堆栈空间的限制。 一般在调用子程序前要设置子程序的入口参数和出口参数。其参数传递方法通常有三种:即利用寄存器传递参数、利用寄存器间接寻址传递参数、利用堆栈传递参数。
例 设内部RAM存有128字节ASCII码字符串,首址为30H。要求将该字符串中每个字符按偶校验在最高位加偶校验位。试以调用程序的方法来实现。 程序如下: MOV R7,#80H ;置数据块长度 MOV R0,#30H ;置数据块首址指针 LOOP:MOV A,@R0 ;取未加偶校验位的ASCII码 LCALL SUB1 ;调用加偶校验位的子程序 MOV @R0,A ;已加偶校验位的ASCII码回送 INC R0 DJNZ R7,LOOP SJMP $ SUB1:ADD A,#00H JNB P,EXIT ;判原字符P=1否?若是则加偶校 验位,否则不加。 ORL A,#80H EXIT:RET
五、查表程序设计 在单片机程序设计中,查表程序是一种常用程序,它广泛使用于LED显示控制中查字段码表,键盘扫描控制中查键值表,代码转换中查ASCII码表等程序中。 所谓查表,就是把事先设计的数据按一定顺序编制成表格,存放在程序存储器中,由查表程序查出所需要的表格中的数据。 MCS-51单片机指令系统中有两条查表指令: 1、用MOVC A,@A+DPTR指令查表。 2、用MOVC A,@A+PC指令查表。 数表中的数据可用伪指令DB或DW来定义,汇编时会将此数表中的数据作为目标代码放在自表首地址开始的一个连续的ROM区域中。
例4-16设在内部RAM 30H单元中存有一位十六进制数,试通过查表的方法把它转换为ASCII码,并存入40H单元中。 解:程序如下: STAR:PUSH PSW ;将PSW压栈保护 PUSH ACC ;将A压栈保护 MOV A,30H ;取该十六进制数 MOV DPTR,#TAB ;置数表首地址 MOVC A,@A+DPTR ;读数表中ASCII码 MOV 40H,A ;存入查表后的ASCII码 POP ACC ;恢复A中的值 POP PSW ;恢复PSW中的值 RET TAB:DB 30H,31H,32H,33H,34H,35H,36H,37H DB 38H,39H,41H,42H,43H,44H,45H,46H END
六、散转程序设计 在单片机实际应用中,经常遇到根据某一输入变量或运算结果转向不同的处理程序入口。 MCS-51单片机指令系统中散转指令JMP @A+DPTR就是由基址值DPTR和变址值A之和决定程序的转向地址,可很方便的实现多路分支程序的处理。
例4-18试根据30H单元中的值设计一段转256路分支的子程序。例4-18试根据30H单元中的值设计一段转256路分支的子程序。 解:START:MOV A,30H ;读取转口参数 CLR C RLC A ;由于各分支入口地址相距是偶数字节 MOV DPTR,#TAB JNC LOOP ;若是前128个分支入口,转LOOP INC DPH ;是后128个分支入口,高8位地址加1 LOOP:JMP @A+DPTR ;散转到相应入口 SJMP $ TAB:AJMP LOOP0 ;转到分支程序0入口 AJMP LOOP1 ;转到分支程序1入口 ┆ AJMP LOOP255 ;转到分支程序255入口 AJMP $ LOOP0:……;分支0处理程序 SJMP $ LOOP1:……;分支1处理程序 SJMP $ ┆ LOOP255:……;分支255处理程序 SJMP $