《单片机原理与应用》-4_第1页
《单片机原理与应用》-4_第2页
《单片机原理与应用》-4_第3页
《单片机原理与应用》-4_第4页
《单片机原理与应用》-4_第5页
已阅读5页,还剩148页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第一章保持阳光心态67384.6运算程序设计

4.7代码转换程序设计思考与练习题上一页返回4.1汇编语言简介

计算机所能执行的每条指令都对应一组二进制代码。为了容易理解和记忆计算机的指令,人们用一些英语的单词和字符以及数字作为助记符来描述每一条指令的功能。用助记符描述的指令系统,称为机器的汇编语言系统,简称汇编语言。汇编语言也是面向机器的,每种计算机系统也都有它自己的汇编语言,用汇编语言编写的程序,称为汇编语言源程序或汇编源程序。下一页返回4.1汇编语言简介4.1.1汇编语言格式由操作助记符和操作数字段组成的汇编指令指能汇编成机器语言代码的指令。格式:操作码〔操作数1],〔操作数z],〔操作数3]

操作码:由2一5个英文字母组成的助记符。操作码后至少需要一个空格。操作数:操作数个数最多为3个,亦可没有操作数,操作数之间用逗号隔开。4.1.2汇编伪指令上一页下一页返回4.1汇编语言简介一、定位伪指令m:一般为十六进制数

m指出在该伪指令后的指令的汇编地址,即生成的机器指令起始存储器地址。显然,当使用多条“OR(}m”伪指令时,应注意其后生成的机器指令存放地址不应重叠【例4-1】ORG0START:SJMPMAINORG0BHLJMPPTFOORG40HMAIN:上一页下一页返回4.1汇编语言简介二、定义字节伪指令[标号:]DBX1、X2、…、Xn【例4-2】ORG1000HDB0AAHSR-DATA:DB25,25HDZX-DATA:DB'MCS-51'经汇编后,从地址1000H处存储器的内容为:(1000H)=AAH(1001H)=19H(1002H)=25H(1003H)=4DH上一页下一页返回4.1汇编语言简介(1004H)=43H(1005H)=53H(1006H)=2DH(1007H)=35H(1008H)=31H三、字定义伪指令[标号:]DWY1、Y2、…、Yn通知汇编程序从当前ROM地址开始,保留存储单元,并存入DW后面的数据。存放时高8位在前,低8位在。上一页下一页返回4.1汇编语言简介【例4-3】ORG1000HDW1234HSR_DATA:DW56H,2000经汇编后,从地址1000H处存储器的内容为:(1000H)=12H(1001H)=34H(1002H)=00H(1003H)=56H(1004H)=07H上一页下一页返回4.1汇编语言简介(1005H)=D0H四、EQU赋值伪指令字符名称EQU项(数或汇编符号)【例4-4】AAEQUR1MOVA,AAD10EQU10ADD_YEQU07ABHMOVA,D10LCALLADD_Y五、DS定义存储空间伪指令上一页下一页返回4.1汇编语言简介DS表达式在汇编时,从指定地址开始保留DS之后“表达式”的值所规定的存储单元。【例4-5】ORG1000HDS07HDB20H,20DW12H经汇编后,从地址1000H开始保留7个单元,然后从1007H处存储器的内容为:(1007H)=20H上一页下一页返回4.1汇编语言简介(1008H)=14H(1009H)=00H(100AH)=12H六、DATA数据地址赋值伪指令字符名称DATA表达式这里的“字符名称”与标号不同(其后没有冒号),但它是必须的,其功能是把“表达式”的值赋给左边的“字符名称”。DATA伪指令与EQU伪指令的主要区别是:EQU定义的“字符名称”必须先定义后使用,而DATA定义的“字符名称”没有这种限制,故DATA伪指令通常用在源程序的开头或末尾。上一页下一页返回4.1汇编语言简介【例4-6】ORG0100HAADATA35HDPTRADATA0AA00HMOVA,AA;(35H)→AMOVDPTR,#DPTRA;0AA00H→DPTR七、BIT定义位地址符号伪指令字符名称BIT位地址上一页下一页返回4.1汇编语言简介这里的“字符名称”与标号不同(其后没有冒号),但它是必须的,其功能是把BIT之后的“位地址”值赋给“字符名称”。【例4-7】P11BITP11A2BIT02HMOVC,P11MOVA2,C八、汇编结束伪指令END———指出汇编结束,其后即使还有指令,汇编程序也不作处理上一页返回4.2汇编语言程序设计简介一、汇编应用程序的设计步骤通常利用汇编语言设计一单片机系统,需要以下几个步骤:(1)拟定任务书。(2)建立数学模型。(3)建立算法。(4)绘制程序流程图。(5)编制汇编语言源程序。(6)上机调试。二、汇编程序结构设计的基本要求:下一页返回4.2汇编语言程序设计简介可靠性高、可读性好、效率高、占用存储容量小和执行速度快。三、汇编程序设计的基本结构①简单程序的设计;②分支程序设计;③循环程序设计;④子程序设计;⑤查表程序设计;⑥散转程序设上一页返回4.3简单和分支程序设计4.3.1简单程序设计简单程序:是指程序设计中没有使用转移类指令的程序段。也称顺序程序或直线程序。程序执行:按照指令存储位置的先后顺序依次执行,中间不会有任何分支程序、循环程序等。程序特点:结构简单,易于阅读理解,大量使用数据传送指令。【例4-8】请用51汇编指令编写程序,将外部RAM单元中40H单元4位BCD数转换成ASCII码,送到内部RAM单元60H~61H之中下一页返回4.3简单和分支程序设计分析:根据ASCII字符表,十进制数0~9的ASCII码和它的BCD码之间仅相差30H,本题需要把一个字节的两位BCD数进行拆分,然后分别和30H相加,即得到相应的ASCII码。参考设计程序如下:ORG1000HADDR1DATA0040HADDR2EQU60HMOVDPTR,#ADDR1;源地址=>DPTRMOVR0,#ADDR2;目标地址=>R0MOV@R0,#00H;目标地址单元清零上一页下一页返回4.3简单和分支程序设计MOVXA,@DPTR;源地址单元中BCD数送AMOVB,AANLA,#0FHORLA,#30H;完成低位BCD数转换MOV@R0,A;存入60HINCR0MOVA,BANLA,#0F0HSWAPA;高位BCD数送低4位ORLA,#30H;完成高位BCD数转换上一页下一页返回4.3简单和分支程序设计MOV@R0,A;存入61HSJMP$END4.3.2分支程序设计分支程序的特点是程序中含有转移指令。由于转移指令有无条件转移和条件转移之分,因此分支程序也可分为无条件分支程序和条件分支程序两类。无条件分支程序中含有无条件转移指令,因其比较简单,这里不作专门讨论;条件分支程序中含有条件转移指令,是我们讨论的重点上一页下一页返回4.3简单和分支程序设计条件分支程序体现了计算机执行程序时的分析判断能力。若某种条件满足,则机器就转移到另一分支上执行程序;若条件不满足,则机器就按原程序继续执行。MCS-51中,条件转移指令共有13条,分为累加器A判零条件转移、比较条件转移、减1条件转移和位控制条件转移等四类。【例4-9】已知VAR单元内有一自变量X,请按如下条件编出求函数值Y并将它存入FUNC单元的程上一页下一页返回4.3简单和分支程序设计

1,X>0Y=0,X=0-1,X<{0分析:这是一个三分支归一的条件转移问题,程序实现通常可分为“先分支后赋值”和“先赋值后分支”两种求解办法。现分述如下。(1)先分支后赋值。题意告诉我们,自变量X是个带符号数,可采用累加器判零条件转移和位控制条件转移指令来实现,程序流程如图4-1(a)所示上一页下一页返回4.3简单和分支程序设计参考设计程序如下:ORG1000HVARDATA30HFUNCDATA31HMOVA,VAR;X送AJZDONE;若X=0,则转DONEJNBACC7,POSI;若X>0,则转POSIMOVA,#0FFH;若X<0,则-1送ASJMPDONE;转DONEPOSI:MOVA,#01H;1送ADONE:MOVFUNC,A;存Y值上一页下一页返回4.3简单和分支程序设计SJMP$END(2)先赋值后分支。先把X调入累加器A,并判断它是否为零?若X=0,则A中内容送FUNC单:若X≠0,则先给R0赋值(如-1),然后判断A<0?若A<0,则R0送FUNC单元;若A>0,则把R0修改成1后送FUNC单元,程序流程如图4-1(b)所示上一页下一页返回4.3简单和分支程序设计参考设计程序如下:ORG1000HVARDATA30HFUNCDATA31HMOVR0,#00HMOVA,VAR;X送AJZDONE;若X=0,则转DONEMOVR0,#0FFH;若X≠0,则-1送R0JBACC7,DONE;若X<0,则转DONEMOVR0,#01H;若X>0,则1送R0上一页下一页返回4.3简单和分支程序设计DONE:MOVFUNC,R0;存Y值SJMP$END【例4-10】某系有200名学生参加外语统考,若成绩已存放在MCS-51外部RAM始地址为ENGLISH的连续存储单元,现决定给成绩在90~100分之间的学生颁发A级合格证书和成绩在80~89分之间学生颁发B级合格证书。试编制一个程序,可以统计A级和B级证书的学生人数,并把统计结果存入内部RAM的GRADA和GRADB单元。分析:这是一个循环和分支相结合程序,程序流程图如图4-2

所示。上一页下一页返回4.3简单和分支程序设计参考设计程序如下:ORG1000HENGLISHDATA2000HGRADADATA20HGRADBDATA21HMOVGRADA,#00H;GRADA单元清零MOVGRADB,#00H;GRADB单元清零MOVR2,#200;参考总人数送R2MOVDPTR,#ENGLISH;学生成绩始地址送DPTRLOOP:MOVXA,@DPTR;取某学生成绩到A上一页下一页返回4.3简单和分支程序设计CJNEA,#90,LOOP1;和90作比较,形成CYLOOP1:JNCNEXT1;若A>90,则NEXT1CJNEA,#80,LOOP2;和80作比较LOOP2:JCNEXT;A<80,NEXTINCGRADB;为B级,则GRADB单元内容加1SJMPNEXT上一页下一页返回4.3简单和分支程序设计NEXT1:INCGRADA;A>90,则GRADA单元内容加1NEXT:INCDPTR;修改学生成绩指针DJNZR2,LOOP;未完,则LOOPSJMP$;结束END上一页下一页返回4.3简单和分支程序设计4.3.3散转程序设计在利用MCS-51单片机指令设计汇编程序时,有时会遇到一类多分支程序的设计。分支转移的目标地址不是汇编或编程时确定的,而是在程序运行时动态决定的。MCS-51单片机提供了间接转移指令JMP@A+DPTR,恰好可以实现这一类转移。其中,DPTR装入多分支转移程序的首地址,用累加器A的内容来动态选择其中的某一个分支予以转移。这样一条指令可实现以DPTR内容为起始地址的256个字节范围的选择转上一页下一页返回4.3简单和分支程序设计【例4-11】已知通过调用键盘控制程序KEYREAD可将按下的按键键值0~15之一读到累加器A,要求编写程序对读入的不同键值,分别转入对应的键控程序段KEY0~KEY15执行。即要求:当(A)=0时,转键控处理程序KEY0;当(A)=1时,转键控处理程序KEY1;

……当(A)=15时,转键控处理程序KEY15。分析:对于上述要求的问题,可利用指令JMP@A+DPTR来实现,即我们通常所说的散转程序。参考设计程序如下:上一页下一页返回4.3简单和分支程序设计ORG1000HACALLKEYREAD;读键值程序RLA;调整MOVDPTR,#TABLE;表首址送DPTRJMP@A+DPTR;以A中内容为偏移量跳转……TABLE:AJMPK0;读入键为第1个键,转K0执行AJMPK1;读入键为第2个键,转K1执行上一页下一页返回4.3简单和分支程序设计AJMPK15;读入键为第16个键,转K15执行

……K0:[第1键处理程序段]K1:[第2键处理程序段]

……K15:[第16键处理程序段]虚线表示该处程序段省略,实际应用时,用户可根据实际需要加上特定功能的程序段。上一页返回4.4循环和查表程序设计4.4.1循环程序设计循环程序的特点是程序中含有可以重复执行的程序段,该程序段通常称为循环体。例如,求100个数的累加和是没有必要连续安排100条加法指令的,可以只用一条加法指令并使之循环执行100次。循环程序设计不仅可以大大缩短所编程序长度和使程序所占存储单元数最少,也能使程序结构紧凑和可读性变好。应注意循环程序设计并不能缩短完成任务的程序执行时间。循环程序的组成部分如下。(1)循环初始下一页返回4.4循环和查表程序设计循环初始化程序段位于循环程序开头,用于完成循环前的准备工作,例如:循环体中循环计数器和各工作寄存器设置初值,其中循环计数器用于控制循环次数。(2)循环处理。这部分程序位于循环体内,是循环程序的工作程序,需要重复执行。要求编写得尽可能简练,提高程序执行速度。(3)循环控制。循环控制程序也在循环体内,常常由修改循环计数器内容的语句和条件转移语句等组成,用于控制循环执行次数。(4)循环结束。上一页下一页返回4.4循环和查表程序设计这部分程序用于存放执行循环程序所得结果以及恢复各工作单元循环前的初值。【例4-12】已知内部RAM的BLOCK单元开始有一无符号数据块,块长在LEN单元。请编出求数据块中各数累加和、并存入SUM单元的程序。分析:为了使读者对两种循环结构有一个全面了解,以便进行分析比较,现给出两种设计方案。(1)先判断后处理,流程图见图4-3(a)。求累加和参考程序:ORG1000H上一页下一页返回4.4循环和查表程序设计LENDATA20HSUMDATA21HBLOCKDATA22HCLRA;A清零MOVR2,LEN;块长送R2MOVR1,#BLOCK;块始地址送R1INCR2;块长+1SJMPCHECKLOOP:ADDA,@R1;A+(R1)送AINCR1;修改数据块指针R1上一页下一页返回4.4循环和查表程序设计CHECK:DJNZR2,LOOP;若未完,则转LOOPMOVSUM,A;存累加和SJMP$END(2)先处理后判断,流程图见图4-3(b)。参考设计程序:上一页下一页返回4.4循环和查表程序设计ORG1000HLENDATA20HSUMDATA21HBLOCKDATA22HCLRA;A清零MOVR2,LEN;块长送R2MOVR1,#BLOCK;数据始地址送R1NEXT:ADDA,@R1;A+(R1)送AINCR1;修改数据块指针R1上一页下一页返回4.4循环和查表程序设计DJNZR2,NEXT;若未完,则转NEXTMOVSUM,A;存累加和SJMP$END上面的例题使用的是单重循环,循环程序中不包含其他的循环。实际应用中常常要用到多重循环,多重循环又称为循环嵌套,是指一个循环程序的循环体中包含另一个循环程序。理论上对循环嵌套的层数没有限制,但由于受硬件资源的制约,不可能嵌套太多的层数。需要注意的是循环嵌套只允许一个循环程序完全包含另一循环程序,不允许两个循环程序之间相互交叉嵌套。上一页下一页返回4.4循环和查表程序设计【例4-13】设单片机MCS-51内部RAM起始地址为30H的数据块中有64个无符号数。试编制一个程序能使它们按从小到大数据排列。分析:设有64个无符号数,在数据块中序号为:e1,e2,…,e63,e64,使它们按从小到大顺序排列的方法颇多。现以常见的冒泡排序法为例加以介绍。它先使e63和e64比较,若e64>e63,则两个存储单元中内容交换,反之就不交换;然后使e62和e63相比,按同样原则决定是否交换;一直比较下去;最后完成e1和e2比较及交换,经过N-1=63次比较(常用内循环63次来实现)后,e1位置上必然得到数组中的最大值,犹如一个气泡从水底冒到了水顶,如图4-4

(a)所上一页下一页返回4.4循环和查表程序设计第二次冒泡过程和第一次冒泡过程完全相同,比较次数也可以是63次(其实只需62次),冒泡后可以在e2位置上得到次最大值,如图4-4(b)所示。冒泡循环次数计算:(以64个数的排序为例)大循环(外循环)共63次;内循环:共63×63次。完成64个数的排序需要外循环63次、内循环3969次。第一次冒泡排序(比较5次):上一页下一页返回4.4循环和查表程序设计第二次冒泡排序(比较4次):第三次冒泡排序(比较3次),见图4-4(c):第四次冒泡排序(比较2次),见图4-4(d)。第五次冒泡排序(比较1次),见图4-4(e)。其实,64个无符号数的数组排序需要冒泡63次的机会是很少的,每次冒泡所需的数据比较次数,也是从63逐次减少(每冒一次泡减少一次比较)。上一页下一页返回4.4循环和查表程序设计为了禁止那些不必要的冒泡次数,人们常常设置一个“交换标志位”。“交换标志位”在循环初始化时清零,在数据交换时置位成1(表示冒泡中进行过数据交换)。“交换标志位”用来控制是否再需要冒泡。若“交换标志位”为1,则表明刚刚进行的冒泡中发生过数据交换(即排序尚未完成),应继续进行冒泡;若“交换标志位”为0,则表明刚进行完的冒泡中未发生过数据交换(即排序已完成),冒泡应该禁止。例如,对于一个已经排好序的数组:1,2,3,…,63,64,排序程序只要进行一次冒泡便可根据“交换标志位”状态而结束排序程序的再执行,这自然可以节省63-1=62次的冒泡时间。冒泡程序流程如图4-5

所示。上一页下一页返回4.4循环和查表程序设计参考设计程序如下:ORG1000HBUBBLE:MOVR0,#30H;置数据块指针R0MOVR2,#64;块长送R2CLR7FH;交换标志7FH清零DECR2;块长-1为比较次数BULOOP:MOV20H,@R0;e送20HMOVA,@R0;e送AINCR0上一页下一页返回4.4循环和查表程序设计MOV21H,@R0;e送21HCJNEA,21H,LOOP;(20H)和(21H)比较LOOP:JCBUNEXT;若(20H)<(21H),则BUNEXTMOV@R0,20H;若(20H)≥(21H),则两者交换DECR0MOV@R0,21HINCR0;恢复数块指针SETB7FH;置“1”交换标志上一页下一页返回4.4循环和查表程序设计BUNEXT:DJNZR2,BULOOP;若一次冒泡未完,则BULOOP;R2=0?JB7FH,BUBBLE;若交换标志位为1,则BUBBLESJMP$;结束END以上“冒泡”排序程序实现了将一组无序的数据从小到大的排列,请读者思考如何将一组无序数据完成从大到小的排列。【例4-14】编写软件延时100ms程序上一页下一页返回4.4循环和查表程序设计分析:在许多应用程序中都会用到延时程序,如:数码管动态显示、按键扫描、A/D转换等。设单片机的时钟频率为12MHz,则其机器周期为1μs,DJNZ指令需要两个机器周期,即2μs执行时间,MOVRn,#data指令需要1个机器周期,即1μs,NOP空操作指令也是1个机器周期1μs。为了延时100ms,我们通过双重循环来实现。执行两条NOP指令和1条DJNZR6,$指令为4个机器周期,即4μs,循环250次共用1000μs,即程序中第2条到第5条指令完成的延时功能。要完成100ms的延时,只需让1000μs的延时再循环100次便可。计算软件延时的时间可采用下面的公式:上一页下一页返回4.4循环和查表程序设计{[(1+1+2)250+1+2]*100+1+2}1μs=100303μs≈100ms参考设计程序为:D100MS:MOVR7,#200;1机器周期指令D100MS1:MOVR6,#250D100MS2:NOP;1机器周期指令NOPDJNZR6,D100MS2;2机器周期指令上一页下一页返回4.4循环和查表程序设计DJNZR7,D100MS1RET以上例题所涉及的循环都是有条件的循环,循环体程序段是在一定条件下执行的,当条件不满足的时候便退出循环。然而大部分的嵌入式单片机系统都是无限循环地执行指定的程序。【例4-15】80C51单片机的P1口作输出,接8只发光二极管,如图4-6所示。当输出位是“1”,发光二极管被点亮;输出位为“0”,发光二极管熄灭。编制单灯循环点亮程上一页下一页返回4.4循环和查表程序设计ORG0000HMOVA,#01H;送初始值,点亮第一个发光二极管LOOP:MOVP1,AACALLY1S;调用1延时子程序RLA;累加器A左移1位SJMPLOOPY1S:;延时约1s子程序MOVR5,#5Y1S1:MOVR6,#200上一页下一页返回4.4循环和查表程序设计Y1S2:MOVR7,#200Y1S3:DJNZR7,Y1S3DJNZR6,Y1S2DJNZR5,Y1S1RET上一页下一页返回4.4循环和查表程序设计4.4.2查表程序设计查表是根据存放在ROM中数据表格的项数来查找和它对应的表中值。方法简便,可缩短程序长度和提高程序执行效率。注意:MOVCA,@A+DPTR指令可以实现64KB地址范围内的数据查寻,而MOVCA,@A+PC指令只能实现256字节范围内的数据查寻。【例4-16】已知BLOCK1为起始地址的数据块(数据块长度在LEN单元),数块中每个存储单元中的高、低4位分别为两个十六进制数,请编程把它们转换为相应ASCII码,并存放在BLOCK2开始的连续存储单元(低4位ASCII码在前,高4位ASCII码在上一页下一页返回4.4循环和查表程序设计分析:由于每个存储单元中放有两个十六进制数,因此每个存储单元中十六进制数应分别转换成ASCII码。这就需要两次使用查表指令MOVCA,@A+PC,这两条查表指令在程序中位置是不相同的,故两次对PC调整的值也不相同。在编程时,可以先把整个程序编完,然后再计算两条加法指令中的data修正值并填入相应位置。参考设计程序如上一页下一页返回4.4循环和查表程序设计ORG1000HLENDATA30HBLOCK1DATA31HBLOCK2DATA51HMOVR0,#BLOCK1;BLOCK1送R0MOVR1,#BLOCK2;BLOCK2送R1LOOP:MOVA,@R0;取源数据块中数ANLA,#0FH;取出低4位ADDA,#17;第一次地址调整上一页下一页返回4.4循环和查表程序设计MOVCA,@A+PC;第一次查表MOV@R1,A;存第一次转换结果MOVA,@R0;重新取出被转换数SWAPA;高4位调入低4位ANLA,#0FH;取出低4位ADDA,#09;第二次地址调整MOVCA,@A+PC;第二次查表INCR1;修改目的数据块指针MOV@R1,A;存第二次转换结果INCR0;修改源数据块指针上一页下一页返回4.4循环和查表程序设计INCR1;修改目的数据块指针DJNZLEN,LOOP;若未转换完,则转LOOPSJMP$ASCTAB:DB‘0’,‘1’,‘2’,‘3’,‘4’DB‘5’,‘6’,‘7’,‘8’,‘9’DB‘A’,‘B’,‘C’,‘D’,‘E’,‘F’END上一页下一页返回4.4循环和查表程序设计【例4-17】设有一巡回检测报警装置,需对16路输入量进行测量控制,每路有一个最大允许值。控制时根据测量的路数,找出该路的最大允许值。测量的路数保存在R2中,最大值结果保存在R3R4中。LTB:MOVA,R2ADDA,R2MOVR3,AMOVDPTR,#MAX;获取表格数据的首地址MOVCA,@A+DPTR上一页下一页返回4.4循环和查表程序设计XCHA,R3INCAMOVCA,@A+DPTRMOVR4,ARETMAX:;定义字数据DW1520,3721,445,7850DW3483,32657,883,9943DW1101,40511,6756,331DW4468,5871,13224,9981上一页下一页返回4.4循环和查表程序设计【例4-18】在ROM表格中存放着若干个按增序排列的单字节数据,数据个数存放在R7中,表格的首地址存放在DPTR中,要求查找一个存放于A中的数据,若查找到数据,则OV=0,顺序号存放于A中;未找到数据则OV=1。分析:数据查找就是将要查找的数据与表格中的数据进行比照。如果数据个数少,通常采用逐个查找的方法,直至最后一个数。当数据个数较多时,若仍然采用逐个比较的算法,速度较慢,这时往往采用更加优化的算法,如对分查找,可大大提高查找效率,下面分别给出两种查找方法的参考程序。顺序查找参考程:上一页下一页返回4.4循环和查表程序设计;标号:FDS1;功能:顺序查找(ROM)单字节表格;入口条件:查找的内容在A中,表格首址在DPTR中,表格的字节数在R7中。;出口信息:OV=0时,顺序号在累加器A中;OV=1时,未找;影响资源:PSW、A、B、R2、R6;堆栈需求:2字节FDS1:MOVB,A;保存待查找的内容MOVR2,#0;顺序号初始化(指向表首)MOVA,R7;保存表格的长度MOVR6,A上一页下一页返回4.4循环和查表程序设计FD11:MOVA,R2;按顺序号读取表格内容MOVCA,@A+DPTRCJNEA,B,FD12;与待查找的内容比较CLROV;相同,查找成功MOVA,R2;取对应的顺序号RETFD12:INCR2;指向表格中的下一个内容DJNZR6,FD11;查完全部表格内容SETBOV;未查找到,失上一页下一页返回4.4循环和查表程序设计RET对分查找参考程序:;标号:FDD1;功能:对分查找(ROM)单字节无符号增序数据表格;入口条件:查找的内容在累加器A中,表格首址在DPTR中,字节数在R7中。;出口信息:OV=0时,顺序号在累加器A中;OV=1时,未找到。;影响资源:PSW、A、B、R2、R3、R4;堆栈需求:2字节FDD1:MOVB,A;保存待查找的内容上一页下一页返回4.4循环和查表程序设计MOVR2,#0;区间低端指针初始化(指向第一个数据)MOVA,R7DECAMOVR3,A;区间高端指针初始化(指向最后一个数FD61:CLRC;判断区间大小MOVA,R3SUBBA,R2JNZFD64;区间消失,查找失败MOVA,R3;到了边界。判断是否与边界值相等上一页下一页返回4.4循环和查表程序设计MOVCA,@A+DPTRCJNEA,B,FD69MOVA,R3CLROVRETFD64:RRCA;取区间大小的一半ADDA,R2;加上区间的低端MOVR4,A;得到区间的中心MOVCA,@A+DPTR;读取该点的内容上一页下一页返回4.4循环和查表程序设计CJNEA,B,FD65;与待查找的内容比较CLROV;相同,查找成功MOVA,R4;取顺序号RETFD65:JCFD68;该点的内容比待查找的内容大否?MOVA,R4;偏大,取该点位置DECA;减1MOVR3,A;作为新的区间高端SJMPFD61;继续查找FD68:上一页下一页返回4.4循环和查表程序设计MOVA,R4;偏小,取该点位置INCA;加一MOVR2,A;作为新的区间低端SJMPFD61;继续查找FD69:SETBOVRET上一页返回4.5子程序设计子程序是指完成确定任务并能为其他程序反复调用的程序段。调用子程序的程序叫做主程序或称调用程序。只要在主程序中安排程序的主要线索,在需要调用某个子程序时采用LCALL或ACALL调用指令,便可从主程序转入相应子程序执行,CPU执行到子程序末尾的RET返回指令,即可从子程序返回主程序断点处执行。在工程上,几乎所有实用程序都是由许多子程序构成的。子程序可以构成子程序库,集中存放在某一存储空间,任凭主程序随时调用。采用子程序设计能使整个程序结构简单,缩短程序设计时间,减少对存储空间的占用。下一页返回4.5子程序设计如果某一实用程序需要10次调用某一子程序,那么只要在主程序相应地安排10条调用指令就可以避免把同一子程序编写10遍,内存空间几乎可以减少倍子程序的长度。主程序和子程序是相对的,没有主程序也不会有子程序。同一程序既可以作为另一程序的子程序,也可以有自己的子程序。即子程序是允许嵌套的,嵌套深度和堆栈区的大小有关。总之,子程序是一种能完成某一专用任务的程序段,其资源需要为所有调用程序共享,因此,子程序在结构上应具有通用性和独立性,在编写子程序时应注意以下问题。上一页下一页返回4.5子程序设计(1)子程序的第一条指令地址称为子程序的始地址或入口地址。该指令前必须有标号,标号应以子程序任务定名,以便一看就一目了然。例如:延时程序常以DELAY作为标号。(2)主程序调用子程序是通过安排在主程序中的调用指令实现的,子程序返回主程序一般执行安排在子程序末尾的一条RET返回指令。(3)主程序调用子程序和从子程序返回主程序,计算机能自动保护和恢复主程序的断点地址。但对于各工作寄存器、特殊功能寄存器和内存单元中内容,如果需要保护和恢复,就必须在子程序开头和末尾(RET指令前)安排一些能够保护和恢复它们的指令。上一页下一页返回4.5子程序设计(4)为使所编子程序可以放在64KB内存的任何区域并能为主程序调用,子程序内部一般使用相对转移指令而不使用其他转移指令,以便汇编时生成浮动代码。(5)子程序参数可以分为入口和出口参数两类:入口参数是指子程序需要的原始数,由调用它的主程序通过约定的工作寄存器R0~R7、特殊功能寄存器SFR、内存单元或堆栈等预先传送给子程序使用;出口参数是由子程序根据入口参数执行程序后获得的结果参数,应由子程序通过约定的R0~R7、SFR、内存单元或堆栈等传递给主程序使用。子程序传送参数的方法通常有以下几种。上一页下一页返回4.5子程序设计(1)利用寄存器或片内RAM传送子程序参数。对于某些简单子程序、入口参数和出口参数通常较少。常可采用本传送参数的方式。例如:CPU可以预先在主程序中把乘数和被乘数送入R0~R7,转入乘法子程序执行后得到的乘积也可通过R0~R7传送给主程序。(2)利用寄存器传送子程序参数的地址。如果上述方法不太方便,CPU也可在主程序中把子程序入口参数地址通过R0~R7传送给子程序,子程序根据R0~R7中入口参数地址便可找到入口参数并对它们进行相应的操作,操作得到的出口参数也可把它们的地址通过寄存器R0~R7传送给主程序。上一页下一页返回4.5子程序设计(3)利用堆栈传送子程序参数。任何符合先进后出或后进先出原则的片内RAM区都可称为堆栈。堆栈中数据的存取是由堆栈指针SP指示的。因此,堆栈也可用来传送子程序参数。例如:CPU可以通过主程序中的PUSH指令把入口参数压入堆栈传送给子程序,子程序的出口参数也可通过堆栈传送给主程序。(4)利用位地址传送子程序参数。如果子程序的入口参数是字节中的某些位,那么利用本方法传送入口和出口参数也有方便之处,传送参数过程和上述诸方法类似。子程序参数的上述传递方法也适用于中断服务程序的编制。上一页下一页返回4.5子程序设计【例4-19】设MDA和MDB内有两个数据a和b,请编制出求c=a2+b2并把c送入MDC的程序,设a和b皆为小于10的整数。分析:本程序由两部分组成:主程序和子程序。主程序通过累加器A传送子程序的入口参数a或b,子程序也通过累加器A传送出口参数a或b给主程序,子程序为求一个数的平方的通用子程序。ORG1000HMDADATA20H上一页下一页返回4.5子程序设计MDBDATA21HMDCDATA22HMOVA,MDA;入口参数a送AACALLSQR;求a2MOVR1,A;a2送R1MOVA,MDB;入口参数b送AACALLSQR;求b2ADDA,R1;a2+b2送AMOVMDC,A;存入MDCSJMP$;结束上一页下一页返回4.5子程序设计SQR:ADDA,#01H;地址调整MOVCA,@A+PC;查平方表RET;返回SQRTAB:DB0,1,4,9,16DB25,36,49,64,81END上述程序采用了查表法求一个数的平方,并且通过子程序调用实现了两个数的平方求和,值得注意的是,上述程序仅适应两个数比较小,两个数的平方和不大于用一个字节的数据表示。上一页下一页返回4.5子程序设计【例4-20】已知片内RAM中有一个5位BCD码(高位在前,低位在后),最大不超过65535,始地址在R0中,BCD码位数减1(04H)已在R2中,请编出把BCD码转换为二进制整数并存入R4R3中(R4中内容为高8位)中的程序。分析:本题只给出子程序,主程序从略。编写好的子程序可供其他汇编程序调用,调用时需要注意入口参数和出口参数,利用子程序的功能容易实现整个程序的模块化设计。利用汇编语言完成将BCD码转换为十六进制数,需利用到十进制与十六进制之间的关系,采用合理的算法。算法公式如下:上一页下一页返回4.5子程序设计y=a4×104+a3×103+a2×102+a1×101+a0×100=(((((a4×10)+a3)×10)+a2)×10+a1)×10+a0程序流程图如图4-7

所示:通用参考子程序:标号:BCDB功能:将五位BCD码转换为十六进制数入口参数:BCD字节地址指针R0,指数幂R2中出口参数:AY值应存于R4R3中(R3中为高字节上一页下一页返回4.5子程序设计ORG1000HBCDB:PUSHPSW;保护现场PUSHACCPUSHBDECR2;BCD码的位数减1MOVR3,#00H;R3清零MOVA,@R0MOVR4,A;万位BCD码送R4LOOP:MOVA,R4;R4送上一页下一页返回4.5子程序设计MOVB,#10MULAB;A×10送BAMOVR4,A;R4×10低位送R4MOVA,#10XCHA,BXCHA,R3;R4×10高位送R3MULAB;R3×10ADDA,R3XCHA,R4INCR0ADDA,@R0上一页下一页返回4.5子程序设计XCHA,R4ADDCA,#00HMOVR3,A;完成R3R4R3R4+(R0)DJNZR2,LOOP;若未完,则转LOOP执行。POPB;恢复现场POPACCPOPPSWRET;返回我们在编写某些具有一定通用性的子程序时,往往采用上例的方法,注明程序的标号、功能、入口参数和出口参数,这样即便是他人,也能够较方便地利用该子程序,实现软件资源的共享。上一页返回4.6运算程序设计运算程序可分为浮点数运算程序和定点数运算程序两大类。浮点数就是小数点不固定的数,其运算通常比较麻烦,常由阶码运算和数值运算两部分组成;定点数就是小数点固定的数,通常包括整数、小数和混合小数等,其运算比较简单,但在数位相同时定点数的表示范围比浮点数的小。以下只介绍定点数运算程序设计,若无特别说明,则所有程序均指定点数运算程序。下一页返回4.6运算程序设计4.6.1加减运算程序设计多字节加、减运算是应用程序设计中经常要进行的一种运算,加、减运算程序可以分为无符号多字节数加减运算和带符号多字节数加减运算程序两种。一、无符号多字节加减运算程序无符号多字节加法运算程序的编制已在前面作过介绍,现以多字节减法程序为例加以介绍。【例4-21】已知BLOCK1和BLOCK2为起始地址的存储区中分别有N个字节的无符号被减数和减数(高位在前,低位在后)。请编制一个减法子程序,令它们相减,并把差值放入BLOCK1为起始地址的存储单元。上一页下一页返回4.6运算程序设计分析:用减法指令从低字节开始相减。相应程序为:ORG1000HSBYTESUB:MOVR0,#BLOCK1;被减数始址送R0MOVR1,#BLOCK2;减数始址送R1MOVR2,#N;字长送R2,MOVA,R2ADDA,R0DECAMOVR0,AMOVA,R1上一页下一页返回4.6运算程序设计ADDA,R1DECAMOVR1,ACLRC;CY清零,LOOP:MOVA,@R0;被减数送ASUBBA,@R1;相减MOV@R0,A;存差INCR0;修改被减数地址指针INCR1;修改减数地址指针DJNZR2,LOOP;若未完,则LOOP上一页下一页返回4.6运算程序设计RETEND二、带符号单字节加减运算程序带符号单字节加减运算程序和无符号加减运算程序类似,只是符号位处理上有所差别。【例4-22】设在BLOCK和BLOCK+1单元中有两个补码形式的带符号数。请编出求两数之和,并把它放在SUM和SUM+1单元(高8位在SUM单元)的子程序。上一页下一页返回4.6运算程序设计分析:在两个8位二进制带符号数相加时,其和很可能会超过8位数能表示的范围而需要采用16位数形式来表示,因此,在进行加法时,可以预先把这两个加数扩张成16位二进制补码形式,然后对它完成双字节相加。例如:加数和被加数皆为-98(补码为9EH)时,扩张成16位二进制形式后相加的算式为:-981111111110011110B+-981111111110011110B-1961111111100111100B最高进位位丢失不计,换算成真值显然也是-196,结果是正确。上一页下一页返回4.6运算程序设计因此,一个8位二进制正数扩张成16位时只要把它的高8位变成全“0”,一个8位二进制负数扩张成16位时需要把它的高8位变成全“1”。据此,我们在编程时应在加减运算前先对加数和被加数进行扩张,然后完成求和。设R2和R3分别用来存放被加数和加数高8位,则相应程序为:ORG1000HSBADD:PUSHACCPUSHPSW;保护现场MOVPSW,#00H上一页下一页返回4.6运算程序设计MOVR0,#BLOCK;R0指向一个加数MOVR1,#SUM+1;R1指向和单MOVR2,#00H;高位先令其为零MOVR3,#00HMOVA,@R0;一个加数JNBACC7,POS1;若为正数,则转POS1MOVR2,#0FFH;若为负数,则全“1”送R2POS1:INCR0;R0指向下一个加数MOVB,@R0;取第二加数到BJNBB7,POS2;若是正数,则转POS2上一页下一页返回4.6运算程序设计MOVR3,#0FFH;若是负数,则全“1”送R3POS2:ADDA,B;低8位相加MOV@R1,A;存低8位和DECR1;R1指向SUM单元MOVA,R2ADDCA,R3;完成高8位求和MOV@R1,A;存高8位和POPPSW;恢复现场POPACCRET上一页下一页返回4.6运算程序设计END在上述程序中,入口:被加数存放在BLOCK,加数存放在BLOCK+1;出口:和的低字节存放在SUM+1,和的高字节存放在SUM。参数传递是利用BLOCK、BLOCK+1、SUM和SUM+1单元实现的。根据本程序,读者编出带符号8位数减法子程序并不困难。三、多字节十进制数BCD码减法由于MCS-51指令系统中只有十进制加法调整指令“DAA”,也即该指令只有在加法指令(ADD、ADDC)后,才能得到正确的结果。为了用十进制加法调整指令对十进制减法进行调整,必须采用补码相加的办法,用9AH减去减数即得到以十为模的减数的补码。上一页下一页返回4.6运算程序设计【例4-23】多字节十进制BCD码减法。被减数低字节地址在R1,减数低字节地址在R0,字节数在R2。分析:因为51单片机只有十进制加法调整指令“DAA”,为了实现十进制BCD码的减法,需要将减法转化为加法,转换的方法就是利用十进制的补码。参考设计程序如下:;标号:SBCD;功能:实现BCD码的减法;入口:被减数低字节地址在R1,减数低字节地址在R0,字节数在R2。;出口:差(补码)的低字节地址在R0,字节数在R3,07H为符号位,“0”为正,“1”为负。上一页下一页返回4.6运算程序设计SBCD:MOVR3,#00H;差字节数置0CLR07H;符号位清0CLRC;借位位清0CLRF0SBCD1:MOVA,#9AH;减数对100求补码SUBBA,@R0MOVC,F0ADDA,@R1;补码相加DAA;十进制相加调整上一页下一页返回4.6运算程序设计MOV@R0,A;存结果INCR0;地址值增加1INCR1INCR3;差字节增加1MOVF0,CSETBC;进位位求反,以形成正确的借位DJNZR2,SBCD1;未减完,转SBCD1,继续JNCSBCD2;无借位,转SBCD2SETB07H;有借位,置“1”符号位SBCD2:RET;返回主程序上一页下一页返回4.6运算程序设计END程序中,减数求补后与被减数相加,方可利用“DAA”指令进行调整,若二者相加调整后结果无进位C=0,实际上表示二者相减有借位;若二者相加调整后结果有进位C=1,实际上表示二者相减无借位。为了正确反映其借位情况,必须对其进位标志位C进行求反操作。上一页下一页返回4.6运算程序设计一、无符号多字节乘法运算程序【例4-24】16位无符号数乘法程序。已知BLOCK1和BLOCK2开始的存储单元内存放有16位乘数和被乘数(高字节在前,低字节在后)。试编程求积并把积放入BLOCK3开始的连续四个存储单元(高字节在前,低字节在后)。分析:MCS-51乘法指令只能完成两个8位无符号数相乘,因此16位无符号数求积必须将它们分解成四个8位数相乘来实现。其方法有先乘后加和边乘边加两种,现以边乘边加进行分析。边乘边加的乘法原理和过程如图4-8所示。图中:ab为16位被乘数(a为高8位,b为低8位)、cd为16位乘数(c为高8图4-8边乘边加16位乘法法则示意图位,d为低8位)。上一页下一页返回4.6运算程序设计第一次乘法完成b×d,其积为bdH和bdL(bdH为高8位,bdL为低8位);第二次乘法完成a×d,其积为adH和adL(adH为高8位,adL为低8位);同理可以得到的三次和第四次乘积bcH、bcL和acH、acL,其中bcH和acH分别为高8位。ab×cd的积共为4字节,分别存放在R0为起始地址的连续4个内存单元。参考设计程序如下:(1)主程序。ORG1000H上一页下一页返回4.6运算程序设计MOVR4,BLOCK1+1MOVR5,BLOCK1;乘数送R5R4MOVR6,BLOCK2+1MOVR7,BLOCK2;被乘数送R7R6MOVR0,#BLOCK3+3;R0指向积单元始址ACALLMLTY;转入乘法子程序

……(2)乘法子程序。入口参数:R7R6存放被乘数R5R4存放乘数,R0存放积单元起始地址MLTY:上一页下一页返回4.6运算程序设计MOVA,R6MOVB,R4MULAB;b×d=BAMOV@R0,A;bdL送(R0)MOVR3,B;bdH送R3MOVA,R7MOVB,R4MULAB;a×d=BAADDA,R3;加法形成CYMOVR3,A;bdH+adL送R3上一页下一页返回4.6运算程序设计MOVA,BADDCA,#00HMOVR2,A;adH+CY送R2MOVA,R6MOVB,R5MULAB;b×c=BAADDA,R3DECR0MOV@R0,A;R3+bcL送(R0+1)MOVA,R2ADDCA,B;加法,并形成CY上一页下一页返回4.6运算程序设计MOVR2,A;R2+bcH+CY送R2MOVR1,#00HJNCNXET;若CY=0,则NEXTINCR1;若CY=1,则存R1NEXT:MOVA,R7MOVB,R5MULAB;a×c=BADDA,R2DECR0MOV@R0,A;R2+acL送(R0+2)上一页下一页返回4.6运算程序设计MOVA,BADDCA,R1DECR0MOV@R0,A;R1+acH+CY送(R0+3)RET;返回主程序END二、带符号多字节乘法运算程序带符号多字节乘除法运算程序和无符号多字节乘除法运算程序类似,只是符号位应单独处理。为了简便起见,以8位带符号乘法运算程序为例说明符号处理的运算规。上一页下一页返回4.6运算程序设计【例4-25】设R0和R1中有两个补码形式的带符号数,试编写出求两数之积并把积送入R2R3(R2内为积的高8位)中的程序。分析:MCS-51乘法指令是对两个无符号数求积的。若要对两个带符号数求积,则可采用对符号位单独处理的办法。相应处理步骤如下。(1)单独处理被乘数和乘数的符号位。办法是单独取出被乘数符号位并和乘数符号位进行异或操作,因积的符号位的产生规则是同号相乘为正和异号相乘为负。(2)求被乘数和乘数的绝对值,并使两绝对值相乘而获得积的绝对值。方法是分别判断被乘数和乘数的符号位:若它为正,则其本身就是绝对值;若它为负,则对它求补。上一页下一页返回4.6运算程序设计(3)对积进行处理。若积为正,则对积不作处理;若它为负,则对积求补,使之变为补码形式。参考程序如下:ORG1000HSBITBIT20H0SBIT1BIT20H1SBIT2BIT20H2MOVA,R0;被乘数送ARLCA;被乘数符号送CYMOVSBIT1,C;送入SBIT1上一页下一页返回4.6运算程序设计MOVA,R1;乘数送ARLCA;乘数符号送CYMOVSBIT2,C;送入SBIT2XRLC,/SBIT1;SBIT1SBIT2送CYMOVSBIT,C;送入SBITMOVA,R0;处理被乘数JNBSBIT1,NCH1;若它为正,则转NCH1CPLA;若它为负,则求补得绝对值INCANCH1:MOVB,A;被乘数绝对值送B上一页下一页返回4.6运算程序设计MOVA,R1;处理乘数JNBSBIT2,NCH2;若它为正,则转NCH2CPLA;若它为负,则求补得绝对值ADDA,#01HNCH2:MULAB;求积的绝对值JNBSBIT,NCH3;若它为正,则转NCH3CPLA;若它为负,则低字节求补ADDA,#01HNCH3:MOVR2,A;积的低字节存入R2MOVA,B;积的高字节送AJNBSBIT,NCH4;若它为正,则转NCH4上一页下一页返回4.6运算程序设计CPLA;若它为负,则高字节求补ADDCA,#00HNCH4:MOVR3,A;积的高字节存入R3SJMP$;结束END应当注意:对积的低字节求补时使用了ADD加法指令,之所以没有用INC指令是因为INC指令执行时不会影响CY标志。这种对带符号数的处理方法,不仅可以用作单字节的乘法和除法,而且对多字节的乘法和除法也是实用的。上一页下一页返回4.6运算程序设计三、多字节除法运算程序【例4-26】设32位长的被除数已放在R5R4R3R2(R5内为最高字节),16位除数存放在R7R6,请编出使商存于R3R2和余数存于R5R4的除法程序。该程序应能判定除数为零时转入ERR出错处理程序和商超过双字节时使PSW中F0=1(否则F0=0)。执行前:被除数为R5R4R3R2,除数为R7R6。除法执行后:商为R3R2,余数为R5R4。除法运算的法则可采用重复减法,比较除法程序框图如图4-9所示,相应算法步骤如下。(1)判断除数是否为零。若除数为零,则转出错处理程序ERR执行。上一页下一页返回4.6运算程序设计(2)若除数不为零,则判断商是否大于双字节,即判断R5R4≥R7R6?若R5R4≥R7R6,则商大于双字节,使F0=1和结束除法运算。(3)若R5R4<R7R6,则采用重复比较法求商。由于是16位除法,故比较法求商时比较次数16送B寄存器,以控制除法的循环次数。(4)使32位被除数R5R4R3R2左移一位,即扩大两倍,R2最低位空出。(5)使被除数高16位减去除数。若够减,则在R2最低位上商“1”(即除法完成后R3R2内可得到商,R5R4内得到余数);若不够减,则R2最低位上商“0”。上一页下一页返回4.6运算程序设计(6)判断除法是否完成(B=0)?若未完成,则重复执行第四步;若已完成,则令F0=0,然后结束除法运算。双字节无符号除法程序流程图如图4-10所示参考程序如下:ORG1000HNSDIV:MOVA,R6;除数低8位送AJNZSTART;若除数≠0,则STARTMOVA,R7;除数高8位送上一页下一页返回4.6运算程序设计JZERR;若除数=0,则转ERRSTART:MOVA,R4;R4送ACLRC;CY清零SUBBA,R6;R4-R6送A,形成CY…MOVA,R5;R5送ASUBBA,R7;R5-R7-CY送A,形成CYJNCLOOP4;若R5R4≥R7R6,则LOOP4(溢出)MOVB,#16;否则,准备做除法上一页下一页返回4.6运算程序设计LOOP1:CLRC;CY清零MOVA,R2;R2送ARLCA;左移一位,低位补零MOVR2,A;送回R2MOVA,R3;R3送ARLCA;左移一位MOVR3,A;送回R3MOVA,R4;R4送ARLCA;左移一位MOVR4,A;送回R4上一页下一页返回4.6运算程序设计XCHA,R5;R5进入A,R5保存R4移位后的内容RLCA;左移一位XCHA,R5;送回R5,A中保存R4移位后的内容MOVPSW5,C;被除数最高位送F0CLRC;CY清零SUBBA,R6;R4-R6MOVR1,A;送R1保存MOVA,R5;R5送ASUBBA,R7;R5-R7-CY送AJBPSW5,LOOP2;若够减(F0=1),则LOOP2上一页下一页返回4.6运算程序设计JCLOOP3;若不够减,则LOOP3LOOP2:MOVR5,A;余数高字节送R5MOVA,R1;余数低字节送AMOVR4,A;存入R4INCR2;商末位加1LOOP3:DJNZB,LOOP1;若除法未完,则LOOP1CLRPSW5;若除法完成,则F0清零DONE:上一页下一页返回4.6运算程序设计RET;返回主程序LOOP4:SETBPSW5;令F0=1SJMPDONE;转入DONEERR:;出错处理程序END上述子程序中,我们省略了累加器A、B寄存器、PSW和R1中内容的保护和恢复语句。在实际编程中,若需要的话可根据实际情况添补。上一页返回4.7代码转换程序设计代码转换是计算机程序中经常遇到的一种数据处理过程,下面介绍几种常见的代码转换程序,供使用时参考。一、4位二进制转换为ASCII代码从ASCII编码表可知,若4位二进制数小于10,则此二进制数加上30H即变为相应的ASCII码,若大于10,则应加上37H方可。由于该过程比较简单,所以下面直接给出转换子程序。入口:R2存放转换前4位二进制数出口:R2存放转换后的ASCII码ORG1000HASCB1:MOVA,R2ANLA,#0FH;取出四位二进制数下一页返回4.7代码转换程序设计PUSHA;压入堆栈CLRCSUBBA,#0AH;与数10比较POPAJCLOOP;小于10,则转LOOP执行ADDA,#07H;否则,该数加7LOOP:ADDA,#30H;加30H,转换为ASCII码MOVR2,A;保存结果,结果存于R2RET;返回上一页下一页返回4.7代码转换程序设计二、ASCII码转换为四位二进制数这是上述转换的逆过程,程序如下:入口:转换前ASCII码送R2。出口:转换后的二进制数存于R2。ORG1000HBCDB1:MOVA,R2SUBBA,30H;ASCII码减30HMOVR2,A;二进制数据保存于R2SUBBA,#0AH上一页下一页返回4.7代码转换程序设计JCLOOP;若该数<10,返回主程序MOVA,R2;若该数≥10,再减7SUBBA,07HMOVR2,A;所得二进制数送R2LOOP:RET;返回主程序上一页下一页返回4.7代码转换程序设计三、BCD码转换为二进制码子程序设有用BCD码表示的4位十进制数分别存放于R1、R2中,其中R2存千位和百位数,R1存十位和个位数,要把其转换为纯二进制码,可用由高位到低位逐位检查BCD码的数值,然后累加各十进制位对应的二进制数来实现。其中1000D=03E8H,100D=0064H,10=000AH(各位数的BCD码与二进制码相同)。子程序如下:入口:待转换的BCD码存于R1、R2中,分配如下:低位字节十位数个位数R1上一页下一页返回4.7代码转换程序设计高位字节千位数百位数R2出口:结果存在20H、21H单元中,其中21H存低字节,20H存高字节。参考程序如下:BCDBI1:MOV20H,#00HMOV21H,#00H;存结果单元MOVR3,#0E8HMOVR4,#03H;千位数的二进制数送R3、R4MOVA,R2上一页下一页返回4.7代码转换程序设计ANLA,#0F0H;取千位数SWAPA;将千位数移至低4位JZBRAN1;千位数为0,则转BRAN1LOOP1:DECAACALLADDT;千位数不为0,加千位数二进制码JNZLOOP1BRAN1:MOVR3,#64HMOVR4,#00H;百位数的二进制码送R3、R4MOVA,R2上一页下一页返回4.7代码转换程序设计ANLA,#0FH;取百位数JZBRAN2;为0则转BRAN2,否则继续LOOP2:DECAACALLADDTJNZLOOP2;加百位数的二进制码BRAN2:MOVR3,#0AHMOVA,R1ANLA,#0F0H;取十位数SWAPA;将十位数移至低4位上一页下一页返回4.7代码转换程序设计JZBRAN3;十位数为0,转BRAN3,否则继续LOOP3:DECAACALLADDTJNZLOOP3;加十位数的二进制玛BRAN3:MOVA,R1ANLA,#0FHMOVR3,AACALLADDTRET上一页下一页返回4.7代码转换程序设计ADDT:PUSHPSWCLRCMOVA,21H;在20H、21H单元中,ADDA,R3;累计转换结果MOV21H,AMOVA,20HADDCA,R4MOV20H,APOPPSWRET上一页下一页返回4.7代码转换程序设计四、双字节BCD码整数转换成双字节十六进制整数在许多的单片机控制系统中,往往需要数据命令和数据,如输入定时时间,输入的数字都是十进制,为了方便单片机内部对数据的处理,通常需要将十进制数转换为十六进制数。参考程序如下:;标号:BH2。;功能:双字节BCD码整数转换成双字节十六进制整数;入口条件:待转换的双字节BCD码整数在R2、R3中;出口信息:转换后的双字节十六进制整数仍在R2、R3中上一页下一页返回4.7代码转换程序设计;影响资源:PSW、A、B、R

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论