微机实验一.docx
《微机实验一.docx》由会员分享,可在线阅读,更多相关《微机实验一.docx(12页珍藏版)》请在冰豆网上搜索。
微机实验一
单片微型计算机实验
第一次实验
姓名:
Elliott
班级:
xxxxxx
学号:
xxxxxxxxx
电话:
xxxxxxxxxx
一、任务要求
1.调试例程,观察相关寄存器和单元的内容。
2.编写两个十六位数的加法程序。
有两个十六位无符号数,分别存放在从20H和30H开始的数据区中,低八位先存,高八位在后,和存于R3(高八位)和R4(低八位),进位位存于R2。
3.编写两个双字节BCD码的加法程序。
有两个双字节BCD码,分别存放在从20H和30H开始的数据区中,低八位先存,高八位在后,和存于R3(高八位)和R4(低八位),进位位存于R2。
4.编写程序,使之实现从片外RAM的7020H单元开始,连续填充10个字节的数据的功能。
5.编写程序,实现对片外RAM按递减1规律填充数据块的功能。
二、设计思路
1.无符号十六位数加法
对于无符号十六位加法,低八位使用不带标志位的加法,相加后存放。
由于此处可能有进位,所以下一次加法时要用带进位标志位的加法。
为了避免程序最初时CY标志位的随机取值影响带高八位运算的结果,最好在做第一加法的之前将CY置零。
获取最高位进位位时,还是采用ADDC指令,所以两个加数应该都是0。
为了程序的扩展性能,读取加数时,采用R0和R1做指针,这样只要把加数的初始位置赋给R0和R1后,便可以通过R0和R1的自加实现自动取下一位值。
这样有利于多位数相加时的循环实现,同时程序的移植性也得到提高。
2.双字节BCD码加法
本程序的实现方式和无符号十六位加法的实现方式没有本质上的区别,不同之处在于通过加法获得相加的结果后,要用DA指令将数据调整为BCD码,然后再存储数据。
3.顺序填充数据
对于片外RAM的数据访问,只有通过MOVX@DPTR,A这条指令实现,所以要写入的数据得先存放在A当中,DPTR中存放地址。
每次写入数据后,将DPTR的数据加一,指针向下移一位。
由于要写入大量的数据,所以要采用循环,采用工作寄存器R0来计数,用CJNE指令来实现循环的控制。
4.逆序填充数据
逆序填充的程序和顺序填充的程序并没有太大的区别,但是由于DPTR没有自减一的指令,所以需要换一种方式来实现。
DPTR实际上是DPH和DPL两个字节组成的,而DPH和DPL都具有自减一的指令,通过对DPH和DPL的修改便可以实现逆序填充。
三、资源分配
1.无符号十六位加法
20H、21H、30H、31H:
存放加数
R0、R1:
用做数据指针
R2、R3、R4:
存放结果
2.双字节BCD码加法
20H、21H、30H、31H:
存放加数
R0、R1:
用做数据指针
R2、R3、R4:
存放结果
3.顺序填充
片外RAM的7020H至702AH:
存放数据
R0:
存放数据用于循环控制
累加器A:
存放要写入片外RAM的数据
4.逆序填充
片外RAM的7020H至702AH:
存放数据
R0:
存放数据用于循环控制
R1:
用于保护累加器A中的内容
累加器A:
存放要写入片外RAM的数据
四、流程图
1.无符号十六位数加法
2.双字节BCD码加法
3.顺序填充
4.逆序填充
五、源代码
1.无符号十六位加法
ORG0000H
LJMPMAIN
ORG0200H
MAIN:
MOV20H,#0A0H
MOV21H,#11H
MOV30H,#0A0H
MOV31H,#23H
MOVR0,#20H;R0指向加数1首地址
MOVR1,#30H;R1指向加数2首地址
CLRC
MOVA,@R0
ADDA,@R1
MOVR4,A;不带标志位相加,结果存放于R4
INCR0
INCR1;修正指针
MOVA,@R0
ADDCA,@R1;带符号相加
MOVR3,A;存放
MOVR2,#00H;R2置零
MOVA,#00H;A清零
ADDCA,R2
MOVR2,A;存放进位位
SJMP$
END
2.双字节BCD码加法
ORG0000H
LJMPMAIN
ORG0200H
MAIN:
MOV20H,#55H
MOV21H,#11H
MOV30H,#50H
MOV31H,#23H;赋值
MOVR0,#20H;R0指向加数1首地址
MOVR1,#30H;R1指向加数2首地址
CLRC
MOVA,@R0
ADDA,@R1
DAA;修正结果
MOVR4,A;结果存放于R4
INCR0;修正指针
INCR1;修正指针
MOVA,@R0
ADDCA,@R1;带进位相加
DAA;修正结果
MOVR3,A;存放结果
MOVR2,#00H;R2清零
MOVA,#00H;A清零
ADDCA,R2;带进位位加法
DAA;修正结果
MOVR2,A;存放
SJMP$;原地踏步
END
3.顺序填充
ORG0000H
LJMPMAIN
ORG0100H
MAIN:
MOVSP,#40H
FILL:
CLRA;累加器A清零
MOVR0,#00H;设循环计数器
MOVDPTR,#7000H;设数据指针
FILL1:
MOVX@DPTR,A;传送到片外RAM
INCA;A内容加1
INCDPTR;修改数据指针
INCR0;修改循环计数器
CJNER0,#09H,FILL1;判断是否结束
HERE:
SJMPHERE;原地踏步
END
4.逆序填充
ORG0000H
LJMPMAIN
ORG0100H
MAIN:
MOVSP,#40H
CLRA;A累加器清零
MOVR0,#00H;设为循环计数器
MOVDPTR,#7020H;设为数据指针
FILL1:
MOVX@DPTR,A;将数据写到片外RAM
INCA;A内容加1
MOVR1,A;将A的值给R1,保护A的内容
MOVA,DPL;将DPTR低八位给A
CLRC
SUBBA,#00H;将A与00H做减法,
JZHDO;若为零说明则DPH要减1,
;跳转到HDO处,否则顺序执行
SJMPGOON;若顺序执行则跳转,
;用于屏蔽高八位减1的代码
HDO:
DECDPH;DPTR高八位减1
GOON:
MOVA,R1;还原A的数据
DECDPL;DPTR低八位减1
INCR0;修改循环计数器
CJNER0,#0AH,FILL1;判断是否结束
HERE:
SJMPHERE;原地踏步
END
六、程序测试方法与结果、软件性能分析
1.程序测试方法
本次上机实验程序调试的方法是用Keil进行仿真,用“d:
xxxx”和“x:
xxxx”命令查看片内RAM和片外RAM的数据。
在Register窗口查看累加器A、DPTR和R0,R1,R2,R3,R4内的内容。
2.测试结果
1)无符号十六位加法
从左侧的Register窗口可以看到11A0H+23A0H运算结果是003540H(R2、R3、R4)说明程序是正确的。
2)双字节BCD码加法
从左侧的Register窗口可以看到1155+2350的结果是003405(R2、R3、R4),说明程序是正确的。
3)顺序填充
可以看到片外RAM的7000H到7009H顺序写入了0到9共十位数,说明程序是正确的。
4)逆序填充
可以看到片外RAM的7017H到7020H被逆序写上了0到9,说明此算法能够完成逆序写数据的功能,但是不能说明此代码能够应对DPL向DPH借位的情况,下一张图将证明本代码确实能够实现该功能。
可以看到片外RAM的7017H到7020H被逆序写上了0到9,说明此算法能够完成逆序写数据的功能,并能应对DPL向DPH借位的情况。
5)BCD码与ASCII码转换调试
数字4的ASCII码为34H,9为39H,在memory窗口中可以看到片内RAM的31H存放的是34H,32H存放的是39H,33H存放的是由片内RAM的31H和32H单元的数据转换成的BCD码。
3.软件性能分析
由于本次程序设计的时候所有的代码都有良好的可移植性,同时采用了循环或者循环雏形,这样的程序在以后处理大量数据时有良好的性能。
采用指针的方式进行数据访问,在对其他区域的数据进行处理时只需要修改数据的起始地址。
七、心得与体会
虽说我在上单片机这门课之前我已经和单片机打了一年的交道,也用单片机做了一些中小型的程序,但是都是用C51来做的。
使用C51的时候从来没有考虑过很多底层的东西,比如说两个数相加,用汇编的时候得考虑什么时候用ADD,什么时候用ADDC而在C51中只要用“+”就完成了。
看起来用汇编要麻烦很多,但是这才是真正的懂了单片机。
在编写逆序存放的代码时候我最终想到用修改DPL和DPH来修改DPTR的数据,从功能上我实现了要求,同时我也加深了对DPTR工作原理的认识。