汇编程序.docx
《汇编程序.docx》由会员分享,可在线阅读,更多相关《汇编程序.docx(11页珍藏版)》请在冰豆网上搜索。
汇编程序
【例4.1】拆字程序。
将一个字节的两个BCD码十进制数拆开并变成相应的ASCII码,并存入两个RAM单元中。
设两个BCD码(一个字节)已存入在内部RAM的30H单元中,变换后的ASCII码分别存放在31H和32H单元,且高位BCD码的ASCII码的ASCII码存于31H单元。
数字0~9的ASCII为30H~39H,完成拆字转换只需将一个字节的两个BCD码拆开存放在另两个单元的低4位,并在其高4位赋以0011即可。
程序段清单如下:
MOVR0,#32H;将32H单元地址送R0
MOV@R0,#00H;32H单元清0
MOVA,30H;将30H单元中的BCD送A
XCHDA,@R0;将低位BCD码送32H单元
ORL32H,#30H;完成低位BCD码转换
SWAPA;将高位BCD码交换到低位
ORLA,#30H;完成高位BCD码转换
MOV31H,A;将高位BCD的ASCII码存入31H
上述程序段完成了将一个字节的BCD码转换成两个ASCII码的功能。
共需占用15个程序存储器字节单元,用9个机器周期执行完毕。
【例4.2】 双字节加法程序段
设被加数存放在内部矛盾RAM的31H、32H单元,低位字节在前,加数存入于34H、35H单元(低字节在前),结果和存放于31H、32H、33H单元中。
其程序段清单如下;
STRT:
PUSHA;将A内容进栈保护
MOVR0,#31H;将地址码送R0和R1
MOVR1,#34H
MOV33H,#00H;将33H单元清0,存放和的最高字节数
MOVA,R0;两低字节数相加
ADDA,@R1
MOV@R0,A;低字节和存于31H单元
INCR0;地址数分别加1
INCR1
MOVA,@R0;连用低位进位进行高字节数
ADDCA,@R1;相加
MOV@R0,A;高字节和存于32H单元
INCR0;R0指针指向33H单元
MOVA,#00H;清A为0
ADDCA,#00H;求高字节和的进位
MOV@R0,A;将高字节进位存于33H单元
POPA;恢复A原内容
【例4.3】 求双字节补码程序段
设:
存于内部RAM的addr1和addr1+1单元的双字节数读出取补后存入addr2和addr2+1单元中,其中高字节数存于高地址单元,图4.7为双字节数求补流程图
图4.7双字节数取补流程图
8位字长的单片机对双字节数取补需分两次进行,首先对低字节数取补后判其结果是否为0,若为全0,则要对高字节数取补,否则取反即可。
双字节数取补程序估如下:
START:
MOVR0,#addr1;原码低字节数地址送R0
MOVR1,#addr2;补码低字节数地址送R1
MOVA,@R0;原码低字节数送A
CPLA;对低字节数取补
INCA
MOV@R1,A;低字节补码存入addr2单元
INCR0;R0、R1内容分别加1
INCR1
JZZERO;判(A)=0?
当(A)=0,则转ZERO
MOVA,@R0;原码高字节数送A
CPLA;对A内容取反
MOV@R1,A;高字节数补码存addr2+1
SJMPLOOP1;转结束
ZERO:
MOVA,@R0;低字节取补后为0,则对高字节数取补
CPLA
INCA
MOV@R1,A;将高字节补码存addr2+2
LOOP1:
END;结束
所有条件判跳指令均属相对寻址方式,其相对偏移量是一个带符号的8位二进制码,常以补码形式出现。
其寻址范围为-128~+127B。
编程时应多加注意。
【例4.4】 由累加器A在动态运行中给出的结果值选择对应的转移指令,其对应关系为:
(A)=0,转向分反处理程序0
(A)=1,转向分支处理程序1
(A)=n,转向分支处理程序n
一般转移指令均为有条件转移指令,而MCS-51单片机有两条无条件转移指令:
AJMP和LJMP。
前者为双字节指令,后者为三字节指令,因此,需视选用何种跳转指令而应对A中值作相应变换。
如选用AJMP指令,则应对A值变换成偶数值;如选用LJMP指令,则应对A值乘3的变换。
每个分支处理程序均为各自独立的等程序段,分散在各自的程序存储器区段。
要皮,必须有一个中转站,轩向各自的分支处理程序。
这个无条件转移指令串的首地址由DPTR指示。
现以AJMP为例,其程序段如下:
START:
MOVDPTR,#addr16;跳转指令串首址送DPTR
CLRC;清C为0
RLCA;将A值变换成偶数
JNCTABEL;判(C)=0?
不为0则转
INCDPH;(C)=1,则DPH内容+1
TABEL:
JMP@A+DPTR;散转
…
ADDR16:
AJMPLOOP0;无条件转移指令串
AJMPLOOP1
…
AJMPLOOPn
LOOP0:
…;分支程序段0
…
LOOP1:
…;分支程序段1
…
由于上例选用绝对值转移指令AJMP是双字节指令,因此,要求A中内容必须换算成偶数。
换算方式可以乘2,而这里采用左移一位的办法来实现。
如果n值等于或大于128,则左移一位将产生高位进位,将进位值加到DPH中去,等于将转移指令串首址延伸256个存储单元,所以在程序段中对C进行测判。
这样,保证分支处理程序段可以在0-255个中任选。
如果选用长调用LJMP,它是怎么样三字节指令,在进A值换算时应乘3处理,将积的高字节值加到DPH中去。
一般,DPTR+A的最终值应不超过64KB范围。
【例4.5】 采用循环程序实现延时,一般可达到任意延时要求,但需牺牲CPU的工作。
MOV40H,#data;设置计数初值
AGIN:
NOP
NOP
DJNZ40H,AGIN;当(40H)-1≠0则继续循环
上例每循环一次共需4个机器周期,实际总延时由40H单元内容和主频(fosc)的频率所设置决定。
【例4.6】 数据块搜索
设外部RAM从BLOCK单元开始有一个无符号数据块,其长度(即数据块个数)存于LEN单元,试求出数据块最大值数据,并存于MAX单元中。
寻找最大值的方法很多,最基本的方法是比较和交换依次进行,即先读取第一个数与第二个数相比较,并把前一个数作为基准。
比较结果:
若基准数在,则不作交换,再取下一个数进行比较;若基准数小,则将大数取代原基准数,即作一次交换,然后再以新的基准数与下一个数作比较,直到全部比较完毕。
基准数始终保持为最大数值。
图7.6为数据块搜索流程图。
设R1中存放基准数,R3为数据长度,R2中存放每次读出的新的数据块。
其循环程序段如下;
START:
CLRA;A清0
CLRR1;清R1为0
MOVR3,LEN;数据块长度送R3作控制计数
LOOP:
MOVXA,@DPTR;读数据块
INCDPTR指向下一个单元
MOVR2,A;将读出的灵敏据块送R2
CLRC;清C为0
MOVA,R1;基准值送A
SUBBA,R2;基准数一读出数
JNCNEXT;(C)=0,即(A)≥(R2),跳转
MOVR1,A
NEXT:
DJNZR3LOOP;判搜索完否
MOVMAX,R1;最大数据存入MAX单元
END;结束
【例4.7】工作单元清0
设R1中存放被清0单元首地址,R3中存放清0字节数,则其循环程序如下:
START;MOVR1,#addr;清0单元首地址送R1
MOVR3,#data;清0字节数送R3
CLRA;A清0
LOOP:
、MOV@R1,A;指定单元清0
INCR1工;指向下一个单元
DJNZR3,LOOP;(R3)-1≠0,继续清0
END;结束
【例4.8】 4位BCD码整数转换成二进制整数
入口参数:
BCD码字节地址指针R0,位数存于R2中。
出口参数:
二进制数存于R3R4中。
算法:
A=103a3+102a2+10a1+a0
程序流程如7.7所示。
子程序清单如下:
BCDA:
PUSHPSW;现场保护
PUSHA
PUSHB
MOVPSW,#08H
MOVR3,#00H
MOVR2,#3;BCD码D的位数
MOVA,@R0;a0-R4
MOVR4,A
BCKB:
MOVA,R3;(R3R4)×10
MOVB,#10;R4
MULAB
MOVR4,A
XCHA,B
MOVB,#10
XCHA,R3
MULAB
ADDA,R3
XCHA,R4
INCR0;(R0)+1-R0
ADDA,@R0;(R3R4)-((R0))-RR3R4
XCHA,R4
ADDCA,#0
MOVR3,A
DJNZR2,BCDB;循环n-1次
POPB;恢复现场
PIPA
POPPSW
RET;返回
上例中的R2内容是BCD码的位数n,本例中n=4,即两个字节4位BCD码,在程序中作为循环控制寄存器的计数值为n-1=4-1=3,即本例循环3次即完成二次字节的BCD码转换。
本例采用乘10运算,也可采用除2运算进行转换。
【例4.9】 多字节十进制数加法子程序
入口参数:
将R0指针的内部RAM中N个字节的BCD码被加数,R1指针的内产RAM中N个字节的BCD码中数进行相加。
R2中存放字数N。
出口参数:
相加结果的BCD码和数存入R0指针的内部RAM(原被加数单元)中。
图4.8为多字节BCD码加法子程序流程图。
子程序清单如下:
图4.8多字节BCD码加法子程序流程图
BCDADD:
PUSHPSW
PUSHA
MOVPSW,#08H
MOVA,R0
ADDA,R2
MOVR0,A
DECR0
MOVA,R1
ADDA,R2
MOVR1,A
DECR1
CLRC
ADDA:
MOVA,@R0
ADDCA,@R1
DAA
MOV@R0,A
DECR1
DECR0
DJNZR2,ADDA;判加完否
JNCADDB;若(C)=0则转ADDB
MOVA,#00H;清A为0
ADDCA,#00H;若(C)=1,则为最高位进位
MOV@R0,A
ADDB:
POPA;现场恢复
POPPSW
RET;返回
本例中两数均按高位字节数存放于低地址单元,而相国运算则从低位字节数开始,R0、R1指针在运算前均指向最高字节数的地址,故需转换成指向最低字节数的地址,然后进行相加运算。
【例4.10】 应用系统采用LED七段显示,可将BCD码或十六进制码以及某些符号通过查找LED显示编码进行显示输出。
七段LED显示器有共阴极和共阳极之分,其显示编码是不同的,共阳极是低电平为有效输入;共阴极则是高电平输入有效,LED的编码不是序码,即表格无规律可寻,可根据各自方便排列。
例如BCD码显示,同是其显示码可按0~9的顺序排列。
假如显示器是共阳极的,则BCD码与显示器编码的对应关系为:
0的显示编码为01000000,即40H,1的编码为01111001,即79H;2的编码为24H,3的编码为30H,…,对于这类问题,通过查表来实现比较方便。
具体程序段如下:
MOVDPTR,#LEDA ;表格首址送DPTR
MOVA,@A+DPTR;变址寄存器A中内容为查表主序号,即要显示的内容,如0,1,2,…,9
MOVCA,@A+DPTR ;读出要显示的内容
;进行LED显示
LEDA:
DB40H,79H,24H,30H,12H
DB20H,78H,00H,18H,…
对于这类问题,一般均选用DPTR作为基址指针的查表指令为宜。
这样,表格串可设置在64KB的任何地址段,可实现任意次查表