1、0第五章 汇编语言程序设计方法本章课题:汇编语言程序设计方法教学内容:1)、汇编语言程序设计2)、顺序与循环程序设计方法3)、分支程序设计方法4)、查表程序设计方法5)、子程序设计方法6)、综合程序设计方法教学目的:通过本章的学习应掌握汇编语言程序设计方法,具备较复杂程序设计能力。本章重点:汇编语言程序设计方法本章难点:分支程序设计方法教 案:第一节 汇编语言程序设计1、程序设计语言1)、机器语言直接用二进制数表示指令和数据的最原始的程序设计语言。2)、汇编语言用助计符来表示的面向机器的程序设计语言。用汇编语言编制的程序须要用“人工汇编”或“机器汇编”将其翻译成机器语言,才能被机器认识。3)、
2、高级语言高级语言是一种面向过程而独立于计算机硬件结构的通用计算机语言。如FORTRAN、 PASCAL、C 语言等。注意:机器语言直接面对机器,实时性好,但难以编出较复杂的程序,现基本上被汇编语言代替;汇编语言是目前单片机初学者采用的一种编程方法,它具有实时性强,对较复杂的程序也能编制。1高级语言它面向过程易于编制复杂程序,具有通用性好,程序简单,但它要求占用较大的内存空间,实时性差,目前从事单片机的开发和研究工作须掌握这种方法。2、汇编语言的规范1)、汇编语言源程序的格式标号:操作码 目的操作数,源操作数;注释2)、汇编语言伪指令ORG-起始地址伪指令;功能:用来规定目标程序或数据的起始地址
3、。格式:标号: ORG 16 位地址说明:在一个程序中允许有多个 ORG 指令,以规定不同程序段的起始位置。END-汇编结束伪指令;功能:用来告诉汇编程序,此源程序到此结束。格式:标号: END说明:在一个程序中有且只有一个 END 指令。例如: ORG 1000HSTART:MOV A,BJNB ACC.7,DONECPL ADONE:MOV B,AENDEQU-赋值伪指令;格式: 字符名称 EQU 数或汇编符号功能:将右边值赋给左边用户定义的字符说明:a、由 EQU 赋的字符可以作数值、数据地址、代码地址。b、由 EQU 伪指令所定义的符号必须先定义后使用。例如:SDGFG EQU 58H
4、 ;表示 SDGFG=58HDB-定义字节伪指令;格式:标号: DB 8 位(二进制)数据表。2功能:用于告诉汇编程序从指定的地址单元开始,定义若干个字节存储单元的内容。说明:a、数据表可以是二进制数也可以是 ASC 编码,数据之间用逗号分开,ASC 要加单引号,如 C,要写成C 。b、它只适应程序存储器。例如: ORG 1000HFIRST:DB 73H,20H,45H,67H,01HMOV A,#55HDB 34H,67H,89H,70H执行后的结果如图 1 所示、DW-定义值伪指令;功能:用来告诉汇编程序从指定的地址单元开始,定义若干个 16 位数据(二进制) 。格式:标号: DW 字常
5、数或 ASC字符说明:a、字常数可以是 8 位也可以是更多位。b、尽管在存储数据的形式上与 DB 相同但使用不一样, DB 后面只能跟 8 位的数据或 ASC字符。 C、它只适应程序存储器。d、单个 DW、DB 定义的数表个数不得超过 80 个,多于 80 个数据应用多个指令完成例如: ORG 1000HPIOI:DW 5678H,1234H,2379H结果如图 2 所示。、TA-数据地址赋值伪指令;格式:字符名称 DATA 表达式功能:它的功能是给标号段中的标号赋以数值。说明:a、本语句与 EQU 相似,但本语句可以先用后定义;b、在程序中它常用来定义数据地址。1000H 73H1001H
6、20H1002H 45H1003H 67H1004H 01H1005H 74H1006H 55H1007H 34H1008H 67H1009H 89H100AH 70H地址: 数据1000H 56H1001H 78H1002H 12H1003H 34H1004H 23H1005H 79H图 1 由 DB 建立的数据表图 2 由 DW 建立的数据表3、BIT-位地址赋值伪指令;格式:字符名称 BIT 位地址功能:用于告诉汇编程序,把位地址赋予规定的字符名称,用于位处理程序中。例如: X0 BIT P1.03、汇编语言程序设计方法1) 、程序设计过程建立数学模型选择适当的算法编制程序流程图汇编语言
7、程序设计汇编语言程序调试2)、程序流程图程序流程图的作用能直观形象地表示各部分的逻辑关系及程序结构,它是设计程序特别是复杂程序的重要工具。程序流程图的组成 端点框表示程序的开始或结束,用 表示,可在内填上相应文字。 流程线表示程序的组向,用方向键 表示。 处理框表示一种处理功能 ;框内用文字说明。用 表示。 判断框用 表示,该框用于指示一个判定点,从这点产生分支,在框内就注明测试条件,而测试结果应注明在各分支流程线上。 连接框连接框用 表示,它表示流程中止而并非流程结束。通常用来辟免流程线交叉,在流程图中标识相同的连接框表示流程相连。4 子程序框用 表示,该框表示调用子程序。在该框内填入相应的
8、子程序名称或入口地址。程序流程图的设计程序流程图的设计将在具体的程序设计方法中针对具体的例子加以介绍。第二节 顺序与循环程序设计方法1、顺序程序设计1)、顺序结构程序设计方法建立数学模型 画程序流程图 编写汇编程序2)、应用举例例 1:设有 16 位二进制数存放在 R0、R1 中(R0 存放高位) ,试编写实现 16 位二进制数“取反加 1”的操作程序。解法 1: 程序流程如图 3 所示,程序如下:ORG 1000HSTART:MOV A,R1CPL AADD A, #01HMOV R1, AMOV A,R0CPL A ADDC A, #00HMOV R0, AEND解法 2:通过将 R0、R
9、1 分别送 DPTR 的高低字节,然后利用 INC DPTR 实现加1,取反后再用:CPL A 这样的指令实现。例 2:设在 8031 单片机内部 RAM 的 40H 单元中存放 8 位二进制数,要求将其转换成相应 BCD 码并由高位的顺序存入内部 RAM 以 60H 为首址的 3 个连续单元中,试开始低位取反加 1高位取反加 C结束图 3 程序流程图5编写相应程序:解:本题的关键是如何将二进制数转换成 BCD 码。由数学变换知:8 位二进制/100=BCD 码的百位数余数/10= BCD 码的十位数余数= BCD 个位数程序如下:ORG 1000HBINBCD: MOV R0, #60HMO
10、V A, 40HMOV B, #100DIV AB ;整数存于 A 中MOV R0, AINC R0MOV A, #10XCH A, BDIV ABMOV R0, AINC R0XCH A, BMOV R0, AEND思考题:对于任意一个 16 进制表示的数,如 AB9EF087,存放在以 20H 为首址的单元中,如何将其转化成 BCD 码?2、循环程序设计方法1)、循环结构程序的组成初始化部分:它是用来设置循环初始化状态,如设置地址指针、循环计数器初值6等。循环处理部分:它是重复执行的数据处理程序。循环控制部分:它通过检测循环次数或循环结束条件从而控制程序循环继续与否。结束部分:它是对结果分
11、析处理和存放结果。2)、循环程序设计方法(1)单循环程序设计方法循环次数是已知的循环程序设计先分析要解决的问题,建立解决问题的数学模型,然后编写出对应的程序,按已知条件设置程序循环次数。循环次数未知的循环程序设计先分析要解决的问题,建立解决问题的数学模型,确定待测定循环的参数,在编程过程中,选取合适的判别语句控制程序的循环。(2) 多循环程序设计方法多循环程序设计除必须满足单循环程序设计的规则外,尚须符合循环不允许交叉的规定。3)、应用举例单循环程序设计举例:例 1:已知 80C51 单片机使用 6MHZ 晶振,要求设计一个软件延时程序,延时时间为 10ms。分析:晶振为 6MHZ 的单片机一
12、个机器周期为 2us,如果采用循环方法,控制程序循环次数,就可以实现定时功能。如图 4 为程序流程。如程序如下: 周期数 ORG 2000H1 MOV R0,#0AH;毫秒数1 DL2:MOV R1,#MT1 DL1:NOP1 NOP开 始1ms延 时R0-=?结 束YN72 DJNZ R1,DL12 DJNZ R0,DL2END定时值的确定:(1+1+2)2usMT=1000usMT=7DH例 2:用 P1 口作为数据读入口,为了读取稳定的值,要求连续读 8 次,然后取平均值。分析:设 R0、R1 作为连续 8 次累加的 16 位工作寄存器,且 R0 存放高位,R1 存放低位,在二进制数的运
13、算中,2=二进制数左移一位, 2=二进制数右移一位。因此本例中8= 将数向右移 3 次。程序流程如图 5,程序如下:程序: ORG 2000HMOV R0,#00HM0V R1,#00HMOV R2。#08HLP2: MOV P1,#0FFHMOV A,P1ADD A,R1JNC LP1INC R0LP1: MOV R1,ADJNZ R2,LP2MOV R2,#03H 图 5 程序流程图CLR CLP3: MOV A,R0RRC AMOV R0,A开 始清 R0、 1设 2=P口 读 入 数存 、-?累 加 结 果 /8结 束YN图 4 程序流程图8MOV A,R1RRC AMOV R1,AD
14、JNZ R2,LP3LP:SJMP LPEND注意:二进制数乘法、除法的计算方法例 3:从 22H 单元开始有一无符号数据块,其长度放在 20H 单元中,求出数据快中最大值,并将其放在 21H 单元。分析:采用比较法,先设 A=00H,然后依次取数与 A 中的值比较,若所比较的数比A 大则用所取数替代 A 中的数。程序流程如图 6,程序如下: 程序: ORG 2000H CLR AMOV R2,20HMOV R1,#22HLP:CLR CSUBB A,R1JNC NEXTMOV A, R1SJMP NEXT1NEXT: ADD A,R1NEXT1:INC R1DJNZ R2,LPMOV 21H
15、,ALP1: SJMP LP1 图 6 程序流程图 END开 始程 序 初 始 化=0、 ( 2H) R、 1C-( )?( ) A+( )?( )结 束 YN9第三节 分支程序设计方法1、分支结构的理论基础计算机具有逻辑判断能力,这是计算机实现分支程序的理论基础;条件转移指令和比较指令是计算机实现分支程序的具体体现;2、分支程序设计过程建立数学模型选择确定分支条件设计程序流程和用适当的语句设计程序3、分支程序设计方法1)、无条件转移程序设计这种程序转移方向是设计者事先安排的,它所使用的转移语句是无条件转移语句。例如:在系统诊断程序中,设置,当发生故障时,系统将无条件停机。2)、条件转移程序设
16、计方法它是根据执行程序对标志位或累加器或对内部 RAM 某位的影响结果,决定程序的走向、形成各种分支。在编写程序时要注意两点:选择适合的语句和安排可供判别的条件正确选定所用的转移条件和转移目标地址例如:警情从单片机的 P1.0 输入,当系统检测到有警情发生时,立即调用拨号子程序,试编制实现上述过程的程序。分析:设拨号程序为 TAB,主程序为 NAME,则程序如下、程序流程如图所示程序: ORG 1000HNAME:SETB P1. 0JNB NAMELJMP TABTAB: 开 始P1.置=?读 口程 序 转 移结 束10END3)、散转程序设计方法采用散转指令实现散转散转指令为:JMP A+
17、DPTR 图 7 程序流程图实现方法: 将要转移的地址在程序存储器中按照某种规律编一个表,以便使用散转指令 在转移地址处用 AJMP 或 LJMP 等指令转到相应的处理程序举例说明:根据 R7 的内容,转向各个操作程序;R7=0 转入 OPR0R7=1 转入 OPR1R7=N 转入 OPRN解;程序流程如图 8,程序如下: JUMP1:MOV DPTR,#JPTAB1MOV A,R7ADD A,R7JNC NOADINC DPHNOAD:JMP A+DPTRJPTAB1:AJMP OPR0AJMP OPR1AJMP OPRNEND 图 8 程序流程图 采用地址偏移实现散转如果偏移的地址在同一
18、256B 范转内,我们可以采用 MOVC A,A+DPTR 指令,先求出地址偏移量 A,然后再用 JMP A+DPTR 转移到转移入口。开 始置 DPTR初 值7*2有 进 位 吗 ?H加 1转 向 散 转 入 口转 向 处 理 程 序结 束 YN拟 设 置 的 转 移 表JMO453A011例如:根据 R7 中的内容转向 5 个操作程序。解程序如下:JUMP3:MOV A,R7MOV DPTR, #TAB3MOVC A,A+DPTRJMP A+DPTRTAB3:DB OPR0-TAB3DB OPR1-TAB3DB OPR2-TAB3DB OPR3-TAB3DB OPR4-TAB3DB OPR
19、5-TAB3OPR1:OPR1:OPR2:OPR5:采用转向地址实现散转若要转移的范围较大,可以先建一个双字节地址表,散转时先用查表方法获得表中的转向地址,然后将该地址装入数扭指针 DPTR 中,再令 A=0,最后用 JMP A+DPTR 实现散转。根据 R7 的内容转入各对应的操作程序中。解:设转移地址入口地址为 OPR0、OPR1、OPRN,散转程序如下:START:MOV DPTR,#LOOPMOV A,R7ADD A,R7 ;R72=AJNC NADD ;无进位则转移INC DPH ;有进位 DPH 加 112NADD:MOV R3, A ;暂存MOVC A,A+DPTR ;取地址高
20、8 位XCH A,R3 ;置转移地址高位INC AMOVC A,A+DPTR ;取地址低 8 位MOV DPL,AMOV DPH,R3CLR AJMP A+DPTRLOOP:DW OPR0DW OPR1DW OPRNEND利用 RET 指令实现散转在散转程序中,除了用 JMP,A+DPTR 指令实现散转外,还可以用 RET 指令实现。例如;上例中,在找到散转入口地址后,用 RET 指令实现散转。分析:设入口地址 DPTR 的地址已知,则可用:PUSH DPHPUSH DPLRET第四节 查表程序设计1、查表指令在 80C51 单片机汇编语言中有两条查表指令:MOVC A,A+DPTR;MOVC
21、 A,A+PC由于 PC 是不断改变的值,通常在查表指令中使用 MOVC A,A+DPTR 指令。132、变量的查表程序设计1)、单字节查表法在程序存储器表格中,每个存储单元是一个数据。例如:设计一个将十六进制转换成 ASC码的子程序,设十六进制数存放在 R0 中的低 4 位,要求将转换后的 ASC码送回 R0 中。分析:09 的 ASC为 30H39H;AHFH 的 ASC为 41H46H;表格设在程序存储器某一地址为首址的连续单元中存放 30H-46H;查表使用:MOVC A,A+DPTR。程序: ORG 2000HMOV A,R0ANL A,#0FHMOV A,#02HMOVC A,A+
22、DPTRMOV R0,ADB 30H,31H,32HEND2)、多字节查表法与单字节表格不一样,多字节表格的表格是多个字节构成,如,某学生的学年成绩是由多门功课成绩构成,在构成学生成绩表时,常常采用一个学生成绩放完后再放另一个学生的成绩,这样的表格的查询方法虽然仍使用 MOVC A,A+DPTR 指令进行查询,但偏移量 A 是按照某种规律变化的值。例如:上面讲的某班学生学年成绩表如图 9 所示:分析:怎样查学生成绩?这就要看题目要求什么?如统计语文的平均成绩:从表中可以看到语文 成绩在表中相隔四个字节,因此取 A 为 04H,采用:MOVC A,A+DPTR 学 生 1的 语 文 :数 学 :
23、化 学 :物 理 :学 生 2的 语 文 :数 学 :化 学 :物 理 :143、非规则变量的查表程序设计在现实生活中,有些表格并没有规律,如: ,x 与 y 并不是按直线规律变fy化而是存在某种对应关系,对这样的表格我们按:先建 X 表格:DB X 的高字节DB X 的低字节再建 Y 表格:DB Y 的高字节DB Y 的低字节找到 X 后就可查到 Y。因此这种表格往往要查两次:如 Y=SINX,这种题采用查表法解决。例如:单片机 80C51 控制系统中,输入参数 X 与输出 Y 的对应关系如下:X:0123H,0234H,085AH0AC4HY:24A7H,5678H,AC23HE345H共
24、存在 M 对对应关系,试编制一个查表程序;分析:表格的设置如下:DB 01H,23HDB 34H,0A7HDB 02H,34HDB 56H,78H即一个 X 值,紧跟一个 Y 值。为此程序的查表采用先取一个 X 值与表中的每一个X 值相比较,从而找到 X 值,再找 Y。程序如下(设 X 值放在 20H、21H 中,Y 值放在 22H、23H 中,表格未地址加 1 后放在 24H、25H):0RG 2100HMOV DPTR, #TABLP: CLR A图 9 学生成绩15MOVC A,A+DPTRCJNZ A,20H,LP1INC DPTRMOVC A,A+DPTRCJNE A,21H,LP2
25、INC DPTR MOVC A,A+DPTRMOV 22H,AINC DPTRMOVC A,A+DPTRMOV 23H,ARETLP1: INC DPTRLP2: INC DPTRINC DPTRINC DPTRMOV A,25HCJNE A,DPL,LPMOV A,24HCJNE A,DPH ,LPMOV A,#0FFHRETTAB:DB 01H,23HDB 34H,0A7HDB 02H,34HDB 56H,78H第五节 子程序设计161、定义在程序中反复用到的一段操作,将这一段程序独立编制供主程序调用,这这一段程序称为子程序。2、子程序设计方法1)、子程序的设计步骤确定子程序的名称,即其入
26、口处的标号确定子程序的入口参数及出口参数确定所使用的寄存器和存储器单元确定子程序的算法、编写源程序2)、子程序及其调用程序的设计子程序是满足某一功能的须要而设计的,因此子程序的设计方法与程序的设计方法基本相同,不同的地方是要在程序的开始部分明确子程序入口地址,即子程序名;在出口用 RET 返回指令。程序的设计中可以采用寄存器、寄存器间址、堆栈等作为主程序与子程序的数据传送方式。3、子程序嵌套子程序与主程序以及子程序与子程序之间的嵌套关系可用下图 10 表示:图 10 子程序嵌套示意图4、举例说明用程序实现 C=a2+b2。设 a、b 均为小于 10。A 存 31H 单元中,b 存 32H 单元
27、中,把结果 C 存入 33H 中单元。分析:依题意可以将某数的平方作为一个子程序,计算 C=a2+b2 只要两次调用子程主 程 序 子 程 序 1子 程 序17序即可,程序如下:ORG 2000HSTART:MOV SP,#3FH ;设堆栈针MOV A,31H ;取 a 值LCALL SQR ;计算 a2MOV R1,AMOV A,32H ;取 b 值LCALL SQR ADD A,R1MOV 33H,ASJMP ¥子程序:ORG 2400HSQR:INC AMOVC A,A+PCRET第六节 综合程序设计1、 编码转换程序设计1)、二进制数与 BCD 码的转换进制数转换成 BCD 码的方法单
28、字节的二进制数转换成 BCD 码采用除 100 得 BCD 码的百位,余数除 10 得十位,最终所得余数即个位。压缩的 BCD 码转化成二进制数的方法压缩 BCD 码即为一个字节中放有两个 BCD 码数,将压缩 BCD 码转化成二进制数的方法是将字节的高 4 位乘 10 再加上低 4 位即可。2)、ASC码与十六进制数的转换ASC码中的 30H-46H,对应十六进制数的 0-F,因此将 ASC码转化成十六18进制或者将十六进制数转化成 ASC码,只要在其中建立一种对应关系即可。例如:将 R0 单元中的 ASC码转换成十六进制数,并存于 R0 单元中。分析:对于小于 9 的数,其 ASC码减去
29、30H 得一位十六进制数;对于大于 9 的数,其 ASC码减去 37H,则恰好是 0AH-0FH。程序: ORG 2000HSTART:MOV A,R0CLR CSUBB A,#30HMOV R0,ASUBB A,#0AHJC SB2XCH A,R0SUBB A,#07HMOV R0, ASB2:RET3)、原码、反码、补码的转换方法原码、反码、补码的转换可采用定义进行,如负数的补码=反码加一。2、运算类程序设计1)、多字节加法程序设计方法多字节加法程序设计,采用低字节相加,再高字相加,高字节相加要考虑低字节相加的进位。2)、多字节减法程序设计方法多字节的减法程序设计,先进行低字节相减再高字节
30、相减。3)、多字节乘法程序设计方法理论依据:双字节数 abcd=(acH) (adH+bcH+acL) (bdH+adL+bcL) (bdL )占四个字节。19编程实现:只要按上式将每一部分计算出来就行,值得注意的事什么时候用带进位的加法,什么时候不用带进位的加法。4)、多字节除法程序设计方法双字节的除法采用余数左移一次后减除数,够减则上商,共进行 16 次,得到商的整数部分。所得余数要进行四舍五入,首先要判余数最高位是否为 1,若为 1,说明余数大于除数,商就加 1,否则余数有可能大于除数,在对余数乘以 2 后,减除数,若够减,则商加 1(五入) 。3、I/O 端口程序设计I/O 端口在作为通用 I/O 口使用时,可以用它来控制周围设备,如何用 I/O 端口控制外围的设备?下面具体谈几点:端口作为通用的 I/O 口使用时,P0 口要接 510K 的上拉电阻,其它口不要接(因为其它端口内部有上拉电阻) ;端口既可单独一位使用,也可整体使用;端口的负载能力是设计过程必需要考虑的;单片机与周围外部控制对象的隔离问题;程序设计时应先考虑各个口的分配;