《第四章 汇编语言程序设计.doc》由会员分享,可在线阅读,更多相关《第四章 汇编语言程序设计.doc(18页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、 第四章 汇编语言程序设计 4.1 程序设计语言 4.1.1 机器语言 以二进制代码形式表示指令和数据的语言.(机器码) 如 + 30H 其机器语言程序为 符号语言程序 二进制 十六进制 74H MOV A, #3AH 3AH 24H ADD A, #5CH 5CH F5H MOV 30H, A 30H 计算机能够识别机器语言,并能够按设计好的逻辑执行这一串代码所规定的动作.但这种语言难懂、难记、易错和编程困难。 借助助记符形成符号语言,反映指令功能和主要特征,这样便于理解和记忆,这就形成汇编语言。 4.1.2 汇编语言 用符号来表示指令和地址的语言就称作符号语言,又称作汇编语言。这也是一种面
2、向机器的语言。 汇编语言的符号 往往用人们容易辨认、阅读和记忆的字母符号。 ()助记符: 指令系统,如加法 ADD,减法 SUB(TRACT),传送 MOV(E) 伪指令,这是汇编控制指令 ()符号地址和标号: 用一些便于、记忆和理解的符号组,如 LOOP、NEXT 汇编 () 几个概念 源程序: 用符号语言编写的程序。 目标程序:机器能够直接执行的机器语言程序。 把源程序翻译成目标程序的过程就称作 汇编,又称作 代真。 () 汇编方法 人工查表 人工汇编: 源程序目标程序 要求一丝不苟,认真细致,繁琐且易出错。 汇编程序 机器汇编: 源程序目标程序 汇编语言程序 机器语言程序 准确、快速,不
3、会出偶然性错误 ()汇编类型 自汇编:机器本身完成的汇编过程,又称驻留汇编。 交叉汇编:用其他机器将程序变成目标程序后送回机器执行。 反汇编:将目标程序变回汇编语言程序。 ! 汇编语言程序与汇编程序是两个不同的概念,不能混淆。 汇编语言虽然比机器语言前进了一大步,但它还是面向机器的一种语言,不同的机器就要有不同的汇编语言,要用汇编语言编写程序,就必须对该种计数器十分熟悉(包括指令系统以至于硬件情况),而且编写出的程序只能在这种机器上使用。有没有不依赖或少依赖机器的语言呢?这就是高级语言。 4.1.3 高级语言 只与解决问题的算法有关,而与机器的类型、结构和指令系统无关。 面向过程的语言: 科学
4、计算: FORTRAN、ALGOL、PASCAL、BASIC、C 商业管理: COBOL 数字程控: APT 人工智能: LISP、PROLOG 面向对象的语言: Smalltalk、C+、Visual BASIC 、Visual C+ (1) 优点 不依赖(很少)依赖于机器,学习容易,变成效率高,使用方便,程序短,便于交流和推广。 可移植性好,同一个程序可以在不同的机器上运行。 (2) 缺点 语法复杂,特殊规定多 用高级语言编写的程序要经过编译程序(Compiler)或解释程序(Interpreter)翻译成目标程序才能运行。而高级语言的编译开销大,要有大量的硬件和软件支持,需要占用大量内存
5、,高级语言越复杂,功能越强,编译程序越庞大(从几k到几M);运行效率低,一般要膨胀15300。 4.1.4 使用汇编语言的意义 高级语言的编译程序大多是用汇编语言编写 汇编语言的运行效率高,提高了计算机的效率,这在实时控制应用中特别重要。 对专用程序、重复使用频率高的程序应该用汇编语言编写,更加有利于提高效率。 采用汇编语言可以充分发挥机器的专有特性。 硬件成本低和软件投资少。 搞通汇编语言,有助于理解和评价高级语言。 4.1.5 结论 使用机器语言和汇编语言无需太多的软件和硬件支持,而且能产生质量很高的目标程序,但成程序没有通用性,难编难懂。 总的来说,汇编语言开发效率低,运行效率高。 高级
6、语言面向过程和面向对象,不依赖于个别的机器,程序相对易编易懂,便于交流使用,但需要较多的软件和硬件支持,而且产生的程序相对质量较低,所占用的时间和空间都大,时空指标下降,一般不适用于实时响应。 总的来说,高级语言开发效率高,运行效率低。 4.2 MCS-51系列单片机汇编语言 4.2.1 汇编语言源程序格式 指令助记符符号由厂方设计人员规定。 符号地址由用户自己确定。 典型的汇编语言语句结构由四部分组成: 标号: 操作码 操作数 ; 注解 (Lable) (Opcode) (Operand) (Comment) 标号后面用冒号分隔,操作码与操作数之间用空格分隔,操作数之间用逗号分隔,操作数与注
7、解之间用分号分隔。 标号:指令的符号地址,在程序汇编时,就被赋以指令存储地址的具体数值。采用符号地址便于查看、修改,尤其是转移指令中转移地址的表示。 实际上并不是每条指令都需要加上标号,只有要被其他语句引用的指令才需要加上标号。 标号有如下规定: () 由字母、数字和其他一些字符组成,但为了在汇编时与数据区分,要求第一个符号必须是大写字母。所用字符一般不超过6个。 () 标号不能用操作码的助记符和寄存器的代号以及其他系统保留字。 () 特定的标号只能在程序中定义一次,保持一义性。 请大家对以下几个标号进行判断,看是否合法: NEXT2 3AB LOOP3 M3 ADD DPTR B3GK4D
8、SP COUNTER -AZ nmpq 操作码字段 这一字段永远不会是空的。(其他三个字段有时会是空的) () 指令系统的助记符(硬指令),即指令操作码助记符。 在汇编时,与“操作码表”进行逐一比较,找出其相应的机器码代真。 () 伪指令(软指令),这是汇编过程的控制指令,也是汇编程序的操作指令。与指令系统的助记符不同,没有机器码与它对应,当源程序汇编成目标程序后,目标程序中并不出现这些伪指令的代码,它们仅在汇编过程中起作用,完成一些特定的操作。 操作数字段 操作对象的数据值或以符号表示的数据或地址值。形式可以是工作寄存器、专用寄存器、已用伪指令EQU赋值的标号、用引号表示的ASCII码、立即
9、数(二进制、八进制、十进制和十六进制)和表达式。 注释字段 用来对程序作一些注解和说明,便于人们阅读程序,汇编程序对此字段不予处理。在些注释时,一般说明指令的作用和执行的条件,注意要说明程序在做什么,而不是说明该指令在做什么。在用到子程序时,要说明子程序的入口条件和出口条件以及该程序完成的功能和作用。 4.2.2 伪指令 这是用来向汇编程序提供的有关如何完成汇编的控制命令信息。一旦汇编结束,伪指令的使命就完成,所以在目标程序中并不出现伪指令的代码。 ORG (Origin) 起点 形式:标号: ORG 地址 作用:指明此语句后面的程序或数据块存放区的首址。 在一个程序中可以根据情况多次使用。其
10、中标号是选择项,根据需要选用,地址可以是16位的地址值,也可以是已赋值的标号和表达式。 如 ORG 2000H 首地址为2000H ORG 100 首地址为0064H ORG BEGIN 在使用前要给BEGIN赋值 ORG 首地址为0000H DB或DEFB (Define Byte) 定义字节 形式:标号 DB 8位数表 作用:把8位数表中的数值或字符的ASCII码存入从标号开始的连续存储单元中。 其中8位数表是指一个字节或用逗号分开的字节串和引号内的ASCII码。 如 ORG 2400H FIRST:DB 56H,0A3H ;56H、0A3H分别存放在2400H和2401H单元 WORD:
11、DB -3,5*2 ;FDH和0AH存放在2402H和2403H单元中 STR:DB TIME ;TIME的ASCII码54H、49H、4DH和45H存放在2404H、 ;2405H、2406H和2407H单元中 DW或DEFW (Define Word) 定义字(主要用于定义地址) 形式:标号 DW 16位数表 作用:把16位数表中的数值或字符的ASCII码存入从标号开始的连续存储单元中。 如 ORG 2400H ADDR:DW 56A3H ;56H、A3H分别存放在2400H和2401H单元 DW AB ;41H、42H分别存放在2402H和2403H单元 DS或DEFS (Define
12、Storage) 定义存储器 形式:标号 DS 8位数表 作用:由标号所指单元开始,保留指定的内存单元(字节)个数,以供源程序在运行中使用。 如 ORG 3000H MAX:DS 1 ;保留3000H单元供存放“最大数”用 BUF:DS 10 ;从3001H单元开始保留10个单元作缓冲区 EQU (Equate) 等值 形式: 标号: EQU 赋值项 作用: 使等式两边的8位量等值,赋值后在程序中不能改变。 如 FIRST:EQU 20H ;给符号地址赋值为20H FIRST:EQU SECOND ;SECOND与FIRST等值,可在使用中互换 EQW (Equate Word) 字等值 形式
13、: 标号: EQW 赋值项 作用: 使等式两边的16位量等值,赋值后在程序中不能改变。 如 FIRST:EQU 2200H ;给符号地址赋值为2200H FIRST:EQU SECOND ;SECOND与FIRST等值,可在使用中互换 BIT 位定义 形式: 标号:BIT 8位位地址 作用:给标号赋以位地址,该地址可以是直接地址,也可以是符号地址或位名 如 USR-FLG:BIT F0/PSW.5 USR_FLG:BIT 0D5H END 结束汇编 形式: 标号: END 表达式 作用:通知汇编程序该汇编语言程序结束 () 在一个源程序中必须要有END伪指令。而且只能有一个放在整个程序的最后;
14、 () 标号只有在其他指令要引用它时才需要; () 表达式一般在主程序中才需要,且表达式即为主程序的起始地址,表示结束源程序的汇编,如果汇编正确,便自动地转向此首址的目标程序执行。 如 MOV R0,#60H ORG 2000H MOV A,#3AH SUM:EQU 60H MOV B,#0AH NUMBA:EQU 3AH MUL AB NUMBB:EQU 0AH MOV R0,B MOV R0,#SUM INC R0 MOV A,#NUMBA MOV R0,A MOV B,#NUMBB MUL AB MOV R0, B INC R0 MOV R0, A END 4.3 汇编语言程序设计 4.
15、3.1 简单直线程序 顺序程序 例 多字节数加法 两个三字节无符号数加法,一个加数在片内RAM的50H、51H、52H单元中,另一个加数在53H、54H、55H单元中,要求相加之和存放在53H、54H、55H、56H单元中。 MOV R0,#50H MOV R1,#53H MOV A,R0 ADD A,R1 MOV R1, A INC R0 INC R1 MOV A,R0 ADDC A,R1 MOV R1, A INC R0 INC R1 MOV A,R0 ADDC A,R1 MOV R1, A CLR A ADDC A,#00H MOV R1, A 查表程序 查表程序常用于数据补偿、非线性修
16、正、求非线性函数和代码转换等。这种方法既不需要计算,速度又快,而且实现容易。如果在程序中不能用几条指令直接完成算术运算时,往往用查表法实现比较有利。但在表中必须列出所有可能的值。所以这种方法需要占用较大的存储器空间。其实质是用空间换取时间。使用查表法的技巧在于巧妙地确定索引值,用得恰当可以大大简化程序设计,带来很大方便。 特点:程序简单,执行速度快; 在表中要列出所有可能的值,占用存储器较多,用空间换取时间。 方法: (),根据变量在表中找到相应的值。 表的形成也可用折线来分段,其中间值可通过插值方法计算。 例 热敏电阻上的电压与所测的温度值为非线性关系。若用10位A/D对其电压进行采样,然后
17、通过转换显示其温度值。这里把所测的10位二进制输入值与其相对应的温度值列成表格TTAB。 测量的10位输入值x存放在R2和R3中,查表所得到的温度值也存放在R2和R3中。 10位二进制输入值的范围为0000H03FFH,一共有1024项,其分辨率为1/1024 (0.1) ! 这里表的偏移量(索引值)有两个字节,所以不能用A作为变址寄存器。 VCT:MOV DPTR,#TTAB ;指向表格的首址 MOV A, R3 ;以下计算R2R3+DPTR ADD A, DPL ;R3+DPL MOV DPL, A MOV A, DPH ADDC A, R2 ;R2+DPH MOV DPH, A ;DPT
18、R指向温度的高字节 CLR A MOVC A, A+DPTR ;读温度的高字节 MOV R2, A CLR A INC DPTR ;DPTR指向温度的低字节 MOVC A, A+DPTR ;读温度的低字节 MOV R3, A RET TTAB:DW XXXX ;温度值表 DW XXXX 例 键入一个ASCII字符,按不同的输入命令字符而转去执行相应的处理程序。设有六个命令字符“I”(输入)“D”(删除)“S”(存储)“C”(复制)“P”(打印)“T”(转换),对应的处理程序入口标号地址分别为AI、AD、AS、AC、AP、AT,用0作为表格的结束符。命令字符在Acc中。 CCP:MOV DPTR
19、, #CATAB MOV B, A ;命令字符暂存于B中 LOOP:CLR A MOVC A, A+DPTR ;取命令项X JZ CEND ;在表中未找到该命令项,转出错处理 INC DPTR ;指向地址项Y CJNE A, B, NEXT ;若不是该命令,转调整指针继续查找 CLR A MOVC A, A+DPTR ;若是该命令,取出其入口地址的高8位 MOV B, A ;暂存于B INC DPTR ;指向入口地址的低8位 CLR A MOVC A, A+DPTR ;取出入口地址的低8位 MOV DPL, A MOV DPH, B ;入口地址送DPTR CLR A JMP A+DPTR NE
20、XT:INC DPTR ;调整指针,指向下一个命令项 INC DPTR SJMP LOOP CEND:容错或出错处理程序 CATAB:DB I 49H DW AI DB D 44H DW AD DB S 53H DW AS DB C 43H DW AC DB P 50H DW AP DB T 54H DW AT 代码转换程序 例 8位二进制数转换成BCD数 分析:8位二进制数最大为255,是百位数,要用三位表示,而一个字节的BCD数只能表示小于100的两位数,所以转换结果要用两个字节单元来存放。 思路:先除以100,商即为百位数,余数再除以10,商即为十位数,余数即为个位数。 若要转换的8位二
21、进制数在Acc中,要求转换后的BCD数存放在片内RAM的60H、61H和62H中。 BCD1:MOV R0, #60H ; MOV B, #100 ;除数 DIV AB ;(A)=百位数,(B)=余数 MOV R0, A ;存放百位数 INC R0 ;指向下一个单元 MOV A, #10 ;10是除数,B中是余数(被除数) XCH A, B ;(A)=余数,(B)=10 DIV AB ;(A)=十位数,(B)=个位数 SWAP A ;十位数移至高4位 ADD A, B ;个位数加到低4位 MOV R0, A ;十位数和个位数存入下一个单元 RET 例 一位16进制数转换成ASCII码。 一位1
22、6进制数在Acc中,其相应的ASCII码存放在60H单元。 HEXASC:MOV R0, #60H ANL A, #0FH ;取低4位 ADD A, #02 MOVC A, A+DPTR PC MOV R0, A RET ASCTAB:DB 0,1,2,3,4 DB 5,6,7,8,9 DB A,B,C,D,E,F 一种简单而快速的算法: ADD A, #90H DA A ADDC A, #40H DA A RET 4.3.2 分支程序 相当于高级语言中的IF-THEN条件语句,由于条件转移指令可根据条件是否满足来改变程序的执行顺序,凡是有判断与比较的地方都可以形成不同的程序分支。 典型的分支
23、程序框图 编好分支程序的关键是掌握好标志的变化,使 程序能正确转移.同一个数若用不同的标志位作为程序转移的判断条件,那么该数就具有不同的含义。 单分支程序 片内RAM两个单元ONE和TWO中存放有两个无符号数,将其中一个大数存放到MAX单元。 MOV A, ONE ;将第一个数送Acc CJNE A, TWO, BIG ;第一个数与第二个数进行比较 SJMP STORE ;若两数相等,就存放第一个数 BIG: JNC STORE ;无借位,第一个数第二个数 MOV A, TWO ;有借位,第一个数第二个数 STORE: MOV MAX, A ;大数存入MAX单元 多分支程序散转程序 这是一种需
24、要根据某种输入或运算结果分别转向各个不同的处理程序的程序结构。其一般结构框图如下: 例 利用地址偏移量表实现(如转向程序在同一页(256字节)内) 按照R2的内容(00H03H)分别转向4个不同的处理程序。 JMPN: MOV A, R2 MOV DPTR, #JTAB MOVC A, A+DPTR JMP A+DPTR 1500H JTAB: DB PROG1-JTAB /20H 1502H DB PROG2-JTAB /60H 1504H DB PROG3-JTAB /A0H 1506H DB PROG4-JTAB /D0H 1520H PROG1: 处理程序 1560H PROG2: 处
25、理程序 15A0H PROG3: 处理程序 15D0H PROG4: 处理程序 例 使用转移指令表,最大可有128个分支转移程序 根据R2的内容(00H7FH),转向各个不同的处理程序。 JMP128: MOV A, R2 RL A / ADD A, R2 ;(R2)X2 MOV DPTR, #JTAB JMP A+DPTR JTAB: AJMP PROG1 ;转移程序必须在同一个2k存储区内 AJMP PROG2 . AJMP PROGN 若转移程序不在同一个2k范围内 可用以下指令实现再转移: PROG1: LJMP XPRG1 PROG2: LJMP XPRG2 . PROGN: LJM
26、P XPRGN 也可把转移指令表中的转移指令AJMP改用长转移指令LJMP,转移程序可以转向任一个地方,但这时索引值为(R2)X3 4.3.3 循环程序 如果要对一组数据进行操作,并且这种操作是相同的,需要多次重复进行,这就可以用循环程序来实现。 方法:用计数器来记录重复操作的次数或用地址指针来描述所处理数据在数组中的位置,也可根据某一条件是否满足来决定是否继续循环,从而控制循环重复操作的进行或结束。 循环结构相当于高级语言中的循环语句REPEAT-UNTIL或WHILE-DO. 循环结构实际上也是一种分支程序结构,所不同的是分支结构的分支都是向下转移,而循环结构则有一个分支是向上转移,重复执
27、行某一循环体。 典型的循环程序流程图有两种: (1) 先执行,后判断 (2) 先判断,后执行 相当于 repeat-until 相当于 while-do 处理部分至少执行一次, 在计数初值为0时,处理部分就不执行 看起来自然一些,似乎更符合习惯 适应性更强、更有效,但看起来别扭 ! 循环程序一定要安排出口,否则就得无限制地循环下去死循环 初始化部分:建立计数器、地址指针及其他变量的初值 循环结束条件初值 循环工作部分初值 处理部分(循环体):进行实际数据处理工作 循环控制部分:为下一轮处理修正计数器(计数器减1)和地址指针(地址指针加1),并检测循环结束条件,以决定下一步的去向。 结束部分:分
28、析和存放结果 一般第一部分和第四部分只执行一次,而第二部分和第三部分则需要重复执行多次,所以第二和第三部分程序的质量对整个程序有决定性影响,为提高整个程序的执行速度,就应着重减少第二和第三部分程序段的执行时间。 单循环程序 例 对一个32个单元的数据缓冲区(30H4FH)清零 CLRBUF:MOV R0, #30H MOV R7, #20H CLR A LOOP:MOV R0, A INC R0 DJNZ R7, LOOP 例 计算若干数据的和 n 0 0 i i i-1 +i i1n i=1 如i 都为单字节数,可依次存放在片内RAM从50H开始的单元内,n放在R2中,和放在R3R4中。 A
29、DDSUM:MOV R3, #00H MOV R4, #00H ;和单元清零 MOV R0, #50H ;用R0作数据指针 LOOP:MOV A, R4 ADD A, R0 MOV R4, A INC R0 ;指向下一个数据,为下一轮作准备 CLR A ADDC A, R3 ;扩展衬16位(加进位) MOV R3, A DJNZ R2, LOOP 例 二路电压值测量输入 如图所示,需要测量V1和V2的值,测量值分别存放在60H和61H两个单元中, 用P1.0切换:P1.0=1,测量V1 P1.0=0,测量V2 因为测量、转换和计算处理程序相同,可用循环方法使用同一段程序实现SETB P1.0M
30、OV R0, #60HLOOP: A/D转换(用延时、查询或中断法)计算处理,把电压转换成温度值结果存放在Acc中MOV R0, AINC R0JBC P1.0, LOOP 多重循环程序 例 50ms延时程序-两重循环 12MHz的晶振,一个机器周期为1s,DJNZ指令周期为2s。 DELAY:MOV R7, #200 ;1s DEL1:MOV R6, #123 ;1s NOP ;1s DEL2:DJNZ R6,DEL2 ;2sX123+2=248s DJNZ R7,DEL1 ;(248s2)X200+1=50001s ; = 50.001MS 例 搜索最大值 从片内RAM的BLOCK单元开始存放一组无符号数,该数据块的长度存放在LEN单元中,查找出其中的最大数存放在MAX单元中。 算法:先取出第一个数与第二个数进行比较,把大数放在Acc中,再用Acc中的大数与下一个数进行比较,同样把大数放在Acc中,直至比较结束,把最大数按要求存放起来。 BLOCK: EQU 30H LEN: EQU 2FH MAX: EQU 2EH MOV R0, #BLOCK ;用R0作数据块地址指针 MOV R7, LEN ;用R7作循环次数计数器 DEC R7 ;循环次数数据块长度