51单片机两个无符号整数相乘实验

合集下载

单片机原理与应用实验教案

单片机原理与应用实验教案

《单片机原理及应用》实验教学大纲课程编号:B04611016课程类别:专业课实验学时:16学时学分:2.5适用专业:计算机科学与技术一、实验教学目的和任务本课程是计算机及应用专业一门重要的专业课。

其教学内容直接面向生产。

同时,微机向小型化、超小型化方面发展愈来愈迅猛。

单片机应用已渗透社会各个领域,特别在通信技术中的应用,大大提高了通信技术水平。

学生应具备这方面的知识与技能,为今后参加工作,打下坚实的基础。

二、实验教学基本要求本课程是一门很注重实践的课程。

以研究MCS-51系列单片机入手,掌握其硬件结构、指令系统和程序设计,以及常用接口技术和典型应用实例。

三、实验教学内容实验项目一:清零程序1、实验目的及要求要求学生掌握软件的结构和键盘的调试。

2、实验内容及学时分配(2学时)(1)了解MCS-51软件的构造(2)掌握清零程序的输入方法(3)了解起始伪指令的输入方法实验项目二:拼字和拆字程序1、实验目的及要求要求学生掌握存储器分配和汇编语言的简单应用。

2、实验内容及学时分配(2学时)(1)进一步掌握MCS-51软件的基本使用方法(2)掌握指令的寻址方式(3)掌握数据传送指令和地址内容的分配实验项目三:数据区传送子程序1、实验目的及要求要求学生掌握RAM数据存储器实际操作。

2、实验内容及学时分配(2学时)(1)掌握MCS-51逻辑运算指令和位操作指令(2)进一步掌握数据传送子程序的简单方法(3)掌握查表程序的编写实验项目四:数据排序实验1、实验目的及要求要求学生掌握汇编语言的应用和实际操作。

2、实验内容及学时分配(2学时)(1)掌握MCS51逻辑运算指令和位操作指令(2)进一步掌握简单顺序程序的编写和调试方法(3)掌握查表程序的编写实验项目五:查找相同个数1、实验目的及要求熟悉汇编语言程序,使用环移指令和加1指令。

2、实验内容及学时分配(2学时)(1)掌握赋值指令(2)掌握带进位的环移指令和加1程序的编写实验项目六:双字节无符号数的乘法实验1、实验目的及要求要求学生掌握MCS-51汇编语言设计和调试方法。

C51单片机实战100例

C51单片机实战100例

目录目录 1函数的使用和熟悉 6实例3:用单片机控制第一个灯亮7实例4:用单片机控制一个灯闪烁:认识单片机的工作频率7实例5:将P1口状态分别送入P0、P2、P3口:认识I/O口的引脚功能8实例6:使用P3口流水点亮8位LED 9实例7:通过对P3口地址的操作流水点亮8位LED 11实例8:用不同数据类型控制灯闪烁时间13实例9:用P0口、P1 口分别显示加法和减法运算结果15实例10:用P0、P1口显示乘法运算结果15实例11:用P1、P0口显示除法运算结果16实例12:用自增运算控制P0口8位LED流水花样17实例13:用P0口显示逻辑"与"运算结果18实例14:用P0口显示条件运算结果18实例15:用P0口显示按位"异或"运算结果 19实例16:用P0显示左移运算结果19实例17:"万能逻辑电路"实验20实例18:用右移运算流水点亮P1口8位LED 20实例19:用if语句控制P0口8位LED的流水方向 22实例20:用swtich语句的控制P0口8位LED的点亮状态23 实例21:用for语句控制蜂鸣器鸣笛次数25实例22:用while语句控制LED 27实例23:用do-while语句控制P0口8位LED流水点亮29 实例24:用字符型数组控制P0口8位LED流水点亮30实例25:用P0口显示字符串常量 32实例26:用P0 口显示指针运算结果33实例27:用指针数组控制P0口8位LED流水点亮34实例28:用数组的指针控制P0 口8 位LED流水点亮35实例29:用P0 、P1口显示整型函数返回值37实例30:用有参函数控制P0口8位LED流水速度38实例31:用数组作函数参数控制流水花样40实例32:用指针作函数参数控制P0口8位LED流水点亮41 实例33:用函数型指针控制P1口灯花样44实例34:用指针数组作为函数的参数显示多个字符串45实例35:字符函数ctype.h应用举例48实例36:内部函数intrins.h应用举例48实例37:标准函数stdlib.h应用举例49实例38:字符串函数string.h应用举例 51实例39:宏定义应用举例2 52实例40:宏定义应用举例2 52实例41:宏定义应用举例3 53中断、定时器54实例42:用定时器T0查询方式P2口8位控制LED闪烁54 实例43:用定时器T1查询方式控制单片机发出1KHz音频55 实例44:将计数器T0计数的结果送P1口8位LED显示56 实例45:用定时器T0的中断控制1位LED闪烁57实例46:用定时器T0的中断实现长时间定时59实例47:用定时器T1中断控制两个LED以不同周期闪烁60 实例48:用计数器T1的中断控制蜂鸣器发出1KHz音频62实例49:用定时器T0的中断实现"渴望"主题曲的播放64 实例50-1:输出50个矩形脉冲69实例50-2:计数器T0统计外部脉冲数70实例51-2:定时器T0的模式2测量正脉冲宽度71实例52:用定时器T0控制输出高低宽度不同的矩形波72 实例53:用外中断0的中断方式进行数据采集75实例54-1:输出负脉宽为200微秒的方波76实例54-2:测量负脉冲宽度77实例55:方式0控制流水灯循环点亮78实例56-1:数据发送程序80实例56-2:数据接收程序83实例57-1:数据发送程序84实例57-2:数据接收程序86实例58:单片机向PC发送数据88实例59:单片机接收PC发出的数据90数码管显示 92实例60:用LED数码显示数字5 92实例61:用LED数码显示器循环显示数字0~9 92实例62:用数码管慢速动态扫描显示数字"1234" 94实例63:用LED数码显示器伪静态显示数字1234 95实例64:用数码管显示动态检测结果96实例65:数码秒表设计100实例66:数码时钟设计103实例67:用LED数码管显示计数器T0的计数值110实例68:静态显示数字“59”112键盘控制113实例69:无软件消抖的独立式键盘输入实验113实例70:软件消抖的独立式键盘输入实验114实例71:CPU控制的独立式键盘扫描实验115实例72:定时器中断控制的独立式键盘扫描实验121实例73:独立式键盘控制的4级变速流水灯128实例74:独立式键盘的按键功能扩展:"以一当四" 132实例75:独立式键盘调时的数码时钟实验135实例76:独立式键盘控制步进电机实验143实例77:矩阵式键盘按键值的数码管显示实验148实例78:矩阵式键盘按键音154实例79:简易电子琴157实例80:矩阵式键盘实现的电子密码锁169液晶显示LCD 175实例81:用LCD显示字符'A' 175实例82:用LCD循环右移显示"Welcome to China" 182 实例83:用LCD显示适时检测结果188实例84:液晶时钟设计196一些芯片的使用*****24c02 DS18B20 X5045 ADC0832 DAC0832 DS1302 红外遥控 208实例85:将数据"0x0f"写入AT24C02再读出送P1口显示208实例86:将按键次数写入AT24C02,再读出并用1602LCD显示216 实例87:对I2C总线上挂接多个AT24C02的读写操作231实例88:基于AT24C02的多机通信读取程序242实例88:基于AT24C02的多机通信写入程序249实例90:DS18B20温度检测及其液晶显示271实例91:将数据"0xaa"写入X5045再读出送P1口显示 289实例92:将流水灯控制码写入X5045并读出送P1口显示296实例93:对SPI总线上挂接多个X5045的读写操作303实例94:基于ADC0832的数字电压表312实例95:用DAC0832产生锯齿波电压324实例96:用P1口显示红外遥控器的按键值 325实例97:用红外遥控器控制继电器 330实例98:基于DS1302的日历时钟335实例99:单片机数据发送程序353实例100:电机转速表设计 355//模拟霍尔脉冲 365函数的使用和熟悉实例3:用单片机控制第一个灯亮#include<reg51.h> //包含51单片机寄存器定义的头文件void main(void){P1=0xfe; //P1=1111 1110B,即P1.0输出低电平}实例4:用单片机控制一个灯闪烁:认识单片机的工作频率#include<reg51.h> //包含单片机寄存器的头文件/****************************************函数功能:延时一段时间*****************************************/void delay(void) //两个void意思分别为无需返回值,没有参数传递{unsigned int i; //定义无符号整数,最大取值范围65535for(i=0;i<20000;i++) //做20000次空循环; //什么也不做,等待一个机器周期}/*******************************************************函数功能:主函数(C语言规定必须有也只能有1个主函数)********************************************************/void main(void){while(1) //无限循环{P1=0xfe; //P1=1111 1110B,P1.0输出低电平delay(); //延时一段时间P1=0xff; //P1=1111 1111B,P1.0输出高电平delay(); //延时一段时间}}实例5:将P1口状态分别送入P0、P2、P3口:认识I/O口的引脚功能#include<reg51.h> //包含单片机寄存器的头文件/*******************************************************函数功能:主函数(C语言规定必须有也只能有1个主函数)********************************************************/void main(void){while(1) //无限循环{P1=0xff; // P1=1111 1111B,熄灭LEDP0=P1; // 将P1口状态送入P0口P2=P1; // 将P1口状态送入P2口P3=P1; // 将P1口状态送入P3口}}实例6:使用P3口流水点亮8位LED#include<reg51.h> //包含单片机寄存器的头文件/****************************************函数功能:延时一段时间*****************************************/void delay(void){unsigned char i,j;for(i=0;i<250;i++)for(j=0;j<250;j++);}/******************************************************* 函数功能:主函数********************************************************/ void main(void){while(1){P3=0xfe; //第一个灯亮delay(); //调用延时函数P3=0xfd; //第二个灯亮delay(); //调用延时函数P3=0xfb; //第三个灯亮delay(); //调用延时函数P3=0xf7; //第四个灯亮delay(); //调用延时函数P3=0xef; //第五个灯亮 delay(); //调用延时函数P3=0xdf; //第六个灯亮delay(); //调用延时函数P3=0xbf; //第七个灯亮 delay(); //调用延时函数P3=0x7f; //第八个灯亮 delay(); //调用延时函数}}实例7:通过对P3口地址的操作流水点亮8位LED#include<reg51.h> //包含单片机寄存器的头文件sfr x=0xb0; //P3口在存储器中的地址是b0H,通过sfr可定义8051内核单片机//的所有内部8位特殊功能寄存器,对地址x的操作也就是对P1口的操作/****************************************函数功能:延时一段时间*****************************************/void delay(void){unsigned char i,j;for(i=0;i<250;i++)for(j=0;j<250;j++); //利用循环等待若干机器周期,从而延时一段时间}/*****************************************函数功能:主函数******************************************/void main(void){while(1){x=0xfe; //第一个灯亮delay(); //调用延时函数x=0xfd; //第二个灯亮delay(); //调用延时函数x=0xfb; //第三个灯亮delay(); //调用延时函数x=0xf7; //第四个灯亮delay(); //调用延时函数x=0xef; //第五个灯亮 delay(); //调用延时函数x=0xdf; //第六个灯亮delay(); //调用延时函数x=0xbf; //第七个灯亮 delay(); //调用延时函数x=0x7f; //第八个灯亮 delay(); //调用延时函数}}实例8:用不同数据类型控制灯闪烁时间#include<reg51.h> //包含单片机寄存器的头文件/******************************************************函数功能:用整形数据延时一段时间******************************************************/void int_delay(void) //延时一段较长的时间{unsigned int m; //定义无符号整形变量,双字节数据,值域为0~65535 for(m=0;m<36000;m++); //空操作}/******************************************************函数功能:用字符型数据延时一段时间******************************************************/void char_delay(void) //延时一段较短的时间{unsigned char i,j; //定义无符号字符型变量,单字节数据,值域0~255 for(i=0;i<200;i++)for(j=0;j<180;j++); //空操作}/****************************************************** 函数功能:主函数******************************************************/ void main(void){unsigned char i;while(1){for(i=0;i<3;i++){P1=0xfe; //P1.0口的灯点亮int_delay(); //延时一段较长的时间P1=0xff; //熄灭int_delay(); //延时一段较长的时间}for(i=0;i<3;i++){P1=0xef; //P1.4口的灯点亮char_delay(); //延时一段较长的时间P1=0xff; //熄灭char_delay(); //延时一段较长的时间}}}实例9:用P0口、P1 口分别显示加法和减法运算结果#include<reg51.h>void main(void){unsigned char m,n;m=43; //即十进制数2x16+11=43n=60; //即十进制数3x16+12=60P1=m+n; //P1=103=0110 0111B,结果P1.3、P1.4、P1.7 口的灯被点亮P0=n-m; //P0=17=0001 0001B,结果P0.0、P0.4的灯被熄灭}实例10:用P0、P1口显示乘法运算结果#include<reg51.h> //包含单片机寄存器的头文件void main(void){unsigned char m,n;unsigned int s;n=71;s=m*n; //s=64*71=4544,需要16位二进制数表示,高8位送P1口,低8位送P0口//由于4544=17*256+192=H3*16*16*16+H2*16*16+H1*16+H0//两边同除以256,可得17+192/256=H3*16+H2+(H1*16+H0)/256//因此,高8位16进制数H3*16+H2必然等于17,即4544除以256的商//低8位16进制数H1*16+H0必然等于192,即4544除以256的余数P1=s/256; //高8位送P1口,P1=17=11H=0001 0001B, P1.0和P1.4口灭,其余亮P0=s%256; //低8位送P0口, P3=192=c0H=11000000B,P3.1,P3.6,P3.7口灭,其余亮}实例11:用P1、P0口显示除法运算结果#include<reg51.h> //包含单片机寄存器的头文件void main(void){P1=36/5; //求整数P0=((36%5)*10)/5; //求小数while(1); //无限循环防止程序“跑飞”}实例12:用自增运算控制P0口8位LED流水花样#include<reg51.h> //包含单片机寄存器的头文件/****************************************************** 函数功能:延时一段时间******************************************************/ void delay(void){unsigned int i;for(i=0;i<20000;i++);}/****************************************************** 函数功能:主函数******************************************************/void main(void){unsigned char i;for(i=0;i<255;i++) //注意i的值不能超过255{P0=i; //将i的值送P0口delay(); //调用延时函数}}实例13:用P0口显示逻辑"与"运算结果#include<reg51.h> //包含单片机寄存器的头文件void main(void){P0=(4>0)&&(9>0xab);//将逻辑运算结果送P0口while(1); //设置无限循环,防止程序“跑飞”}实例14:用P0口显示条件运算结果#include<reg51.h> //包含单片机寄存器的头文件void main(void){P0=(8>4)?8:4;//将条件运算结果送P0口,P0=8=0000 1000B while(1); //设置无限循环,防止程序“跑飞”}实例15:用P0口显示按位"异或"运算结果#include<reg51.h> //包含单片机寄存器的头文件void main(void){P0=0xa2^0x3c;//将条件运算结果送P0口,P0=8=0000 1000B while(1); //设置无限循环,防止程序“跑飞”}实例16:用P0显示左移运算结果#include<reg51.h> //包含单片机寄存器的头文件void main(void){P0=0x3b<<2;//将左移运算结果送P0口,P0=1110 1100B=0xec while(1); //无限循环,防止程序“跑飞”}实例17:"万能逻辑电路"实验#include<reg51.h> //包含单片机寄存器的头文件sbit F=P1^4; //将F位定义为P1.4sbit X=P1^5; //将X位定义为P1.5sbit Y=P1^6; //将Y位定义为P1.6sbit Z=P1^7; //将Z位定义为P1.7void main(void){while(1){F=((~X)&Y)|Z; //将逻辑运算结果赋给F;}}实例18:用右移运算流水点亮P1口8位LED#include<reg51.h> //包含单片机寄存器的头文件/*****************************函数功能:延时一段时间*****************************/void delay(void){unsigned int n;for(n=0;n<30000;n++);}/*****************************函数功能:主函数*****************************/void main(void){unsigned char i;while(1){P1=0xff;delay();for(i=0;i<8;i++)//设置循环次数为8{P1=P1>>1; //每次循环P1的各二进位右移1位,高位补0delay(); //调用延时函数}}}实例19:用if语句控制P0口8位LED的流水方向#include<reg51.h> //包含单片机寄存器的头文件sbit S1=P1^4; //将S1位定义为P1.4sbit S2=P1^5; //将S2位定义为P1.5/*****************************函数功能:主函数*****************************/void main(void){while(1){if(S1==0) //如果按键S1按下P0=0x0f; //P0口高四位LED点亮if(S2==0) //如果按键S2按下P0=0xf0; //P0口低四位LED点亮}}实例20:用swtich语句的控制P0口8位LED的点亮状态#include<reg51.h> //包含单片机寄存器的头文件sbit S1=P1^4; //将S1位定义为P1.4/*****************************函数功能:延时一段时间*****************************/void delay(void){unsigned int n;for(n=0;n<10000;n++);}/*****************************函数功能:主函数*****************************/void main(void){unsigned char i;i=0; //将i初始化为0while(1){if(S1==0) //如果S1键按下{delay(); //延时一段时间if(S1==0) //如果再次检测到S1键按下i++; //i自增1if(i==9) //如果i=9,重新将其置为1i=1;}switch(i) //使用多分支选择语句{case 1: P0=0xfe; //第一个LED亮break;case 2: P0=0xfd; //第二个LED亮break;case 3:P0=0xfb; //第三个LED亮break;case 4:P0=0xf7; //第四个LED亮break;case 5:P0=0xef; //第五个LED亮break;case 6:P0=0xdf; //第六个LED亮break;case 7:P0=0xbf; //第七个LED亮break;case 8:P0=0x7f; //第八个LED亮break;default: //缺省值,关闭所有LEDP0=0xff;}}}实例21:用for语句控制蜂鸣器鸣笛次数#include<reg51.h> //包含单片机寄存器的头文件sbit sound=P3^7; //将sound位定义为P3.7/****************************************函数功能:延时形成1600Hz音频****************************************/void delay1600(void){unsigned char n;for(n=0;n<100;n++);}/**************************************** 函数功能:延时形成800Hz音频****************************************/ void delay800(void){unsigned char n;for(n=0;n<200;n++);}/**************************************** 函数功能:主函数****************************************/ void main(void){unsigned int i;while(1){for(i=0;i<830;i++){sound=0; //P3.7输出低电平delay1600();sound=1; //P3.7输出高电平delay1600();}for(i=0;i<200;i++){sound=0; //P3.7输出低电平delay800();sound=1; //P3.7输出高电平delay800();}}}实例22:用while语句控制LED#include<reg51.h> //包含单片机寄存器的头文件/****************************************函数功能:延时约60ms (3*100*200=60000μs)****************************************/void delay60ms(void){unsigned char m,n;for(m=0;m<100;m++)for(n=0;n<200;n++);}/****************************************函数功能:主函数****************************************/void main(void){unsigned char i;while(1) //无限循环{i=0; //将i初始化为0while(i<0xff) //当i小于0xff(255)时执行循环体{P0=i; //将i送P0口显示delay60ms(); //延时i++; //i自增1}}}实例23:用do-while语句控制P0口8位LED流水点亮#include<reg51.h> //包含单片机寄存器的头文件/****************************************函数功能:延时约60ms (3*100*200=60000μs)****************************************/void delay60ms(void){unsigned char m,n;for(m=0;m<100;m++)for(n=0;n<200;n++);}/****************************************函数功能:主函数****************************************/void main(void){do{P0=0xfe; //第一个LED亮delay60ms();P0=0xfd; //第二个LED亮delay60ms();P0=0xfb; //第三个LED亮delay60ms();P0=0xf7; //第四个LED亮delay60ms();P0=0xef; //第五个LED亮delay60ms();P0=0xdf; //第六个LED亮delay60ms();delay60ms();P0=0xbf; //第七个LED亮delay60ms();P0=0x7f; //第八个LED亮delay60ms();}while(1); //无限循环,使8位LED循环流水点亮}实例24:用字符型数组控制P0口8位LED流水点亮#include<reg51.h> //包含单片机寄存器的头文件/****************************************函数功能:延时约60ms (3*100*200=60000μs)****************************************/void delay60ms(void){unsigned char m,n;for(m=0;m<100;m++)for(n=0;n<200;n++);}/****************************************函数功能:主函数****************************************/void main(void){unsigned char i;unsigned char code Tab[ ]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //定义无符号字符型数组while(1){for(i=0;i<8;i++){P0=Tab[i];//依次引用数组元素,并将其送P0口显示delay60ms();//调用延时函数}}}实例25:用P0口显示字符串常量#include<reg51.h> //包含单片机寄存器的头文件/*************************************************函数功能:延时约150ms (3*200*250=150 000μs=150ms*************************************************/void delay150ms(void){unsigned char m,n;for(m=0;m<200;m++)for(n=0;n<250;n++);}/*************************************************函数功能:主函数*************************************************/void main(void){unsigned char str[]={"Now,Temperature is :"}; //将字符串赋给字符型全部元素赋值unsigned char i;while(1){i=0; //将i初始化为0,从第一个元素开始显示while(str[i]!='\0') //只要没有显示到结束标志'\0'{P0=str[i]; //将第i个字符送到P0口显示delay150ms(); //调用150ms延时函数i++; //指向下一个待显字符}}}实例26:用P0 口显示指针运算结果#include<reg51.h>void main(void){unsigned char *p1,*p2; //定义无符号字符型指针变量p1,p2 unsigned char i,j; //定义无符号字符型数据i=25; //给i赋初值25j=15;p1=&i; //使指针变量指向i ,对指针初始化p2=&j; //使指针变量指向j ,对指针初始化P0=*p1+*p2; //*p1+*p2相当于i+j,所以P0=25+15=40=0x28 //则P0=0010 1000B,结果P0.3、P0.5引脚LED熄灭,其余点亮while(1); //无限循环,防止程序“跑飞”}实例27:用指针数组控制P0口8位LED流水点亮#include<reg51.h>/*************************************************函数功能:延时约150ms (3*200*250=150 000μs=150ms*************************************************/void delay150ms(void){unsigned char m,n;for(m=0;m<200;m++)for(n=0;n<250;n++);}/*************************************************函数功能:主函数void main(void){unsigned char code Tab[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; unsigned char *p[ ]={&Tab[0],&Tab[1],&Tab[2],&Tab[3],&Tab[4],&Tab[5], &Tab[6],&Tab[7]};unsigned char i; //定义无符号字符型数据while(1){for(i=0;i<8;i++){P0=*p[i];delay150ms();}}}实例28:用数组的指针控制P0 口8 位LED流水点亮#include<reg51.h>/*************************************************函数功能:延时约150ms (3*200*250=150 000μs=150msvoid delay150ms(void){unsigned char m,n;for(m=0;m<200;m++)for(n=0;n<250;n++);}/*************************************************函数功能:主函数*************************************************/void main(void){unsigned char i;unsigned char Tab[ ]={0xFF,0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,0xFE,0xFE,0xFC,0xFB,0xF0,0xE0,0xC0,0x80,0x00,0xE7,0xDB,0xBD,0x7E,0x3C,0x18,0x00,0x81,0xC3,0xE7,0x7E,0xBD,0xDB,0xE7,0xBD,0xDB};//流水灯控制码unsigned char *p; //定义无符号字符型指针p=Tab; //将数组首地址存入指针pwhile(1){for(i=0;i<32;i++) //共32个流水灯控制码{P0=*(p+i); //*(p+i)的值等于a[i]delay150ms(); //调用150ms延时函数}}}实例29:用P0 、P1口显示整型函数返回值#include<reg51.h>/************************************************* 函数功能:计算两个无符号整数的和*************************************************/ unsigned int sum(int a,int b){unsigned int s;s=a+b;return (s);}/************************************************* 函数功能:主函数*************************************************/ void main(void){unsigned z;z=sum(2008,2009);P1=z/256; //取得z的高8位P0=z%256; //取得z的低8位while(1);}实例30:用有参函数控制P0口8位LED流水速度#include<reg51.h>/************************************************* 函数功能:延时一段时间*************************************************/ void delay(unsigned char x){unsigned char m,n;for(m=0;m<x;m++)for(n=0;n<200;n++);}/*************************************************函数功能:主函数*************************************************/void main(void){unsigned char i;unsigned char code Tab[ ]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};//流水灯控制码while(1){//快速流水点亮LEDfor(i=0;i<8;i++) //共8个流水灯控制码{P0=Tab[i];delay(100); //延时约60ms, (3*100*200=60 000μs)}//慢速流水点亮LEDfor(i=0;i<8;i++) //共8个流水灯控制码{P0=Tab[i];delay(250); //延时约150ms, (3*250*200=150 000μs)}}}实例31:用数组作函数参数控制流水花样#include<reg51.h>/*************************************************函数功能:延时约150ms*************************************************/void delay(void){unsigned char m,n;for(m=0;m<200;m++)for(n=0;n<250;n++);}/*************************************************函数功能:流水点亮P0口8位LED*************************************************/void led_flow(unsigned char a[8]){unsigned char i;for(i=0;i<8;i++){P0=a[i];delay();}}/*************************************************函数功能:主函数*************************************************/void main(void){unsigned char code Tab[ ]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};//流水灯控制码led_flow(Tab);}实例32:用指针作函数参数控制P0口8位LED流水点亮#include<reg51.h>/*************************************************函数功能:延时约150ms*************************************************/void delay(void){unsigned char m,n;for(m=0;m<200;m++)for(n=0;n<250;n++);}/*************************************************函数功能:流水点亮P0口8位LED*************************************************/void led_flow(unsigned char *p) //形参为无符号字符型指针{unsigned char i;while(1){i=0; //将i置为0,指向数组第一个元素while(*(p+i)!='\0') //只要没有指向数组的结束标志{P0=*(p+i);// 取的指针所指变量(数组元素)的值,送P0口delay(); //调用延时函数i++; //指向下一个数组元素}}}/*************************************************函数功能:主函数*************************************************/void main(void){unsigned char code Tab[ ]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F,0x7F,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,0xFE, 0xFF,0xFE,0xFC,0xFB,0xF0,0xE0,0xC0,0x80,0x00,0xE7,0xDB,0xBD,0x7E,0xFF,0xFF,0x3C,0x18,0x0,0x81,0xC3,0xE7,0xFF, 0xFF,0x7E};//流水灯控制码unsigned char *pointer;pointer=Tab;led_flow(pointer);}实例33:用函数型指针控制P1口灯花样#include<reg51.h> //包含51单片机寄存器定义的头文件unsigned char code Tab[]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F}; //流水灯控制码,该数组被定义为全局变量/**************************************************************函数功能:延时约150ms**************************************************************/void delay(void){unsigned char m,n;for(m=0;m<200;m++)for(n=0;n<250;n++);}/**************************************************************函数功能:流水灯左移**************************************************************/void led_flow(void){unsigned char i;for(i=0;i<8;i++) //8位控制码{P0=Tab[i];delay();}}/**************************************************************函数功能:主函数**************************************************************/void main(void){void (*p)(void); //定义函数型指针,所指函数无参数,无返回值p=led_flow; //将函数的入口地址赋给函数型指针pwhile(1)(*p)(); //通过函数的指针p调用函数led_flow()}实例34:用指针数组作为函数的参数显示多个字符串#include<reg51.h> //包含51单片机寄存器定义的头文件unsigned char code str1[ ]="Temperature is tested by DS18B20";//C语言中,字符串是作为字符数组来处理的unsigned char code str2[ ]="Now temperature is:"; //所以,字符串的名字就是字符串的首地址unsigned char code str3[ ]="The Systerm is designed by Zhang San"; unsigned char code str4[ ]="The date is 2008-9-30";unsigned char *p[ ]={str1,str2,str3,str4}; //定义p[4]为指向4个字符串的字符型指针数组/**************************************************************函数功能:延时约150ms**************************************************************/void delay(void){unsigned char m,n;for(m=0;m<200;m++)for(n=0;n<250;n++);}/**************************************************************函数功能:流水点亮P0口8位LED**************************************************************/void led_display(unsigned char *x[ ]) //形参必须为指针数组{unsigned char i,j;for(i=0;i<4;i++) //有4个字符串要显示{j=0; //指向待显字符串的第0号元素while(*(x[i]+j)!='\0') //只要第i个字符串的第j号元素不是结束标志{P0=*(x[i]+j); //取得该元素值送到P0口显示delay(); //调用延时函数j++; //指向下一个元素}}}/**************************************************************函数功能:主函数**************************************************************/void main(void){unsigned char i;while(1){for(i=0;i<4;i++)led_display(p); //将指针数组名作实际参数传递}}实例35:字符函数ctype.h应用举例#include<reg51.h> //包含51单片机寄存器定义的头文件#include<ctype.h>void main(void){while(1){P3=isalpha('_')?0xf0:0x0f;//条件运算,若'_'是英文字母,P3=0xf0 }}实例36:内部函数intrins.h应用举例#include<reg51.h> //包含51单片机寄存器定义的头文件#include<intrins.h> //包含函数isalpha()声明的头文件/*************************************************函数功能:延时约150ms*************************************************/void delay(void){unsigned char m,n;for(m=0;m<200;m++)for(n=0;n<250;n++);}/*************************************************函数功能:主函数*************************************************/void main(void){P3=0xfe; //P3=1111 1110Bwhile(1){P3=_crol_(P3,1);// 将P3的二进制位循环左移1位后再赋给P3 delay(); //调用延时函数}}实例37:标准函数stdlib.h应用举例#include<reg51.h> //包含51单片机寄存器定义的头文件#include<stdlib.h> //包含函数isalpha()声明的头文件/*************************************************函数功能:延时约150ms*************************************************/void delay(void){unsigned char m,n;for(m=0;m<200;m++)for(n=0;n<250;n++);}/*************************************************函数功能:主函数*************************************************/void main(void){unsigned char i;while(1){for(i=0;i<10;i++) //产生10个随机数{P3=rand()/160; //将产生的随机数缩小160倍后送P3显示。

单片机C语言编程中多位乘法运算问题探讨

单片机C语言编程中多位乘法运算问题探讨

第23卷第4期2006年12月广东工业大学学报Journa l of Guangdong Un i versity of Technology Vol .23 No .4Dece mber 2006收稿日期:2005212212项目基金:广东省科技计划项目(2003C102022)作者简介:严克剑(19822),男,硕士研究生,主要研究方向为控制网络集成.单片机C 语言编程中多位乘法运算问题探讨严克剑,张 淼,黄先伟(广东工业大学自动化学院,广东广州510090)摘要:本文指出了人们运用C51实现多字节乘法运算时可能忽视的一个问题.通过分析该问题出现的原因,提出了中间变量法、分步运算法和强制数据类型转换法等3种解决方法,实验表明这些方法是可行的.关键词:C51;单片机;乘法运算中图分类号:TP332.3 文献标识码:A 文章编号:100727162(2006)0420023204C 语言既具有一般高级语言的特点,又能直接对计算机的硬件进行操作[1].Keil C51是德国Keil Soft w are 公司出品的51系列兼容单片机C 语言软件开发系统.与汇编相比,C 语言在功能、结构性、可读性、可维护性上有明显的优势,因而易学易用.Keil C51继承了C 语言对数据有很强的表达能力的优点,具有丰富的运算符,在算术运算和逻辑运算上更体现了汇编不可比拟的优点.由于C5l 语言具有强大的数据处理能力和数学运算库函数,当涉及到复杂的数学运算,使用C51语言往往会比较方便.在一般情况下,由C51编译生成的代码不论长度还是程序运行速度均能适应程序要求.利用C51开发单片机系统,不但可以使编程工作量大为减少,而且使软件维护、修改亦变得非常方便[2].1 问题提出在Keil C51中,bit 和unsigned char 型变量是机器语言直接支持的,因此两个unsigned char 类型的数据相乘恰好与汇编指令中的“MUL AB ”相符.使用Keil C51做乘法运算编程,往往只需要利用乘法表达式来编译,只要编译通过Keil C51就会自动地寻找寄存器把运行结果存放在里面.因此,在运用C51来完成乘法运算的时候,编程员通常就是编写一个乘法表达式和把乘积结果赋值给一个存储单元就可以了.而如果乘法运算中的乘数不是unsigned char 型变量,就算是简单的一个乘法表达式也需要调用C51中的库函数;如果乘数是大于255的常量,C51自动地把这个乘数以相应的类型储存起来,由于unsigned char 是8位的,大于255的常量和其他类型的变量一样也需要调用库函数.因此,如果在这些情况下还仅仅是用乘法表达式来编译的话,得到的结果就可能与实际结果不相等.笔者在编程的时候曾经遇上上述情况.例如以下有一段程序,运行之后所得结果gg 的值不等于9310000所得的结果.#include <AT89X55.H >main ()42广东工业大学学报第23卷 { unsigned charaa; unsigned l ong gg; aa=9; gg=(aa310000);}本例的实际运算结果应该是90000,但是通过以上程序得到的结果却是24464.通过Keil C51单步运算结果还是24464,与实际结果相差65536,转换为16进制数刚好是10000H,显然这是一个溢出问题.然而通过Keil C51的单步运算可以知道溢出标志OV为零,因此不能运用溢出标志判断,以得到真正的结果.2 问题的分析Keil C51编译器在进行优化处理时,总是企图用工作寄存器来存放局部变量的.在执行aa =9语句时,根据C51的存储规则,可以得到R7=9.执行aa310000时,Keil C51要求算术运算的数据类型一样的,这里10000是两个字节的unsigned int方式储存的,这样aa的储存必需扩展成为两个字节的unsigned int方式.因此,Keil C51用两个寄存器存储aa=9,先存低字节,后存高字节,分别为R7=09H、R6=00H,储存10000的寄存器R5、R4分别是10H、27H.这样的话,执行aa310000就变成了两个双字节数相乘,根据C51的运算规则,生成代码得到的反汇编语言代码如下:MOV A,R7MOV B,R5MUL ABMOV R0,BXCH A,R7MOV B,R4MUL ABADD A,R0MOV R6,BXCH A,R6MOV B,R5MUL ABADD A,R6MOV R6,ARET由此可知,代码少运算了一次,也就是原来存放在R6与R4里面的数据没有进行乘法运算,而且没有把第三次运算(原来存放在R5与R6的数据相乘)得到的结果的高8位储存起来,运算得到的结果的低8位存放在R7,次低8位存放在R6.因此,运算的结果不正确.3 解决方法针对上述所分析的问题,笔者提出了几种可行的解决方法.以下所列举的3种是已经通过第4期严克剑,等:单片机C语言编程中多位乘法运算问题探讨实验验证的解决方法.1)引入中间变量法在运算的时候加入一个中间变量可以解决这个问题.要求这个中间变量数据类型必需能够存储相乘之后得到的结果,上面的程序可以改为:#include <AT89X55.H >main () { unsigned char aa; unsigned l ong gg,bb; aa =9; bb =10000; gg =(aa 3bb );}由程序可以看出,这里aa 是char 而bb 是l ong 类型.根据C51的运算规则,aa 先变成与l ong 一样的数据类型,运行的结果也是l ong 类型的,C51能够自动存储9310000这个数据,因此,结果不会出错.2)分步运算法编程人员也可以采取分步运算的方法,把一个16位的数据分成两个数据的乘积,而这两个数据都是8位数据,结果储存在可以存储相乘之后得到的结果的储存单元中.以上程序可以改为:#include <AT89X55.H >main () { unsigned char aa; unsigned l ong gg; aa =9; gg =(aa 3100); gg 3=100;}这个程序先把10000分成两个8位数的乘积1003100,然后逐个相乘.由于aa 与100都是unsigned char 数据类型,直接调用汇编语言的“MUL AB ”指令,再把结果送到存储单元为l ong 类型的gg,在运行gg 3=100语句的时候,C51先以l ong 类型储存数据100,然后调用库函数,得到的结果为l ong 类型,可以存储9310000这个数,最后运算结果正确.3)强制类型转换法C51中,圆括号“()”可以作为强制类型转换运算符,顾名思义,它的作用就是将表达式或者标量的类型强制转换成为所制定的类型.C51中,有两种数据类型转换方式,—种是隐式转换,另外一种是显式转换.隐式转换有以下规则:①把所有的char 类型的操作数转换成为int 类型.②当强制类型转换运算符连接两个操作数时,如果有一个是fl oat 类型的,另外一个也转换52广东工业大学学报第23卷成fl oat 类型;如果有一个是l ong 类型的,另外的一个要转换成l ong 类型;如果有—个是unsigned 类型的,另外一个也转换成为unsigned .③如果强制类型转换运算符连接的两个数据是对变量的赋值,则仅将赋值号右边的表达式类型转换成为赋值号左边的类型.隐式转换式在对程序进行编译时由编译器自动处理的,本例中应用隐式转化方式不能得到正确的结果.运用显式类型转换方式,通过强制类型转换运算符把aa 强制转换成为可以储存运算结果的类型.main () { unsigned char aa; unsigned l ong gg; aa =9; gg =((unsigned l ong )aa )310000;}程序中,首先把aa 转换成为可以储存9310000的数据类型,得到的结果是正确的.对比3种方法,引入中间变量法可以用在内部寄存器足够使用的时候,如果程序对内部寄存器的使用本来就紧张,则不推荐使用.分步运算法必须要清楚乘数的值,多字节的乘数值的大小完全清楚或者是已知的常数时,推荐使用.使用强制数据类型法时,需要注意的是把少字节类型的数据转换成多字节.4 结束语Keil C51生成目标代码的效率非常高,很多语句生成的汇编代码很紧凑,而且容易理解.乘法运算时出现以上这种情况,并不能掩盖其不可比拟的优点.如果在使用Keil C51作算术运算时,注意一下溢出问题,将会更好地发挥Keil C51运算能力强的优点.参考文献:[1]徐爱钧,彭秀华.单机机高级语言C51W indows 环境编程与应用[M ].北京:电子工业出版社,2001.[2]胡士强,张小英,王改名,等.利用单片系统应用软件[J ].工业科技,1999,16(2):63267.Study of M ulti pli ca ti ve Prog Ramm i n g Problem i n C 51Y AN Ke 2jian,ZHANG M iao,HUANG Xian 2wei(Faculty of Aut omati on,Guangdong University of Technol ogy,Guangzhou 510090,China )Abstract:This text points out a p r oble m that peop le may neglect in the use of C51t o operate multi p li 2cati on of multi 2bytes .It analyzes the reas on why this p r odle m appears .Then it puts for ward three methods t o res olve it,and these methods are p r oved t o be feasible by experi m ents .Key words:C51;single chi p;muiti p licati on operati on 62。

微机原理设计实验之两个数相乘

微机原理设计实验之两个数相乘

课程设计题目:两个数相乘一、实验目的1、领会汇编语言的编程思想;2、掌握汇编语言的指令,加深乘法指令和循环指令的用法;3、学会DOS功能的调用。

二、实验内容实现两个十进制数的乘法,被乘数和乘数均以ASCII码形式存放在内存中,乘积在屏幕上显示出来。

三、实验原理本实验设计A、B两个数相乘。

巧妙地运用了数学中的乘法原理,将B的低位和A的最低位相乘得到的数的低位存到AL中,这个数的进位存到AH中,再用B的低位和A的次低位相乘,得到一个数,这个数的低位和上一次的进位相加。

循环此过程直到到B与A的最高位相乘结束,并与上一次结果的进位相加,得到最后的结果。

四、程序设计流程图(此处画上是实验纸上的流程图)五、实验程序DATA SEGMENT ;定义数据段DATA1 DB 32H,39H,30H,35H,34H ;用ASCII码表示被乘数45092DATA2 DB 34H ;用ASCII码表示乘数4MES1 DB '*','$'MES2 DB '=','$'BUF DB 'Result$'RESULT DB 6 DUP(00H) ;定义存放结果的数据缓冲区,6个字节长,初值为0DATA ENDS ;数据段结束STACK SEGMENT ;定义堆栈段STA DB 20 DUP() ;为变量STA分配20个字节的空间TOP EQU LENGTH STA;返回利用DUP定义的数组元素的个数到TOP,TOP=20STACK ENDS ;堆栈段结束CODE SEGMENT ;定义代码段ASSUME CS: CODE,DS:DATA,SS:STACK,ES:DATASTART: MOV AX,DATAMOV DS,AX ;DS→AXMOV AX,STACKMOV SS,AX ;SS→STACKMOV SP,TOP ;栈顶指针指向TOPMOV DX,OFFESET BUFMOV AH,9 ;DOS功能号09H送AHINT 21H ;显示字符串‘please input ’LEA SI,DATA1 ;被乘数首地址送SIMOV BX,05HL1: MOV AH,02H ;DOS功能号02H送AHMOV DL,[SI+BX-1] ;被乘数送DLINT 21H ; DOS功能号调用(显示器输出)DEC BXJNZ L1MOV AH,09H ; DOS功能号09H送AHLEA DX,MES1 ;MES1的偏移地址送DXINT 21H ; DOS功能号调用(显示字符串) LEA SI,DATA2 ;乘数地址送SIMOV AH,02HMOV DL,[SI] ;乘数送DLINT 21H ;显示乘数MOV AH,09HLEA DX,MES2 ; MES2的偏移地址送DXINT 21HMOV SI,OFFSET DATA2MOV BL,[SI] ;DATA2中的乘数送BLAND BL,00001111B ;屏蔽乘数高4位,ASCII码转换为十六进制MOV SI,OFFSET DATA1 ;被乘数偏移地址送SIMOV DI,OFFSET RESULT ;运算结果偏移地址送DIMOV CX,05 ;设置循环次数LOOP1: MOV AL,[SI] ;被乘数送ALAND AL,00001111B ;屏蔽被乘数高4位,ASCII码转换为十六进制 INC SIMUL BL ;AL * BL送AXAAM ;乘法十进制调整ADD AL,[DI] ;结果低位与前次计算的进位相加AAA ;BCD码加法十进制调整指令MOV [DI],AL ;计算结果低位送DIINC DIMOV [DI],AH ;计算结果高位进位送DI+1LOOP LOOP1 ;循环MOV CX,06MOV SI, DI ;计算结果送SIDISPL:MOV AH,02H ;调用DOS功能号02H送AHMOV DL,[SI]ADD DL,30H ;结果转换为ASCII码INT 21H ;显示一位数据DEC SI ;地址减一,继续后面的数据显示LOOP DISPL ;显示运算结果MOV AX,4C00H ;返回DOSINT 21H ;结束CODE ENDSEND START六、DOS功能调用在DOS软中断指令中最常用的是系统功能调用(INT 21H),主要完成文件管理,输入/输出设备控制,系统参数操作等等。

单片机2位加减乘除(参考实验范例)

单片机2位加减乘除(参考实验范例)

first_ge equ 60h ;伪指令first_shi equ 61hsecond_ge equ 62hsecond_shi equ 63hresult_ge equ 64hresult_shi equ 65hresult_bai equ 66hresult_qian equ 67hal equ 68hp_can bit 40hc_can bit 41hover bit 42horg 0000hljmp startorg 0050hstart:mov first_ge,#0mov first_shi,#0mov second_ge,#0mov second_shi,#0mov al,#5mov result_ge,#0mov result_shi,#0mov result_bai,#0mov result_qian,#0mov 45h,#0mov 46h,#0mov 35h,#0mov 36h,#0mov 37h,#0mov 38h,#0clr p_canclr c_canclr overmov 10h,#0main: lcall xianshimov p0,#0f0hmov a,p0cjne a,#0f0h,next ;判断是否有键按下ljmp mainnext: lcall delay ;延时去斗mov p0,#0f0hmov a,p0cjne a,#0f0h,key_num ;确定有键按下ljmp mainlcall xianshikey_num:mov p0,#0f0h ;取键值mov a,p0mov 20h,amov p0,#0fhmov a,p0add a,20hmov 10h,await: mov P0,#0f0h ;等键放开mov a,P0cjne a,#0f0h,waitmov a,10hlcall displaylcall xianshiljmp main;============================== display: ;判断键值cjne a,#0eeh,next1ljmp display0next1:cjne a,#0edh,next2ljmp display1next2:cjne a,#0ebh,next3ljmp display2next3:cjne a,#0e7h,next4ljmp display3next4:cjne a,#0deh,next5ljmp display4next5:cjne a,#0ddh,next6ljmp display5next6:cjne a,#0dbh,next7ljmp display6next7:cjne a,#0d7h,next8ljmp display7next8:cjne a,#0beh,next9ljmp display8next9:cjne a,#0bdh,nextaljmp display9nexta:cjne a,#0bbh,nextbljmp displayanextb:cjne a,#0b7h,nextcljmp displaybnextc:cjne a,#7eh,nextdljmp displaycnextd:cjne a,#7dh,nexteljmp displaydnexte:cjne a,#7bh,nextfljmp displayenextf:cjne a,#77h,wrongljmp displayfwrong:ret;===================================display0: ;1jb c_can,d_0_0jb p_can,d_0_1mov first_ge,#1setb p_canretd_0_1: mov 61h , 60hmov 60h,#1retd_0_0:jb p_can,d_0_2mov second_ge,#1setb p_canretd_0_2:mov 63h , 62hmov 62h,#1retdisplay1: ;4jb c_can,d_1_0jb p_can,d_1_1mov first_ge,#4setb p_canretd_1_1: mov 61h , 60hmov 60h,#4retd_1_0:jb p_can,d_1_2mov second_ge ,#4setb p_canretd_1_2: mov 63h , 62hmov 62h,#4retdisplay2: ;7jb c_can,d_2_0jb p_can,d_2_1mov first_ge,#7setb p_canretd_2_1: mov 61h , 60hmov 60h,#7retd_2_0:jb p_can,d_2_2mov second_ge,#7setb p_canretd_2_2:mov 63h , 62hmov 62h,#7setb p_canretdisplay3: ;clrmov first_ge,#0mov first_shi,#0mov second_ge,#0mov second_shi,#0mov al,#5mov result_ge,#0mov result_shi,#0mov result_bai,#0mov result_qian,#0mov 45h,#0mov 46h,#0mov 35h,#0mov 36h,#0mov 37h,#0mov 38h,#0clr p_canclr c_canclr overmov 10h,#0retdisplay4: ;2jb c_can,d_4_0jb p_can,d_4_1mov first_ge,#2setb p_canretd_4_1: mov 61h , 60hmov 60h,#2retd_4_0:jb p_can,d_4_2mov second_ge,#2setb p_canretd_4_2:mov 63h , 62hmov 62h,#2setb p_canretdisplay5: ;5jb c_can,d_5_0jb p_can,d_5_1mov first_ge,#5setb p_canretd_5_1: mov 61h , 60hmov 60h,#5retd_5_0: jb p_can,d_5_2mov second_ge,#5setb p_canretd_5_2:mov 63h , 62hmov 62h,#5setb p_canretdisplay6: ;8jb c_can,d_6_0jb p_can,d_6_1mov first_ge,#8setb p_canretd_6_1: mov 61h , 60hmov 60h,#8retd_6_0:jb p_can,d_6_2mov second_ge,#8setb p_canretmov 62h,#8setb p_canretdisplay7: ;0jb c_can,d_7_0jb p_can,d_7_1mov first_ge,#0setb p_canretd_7_1: mov 61h , 60hmov 60h,#0retd_7_0:jb p_can,d_7_2mov second_ge,#0setb p_canretd_7_2:mov 63h , 62hmov 62h,#0setb p_canretdisplay8: ;3jb c_can,d_8_0jb p_can,d_8_1mov first_ge,#3setb p_canretd_8_1: mov 61h , 60hmov 60h,#3retd_8_0:jb p_can,d_8_2mov second_ge,#3setb p_canretd_8_2:mov 63h , 62hmov 62h,#3setb p_canretdisplay9: ;6jb c_can,d_9_0jb p_can,d_9_1mov first_ge,#6setb p_canretmov 60h,#6retd_9_0:jb p_can,d_9_2mov second_ge,#6setb p_canretd_9_2:mov 63h , 62hmov 62h,#6setb p_canretdisplaya: ;9jb c_can,d_a_0jb p_can,d_a_1mov first_ge,#9setb p_canretd_a_1: mov 61h , 60hmov 60h,#9retd_a_0:jb p_can,d_a_2mov second_ge,#9setb p_canretd_a_2:mov 63h , 62hmov 62h,#9setb p_canretdisplayb: ;=setb overmov a,al;````````````````cjne a,#0,d_b_0 ;加法程序mov a,first_shiswap aorl a,first_gemov 45h,amov a,second_shiswap aorl a,second_geadd a,45hda ajnc bai_no_addmov result_bai,#1bai_no_add:mov 46h,aanl a,#0fhmov result_ge,amov a,46hanl a,#0f0hswap amov result_shi,aret;``````````````````````````````d_b_0:cjne a,#1,d_b_1 ;减法程序mov a,first_shiswap aorl a,first_gemov 45h,amov a,second_shiswap aorl a,second_gemov 46h,amov a,#9ah ;取补码9ahsubb a,46hadd a,45hda amov 46h,aanl a,#0fhmov result_ge,amov a,46hanl a,#0f0hswap amov result_shi,aret;``````````````````d_b_1:cjne a,#2,tiao ;乘法程序sjmp chengtiao:ljmp d_b_2;-----------------;十进制个位与个位相乘cheng:mov a,first_gemov b,second_gemul ab ;结果不大于81,存放于a中mov b,#10div ab ;十位数存于a,个位数存于bmov result_ge,b ;求出个位数mov 35h,a ;存十位寄35h;-----------------;个位与十位相乘mov a,first_shimov b,second_gemul abmov b,#10div abmov 36h,a ; 存百位寄存36hmov a,badd a,35hmov 35h,a ;clr csubb a,#10jc bai_no_jin_1inc 36h;如有进位,加一mov 35h,abai_no_jin_1:mov a,36hclr csubb a,#10jc qian_no_jin_1inc 37hmov 36h,aqian_no_jin_1: ;----------------------;十位与个位相乘mov a,first_gemov b,second_shimul abmov b,#10div abmov 33h,a ;结果寄放clr cmov a,badd a,35hmov 35h,a ;十位处理clr csubb a,#10jc bai_no_jin_2inc 36hmov 35h,abai_no_jin_2:mov a,33hadd a,36hmov 36h,a ;百位处理clr csubb a,#10 ;千位处理jc qian_no_jin_2inc 37hmov 36h,aqian_no_jin_2:;--------------------------;十位与十位相乘mov a,first_shimov b,second_shimul abmov b,#10div abmov 33h,aclr cmov a,badd a,36hmov 36h,aclr csubb a,#10jc qian_no_jin_3inc 37hmov 36h,aqian_no_jin_3:mov a,33hadd a,37hmov 37h,a ;--mov result_shi,35hmov result_bai,36hmov result_qian,37hret;```````````````````````````d_b_2:cjne a,#3,d_b_3 ;除法程序mov a,first_shiswap aorl a,first_gemov 45h,a ;第一个bcd码数字存放mov a,second_shiswap aorl a,second_gemov 46h,a ;第二个bcd码数字存放recom:mov a,45hclr csubb a,46hjc xiaomov a,#9ahsubb a,46hadd a,45hda amov 45h,ainc 38hjmp recomxiao:mov a,38hmov b,#10div abmov result_shi,amov result_ge,bret;d_b_3:retdisplayc: ;+mov al,#0setb c_canclr p_canretdisplayd: ;-mov al,#1setb c_canclr p_canretdisplaye: ;*mov al,#2setb c_canclr p_canretdisplayf: ;/mov al,#3setb c_canclr p_canret;========================delay:mov r7,#10loop0:mov r6,#08fhloop1:djnz r6,loop1djnz r7,loop0ret ;===================================xianshi:mov dptr,#TABjb over,over_loopjb c_can,c_loopmov a,first_ge ;显示第一个数movc a,@a+dptrmov P1,amov P2,#0fehlcall delaymov P1,#0ffhmov P2,#0ffhmovc a,@a+dptrmov P1,amov P2,#0fdhlcall delaymov P1,#0ffhmov P2,#0ffhret;-----------------------;显示第二个数c_loop:mov a,second_gemovc a,@a+dptrmov P1,amov P2,#0fehlcall delaymov P1,#0ffhmov P2,#0ffhmov a,second_shimovc a,@a+dptrmov P1,amov P2,#0fdhlcall delaymov P1,#0ffhmov P2,#0ffhretover_loop: ;显示运算结果mov a,result_gemovc a,@a+dptrmov P1,amov P2,#0fehlcall delaymov P1,#0ffhmov P2,#0ffhmov a,result_shimovc a,@a+dptrmov P1,amov P2,#0fdhlcall delaymov P1,#0ffhmov P2,#0ffhmov a,result_baimovc a,@a+dptrmov P1,amov P2,#0fbhlcall delaymov P2,#0ffhmov a,result_qianmovc a,@a+dptrmov P1,amov P2,#0f7hlcall delaymov P1,#0ffhmov P2,#0ffhretTAB: DB 0C0H,0F9H,0A4H,0B0H,99H ;0,1,2,3,4, DB 92H,82H,0F8H,80H,90H ;5,6,7,8,9,DB 88H,83H,0C6H,0A1H,86H ;A,B,C,D,E,DB 8EH;f。

无符号大整数相乘优化算法及

无符号大整数相乘优化算法及

Win32下无符号大整数相乘优化算法及其C++实现Lightning[0GiNr]1、问题的引出:两个无符号的大整数相乘是一道实践意味很浓的算法题目,这里的“无符号”(unsigned) 指的是相乘的两个数都是正数,不需要考虑符号。

由于32 位计算机没有指令支持128 及以上二进制位数的大整数的运算,所以必须自己设计算法来计算。

传统的优化算法基本上都是理论层面上的优化,即尽可能地从理论上减少乘法次数,但是往往不能达到预想的优化效果。

比方说二分法优化:将待相乘的整数M分成相等的左右两个部分M1和M2,另一个相乘整数N也同样地分成N1和N2,然后按这样的方法递归分割,直到最后的元素大小小到可以利用CPU旨令直接计算为止。

这时利用公式M*N= (M1 + M2) * (N1 + N2) = M1*N1 + M1*N2 + M2*N1 + M2*N2 结合移位运算再逐层返回得出最终结果。

显然这种算法理论性过强,一来只有当M和N为2的P次方(P为正整数)时的优化才会节省时间,而实际情况下应对随机数据时则会出现大量位移操作,速度不会得到提升;二来使用的递归算法由于调用栈和跳转指令的开销,浪费大量CPU时间;三来这种方法实际上并没有真正地减少乘法次数,因为除了最后一层递归中的乘法可以直接用CPU指令实现,其余各层的乘法由于数值较大仍得另想办法。

由此,我们须从实际出发,探索一些实用的优化方法。

本程序的测试环境为:Windows XP SP2 32bit + 512MB SDRAM + P4 1.80Ghz + VC2、朴素的算法思路:为了简易起见,我们先来设计一个朴素的算法。

使用一个DWOR类型的数组m_buffer作为缓冲区,大小为64,同时声明一个int类型的变量m_nUsed 记录当前缓冲中DWOR使用的个数(即后面所提到的“位数”)。

类的声明如下:代码清单:BigNumber.cpp#include <windows.h>#include <stdio.h>class CBigNumber{public:CBigNumber(){memset(this, 0, sizeof(*this)); m_nUsed = 1;}CBigNumber& operator = (DWORD dwData);CBigNumber& operator *= (const CBigNumber& right);int GetCount() const { return m_nUsed; }const DWORD* GetBuffer() const { return m_buffer; }protected:VOID OffsetAdd(DWORD dwData, int nOffset);int m_nUsed;DWORD m_buffer[64];};首先是赋值函数,这个函数将一个DWOR类型的整数转化到CBigNumber中。

哈工大单片机实验报告

哈工大单片机实验报告

软件实验在软件实验部分,通过实验程序的调试,使学生熟悉MCS-51的指令系统,了解程序设计过程,掌握汇编语言设计方法以及如何使用实验系统提供的调试手段来排除程序错误。

实验一清零程序一、实验目的掌握汇编语言设计和调试方法,熟悉键盘操作。

二、实验内容把2000~20FFh的内容清零。

三、程序框图四、实验过程(1)实验中定义R0为循环次数,利用定义了初值的数据指针DPTR不断加1指向需要被清零的外部数据存储器单元。

(2)再利用MOVX语句,将外部存储器指定内容清零。

(3)用CJNE比较语句判断循环是否结束。

五、实验结果及分析问题回答:清零前2000H~20FFH中为内存里的随机数,清零后全变为0。

六、实验源程序;清零程序ORG 0000HMOV DPTR,#2000HMOV R0,#0FFHORG 0660HMAIN: MOV A,#00HMOVX @DPTR,AINC DPTRDJNZ R0,MAINEND实验二拆字程序一、实验目的掌握汇编语言设计和调试方法。

二、实验内容把2000h的内容拆开,高位送2001h低位,低位送2002h低位,2001h、2002h高位清零,一般本程序用于把数据送显示缓冲区时用。

三、程序框图四、实验过程(1)定义数据指针DPTR为2000H,将其中内容送入累加器A中,利用高低四位交换语句SWAP可将高四位移至低四位,再用语句ANL与0FH进行与操作取出高四位送入2001H低位(2)再次让数据指针DPTR为2000H,将其中内容送入累加器A中,直接与0FH相与取出低四位送入2002H低位。

五、实验结果及分析问题回答:将ANL A,#0FH改为ORL A,#0F0H可以实现将高位置为1。

六、实验源程序;拆字程序ORG 0000HMAIN: MOV DPL, #00HMOV DPH, #20HMOVX A, @DPTRSWAP AANL A, #0FHINC DPTR-3-MOVX @DPTR, AMOV DPL,#00HMOVX A, @DPTRANL A, #0FHINC DPTRINC DPTRMOVX @DPTR, AEND实验三拼字程序一、实验目的进一步掌握汇编语言设计和调试方法。

单片机作业与习题.

单片机作业与习题.

3-11 假设累加器A的内容为30H,执行命令:
1000H: MOVC A,@A+PC
后,把程序存储器单元 的内容送累加器中。
分析:本条指令是PC作为基址的编址寻址方式, 关键是找到基址和变址的数值。
本条指令的地址是1000H,执行完本条指令 后PC加一(单字节指令),即1001H。
变址为(A)=30H,即寻址的程序存储器 单元(1001H+30H)的内容。
;#64H ;#0AH
(R0)(R1,R2)
TBCD: MOV R0,A MOV R1,#00H MOV R2,#00H MOV R3, #08H
LOOP: CLR C MOV A,R0 RLC A MOV R0, A MOV A, R1 ADDC A, R1 DA A MOV R1, A MOV A, R2 ADDC A, R2
3-10 假设外部数据存储器2000H单元的内容 为80H,执行下列命令后,累加器A中的内容 为:
MOV P2, #20H
MOV R0, #00H
MOVX A, @R0
分析: MOVX A, @R0指令寻址方式 为寄存器间接寻址。R0作为低8位, P2作为高8位。在数据存储器扩展 时,P2口作为地址的高8位。
第三次作业
3.6, 3.9, 3.10, 3.11, 3.12,3.15。 10月26日交。
3.9 试编写程序,将片外RAM的2000H、 2001H两个单元的内容分别存入片内RAM的 20H单元和寄存器R7中。 MOV DPTR,#2000H MOVX A,@DPTR MOV 20H,A INC DPTR MOVX A, @DPTR MOV R7,A
方法一: TRSL: MOV DPTR, #1000H

微机原理与接口技术实验指导书(xin)

微机原理与接口技术实验指导书(xin)

DVCC实验仪器简介微机原理及接口技术实验采用DVCCJH598实验仪器完成。

通过实验,可使学生基本掌握MCS-51单片机的结构、原理、接口技术、编程技巧。

实验过程,将实验仪器与PC机通过串行口连接。

实验仪器布局如图1所示。

图1 DVCCJH598实验仪布局图实验源程序在DVCCJH598实验软件上输入。

软件界面如图2所示。

图2 DVCC软件界面其中各菜单功能如下:文件:主要完成文件新建、打开已有文件、保存。

编译:包括编译文件、编译连接文件、编译连接并传送文件。

编译主要检查源文件语法错误,如没有语法错误,编译器将生成源文件的目标代码。

编译连接文件:主要针对多文件汇编,可以对多文件编译并连接成目标文件。

编译连接并传送文件:编译连接并将目标文件传送给DVCC实验仪。

选项:完成对实验仪的设置。

动态调试:对文件进行单步或连续运行。

实验指南:给出相关实验的目标、内容、原理图等。

第一部分软件实验实验一清零程序一、实验目的二、实验内容把7000H-70FFH的内容清零。

三、实验程序框图四、主要仪器设备及耗材微机原理与接口技术实验板、PC机五、实验步骤1)将DVCC仿真实验系统联PC机;2)在PC机上输入源程序,并编译;3)联接DVCC实验系统,装载目标文件;4)设置PC起始地址5)从起始地址开始连续运行程序(F9)或单步(F8)或断点运行程序6)单步、断点运行完后,在存贮器窗口内检查7000H-70FFH中的内容是否全为00H。

六、思考题假使要把7000H-70FFH中的内容改成FF,如何编制程序?实验二拆字程序一、实验目的掌握汇编语言设计和调试方法。

二、实验内容把7000H的内容拆开,高位送7001H低位,低位送7002H低位。

7001H、7002H高位清零,一般本程序用于把数据送显示缓冲区时用。

三、实验框图四、主要仪器设备及耗材微机原理与接口技术实验板、PC机五、实验步骤1)将DVCC仿真实验系统联PC机;2)在PC机上输入源程序,并编译;3)联接DVCC实验系统,装载目标文件;4)用存贮器读写方法将7000H单元置成34H;5)设置PC起始地址0050H6)从起始地址开始连续运行程序(F9)或单步(F8)或断点运行程序7)单步、断点运行完后,在存贮器窗口内检查7001H和7002H单元中的内容是否为03H 和04H。

8051单片机实验

8051单片机实验

新建项目
项目窗口
(4) 单击快捷工具栏中的“编译”图标(或 F9键),对刚才保存的项目进行编译和连接, 如图所示。
在编译之前,软件会自动将项目中的源程 序文件存盘。如果发生编译连接错误,则 在“信息窗口”中报告如图所示编译连接 出错信息。此时可将鼠标指向“信息窗口” 中的错误行并双击鼠标左键,光标将自动 跳转到编辑窗口中源程序的相应出错位置, 便于用户修改。修改源程序文件并保存之 后,重新进行第(3)步。
从P1.0输出不同频率的方波信号,经放 大滤波后驱动扬声器发声。声音的频率由延 时程序控制。实验电路如下图所示,执行程 序后,扬声器将发出一定频率的声音。
程序参考流程 如右图所示:
复习思考题
复习8051单片机并行I/O端口特性, P0~P3口各有什么特点?
为什么说P1口是“准双向口”?在实 验中用P1口输入时如果不先向P1口写入 “1”而直接读取引脚,会出现什么现象?
② 模拟交通信号灯控制。
8051单片机中断系统
8051单片机有5个中断源,有两个 中断优先级,高优先级的中断源可以中 断低优先级的服务程序,反之不行。当 两个同样级别的中断申请同时到来时, 则按一个固定的查寻次序来处理中断响 应。
中断源 入口地址
外部中断0 0003H
定时/计数器0 000BH
外部中断1 0013H
D7 D6 D5 D4 D3 D2 D1 D0
EA
ES ET1 EX1 ET0 EX0
EA:中断总允许位。 EA=0,CPU关闭所有的中断申请; EA=1,允许各个中断源的中断申请,但 还要取决于各中断源中断允许控 制位的状态。
ES:串行口中断允许位。 ES=1,串行口开中断; ES=0,串行口关中断。

无符号双字节快速乘法子程序实验心得

无符号双字节快速乘法子程序实验心得

无符号双字节快速乘法子程序实验心得
在本次实验中,我们研究了无符号双字节快速乘法子程序的实现方法和性能。

这个子程序可以在不使用乘法运算符的情况下,实现双字节数的快速乘法运算,从而提高计算效率。

在实验中,我们首先了解了快速乘法的原理,即将乘法运算转化为位运算和加法运算的组合。

通过使用位运算符和位移操作,我们可以将乘法转化为加法和移位的操作,从而减少计算量。

然后,我们根据这个原理编写了无符号双字节快速乘法的子程序。

该子程序接受两个双字节数作为输入,并返回它们的乘积。

在子程序的实现中,我们使用了位运算符来进行位运算操作,以及位移操作来实现移位运算。

通过合理地组织这些操作,我们可以快速地计算出乘积。

在实验中,我们进行了多组测试,验证了无符号双字节快速乘法子程序的正确性和效率。

对于测试数据中的不同组合,我们发现无符号双字节快速乘法子程序的计算结果与使用乘法运算符得到的结果完全
一致。

而且,与传统的乘法运算相比,无符号双字节快速乘法子程序具有更快的计算速度和较小的计算复杂度。

通过本次实验,我们深入了解了无符号双字节快速乘法子程序的设计原理和实现方法。

这种方法不仅可以提高计算效率,还可以减少计算
复杂度。

在实际的程序开发中,我们可以将这个子程序应用于需要大量乘法运算的场景,从而提高整体的计算性能。

51单片机编程实例大全

51单片机编程实例大全

//实例 16:用 P0 显示左移运算结果
#include<reg51.h> //包含单片机寄存器的头文件 void main(void) {
P0=0x3b<<2;//将左移运算结果送 P0 口,P0=1110 1100B=0xec while(1)
; //无限循环,防止程序“跑飞” }
//实例 17:"万能逻辑电路"实验
}
//实例 10:用 P0、P1 口显示乘法运算结果
#include<reg51.h> //包含单片机寄存器的头文件 void main(void) {
unsigned char m,n; unsigned int s; m=64;
n=71; s=m n; 位送 P0 口
/256 除以 256 的商 的余数
//s=64 71=4544,需要 16 位二进制数表示,高 8 位送 P1 口,低 8
//由于 4544=17 256+192=H3 16 16 16+H2 16 16+H1 16+H0 //两边同除以 256,可得 17+192/256=H3 16+H2+(H1 16+H0)
//因此,高 8 位 16 进制数 H3 16+H2 必然等于 17,即 4544
//无限循环
{ P1=0xfe; //P1=1111 1110B, P1.0 输出低电平 delay(); //延时一段时间 P1=0xff; //P1=1111 1111B, P1.0 输出高电平 delay(); //延时一段时间
}
}
//实例 3:将 P1 口状态分别送入 P0、P2、P3 口:认识 I/O 口 的引脚功能

常见51单片机指令及详解

常见51单片机指令及详解

常见51单片机指令及详解数据传递类指令(1)以累加器为目的操作数的指令MOV A,RnMOV A,directMOV A,@RiMOV A,#data第一条指令中,Rn代表的是R0-R7。

第二条指令中,direct就是指的直接地址,而第三条指令中,就是我们刚才讲过的。

第四条指令是将立即数data送到A中。

下面我们通过一些例子加以说明:MOV A,R1 ;将工作寄存器R1中的值送入A,R1中的值保持不变。

MOV A,30H ;将内存30H单元中的值送入A,30H单元中的值保持不变。

MOV A,@R1 ;先看R1中是什么值,把这个值作为地址,并将这个地址单元中的值送入A中。

如执行命令前R1中的值为20H,则是将20H单元中的值送入A中。

MOV A,#34H ;将立即数34H送入A中,执行完本条指令后,A中的值是34H。

(2)以寄存器Rn为目的操作的指令MOV Rn,AMOV Rn,directMOV Rn,#data这组指令功能是把源地址单元中的内容送入工作寄存器,源操作数不变。

(3)以直接地址为目的操作数的指令MOV direct,A 例: MOV 20H,AMOV direct,Rn MOV 20H,R1MOV direct1,direct2 MOV 20H,30HMOV direct,@Ri MOV 20H,@R1MOV direct,#data MOV 20H,#34H(4)以间接地址为目的操作数的指令MOV @Ri,A 例:MOV @R0,AMOV @Ri,direct MOV @R1,20HMOV @Ri,#data MOV @R0,#34H(5)十六位数的传递指令MOV DPTR,#data168051是一种8位机,这是唯一的一条16位立即数传递指令,其功能是将一个16位的立即数送入DPTR中去。

其中高8位送入DPH,低8位送入DPL。

例:MOV DPTR,#1234H,则执行完了之后DPH中的值为12H,DPL中的值为34H。

整数加减乘除计算器-C51单片机

整数加减乘除计算器-C51单片机

C51单片机-整数加减乘除计算器本程序是基于技能大赛设备,所使用的模块为显示模块、主机模块和指令模块。

此计算器适合10位以内的加减乘除运算,除法没有小数位,只取整数位。

此程序仅供参考,可以相互学习使用。

/* ---简易整数计算器--- */#include<reg52.h> //包含AT89s52头文件#define uchar unsigned char#define uint unsigned int#define ulong unsigned long/* ---1602液晶控制引脚--- */sbit rs=P2^0;sbit rw=P2^1;sbit e=P2^2;#define port P0 //1602数据端口#define port3 P3 //矩阵键盘uchar code tab[]="0123456789+-*/=c";ulong a1,a2,aa; //没有小数点的长整型变量uchar jsf; //运算符/* ---微秒延时--- */void delay(uint i){while(i--);}/* ---1602液晶各子函数--- */ void busy1602(){port=0xff;rs=0;rw=1;e=1;e=1;while(port&0x80);e=0;}void writecom(uchar com){busy1602();rs=0;rw=0;port=com;e=1;e=0;}void writedat(uchar dat){busy1602();rs=1;rw=0;port=dat;e=1;e=0;}void showstr(bit row,uchar col,uchar *s) //显示字符串{uchar i;writecom(0x80+row*0x40+col);for(i=0;s[i]!=0;i++){writedat(s[i]);}}void shownum(bit row,uchar col,ulong num) //显示数字{writecom(0x04);writecom(0x80+row*0x40+col);if(num>=0)writedat(num%10+'0');if(num>9)writedat(num/10%10+'0');if(num>99)writedat(num/100%10+'0');if(num>999)writedat(num/1000%10+'0');if(num>9999)writedat(num/10000%10+'0');if(num>99999)writedat(num/100000%10+'0');if(num>999999)writedat(num/1000000%10+'0');if(num>9999999)writedat(num/10000000%10+'0');if(num>99999999)writedat(num/100000000%10+'0');if(num>999999999)writedat(num/1000000000%10+'0');if(num>4294967294)showstr(0,4,"rorrE");}void init1602() //1602 初始化{writecom(0x38);writecom(0x0c);writecom(0x06);writecom(0x01);/* ---按键扫描程序--- */uchar keyscan(){uchar key=16,i;for(i=0;i<4;i++){port3=0xfe<<i|0xfe>>(8-i); //循环左移switch(port3&0xf0){case 0xe0:key=4*i;break;case 0xd0:key=4*i+1;break;case 0xb0:key=4*i+2;break;case 0x70:key=4*i+3;break;}}return key;}/* ---运算--- */void js()switch(jsf){case '+':aa=a1+a2;break;case '-':if(a1>=a2)aa=a1-a2;else if(a1<a2)aa=a2-a1;break;case '*':aa=a1*a2;break;case '/':if(a2==0)aa=' ';else aa=a1/a2; break;}}void main(){uchar k;bit b=0,a;init1602();showstr(0,3,"jisuanqi");while(1){if(keyscan()!=16&&b==0){delay(200);if(keyscan()!=16){b=1;k=keyscan();if(k==0||k==1||k==2||k==3||k==4||k==5||k==6||k==7||k==8||k= =9) //数字键{if(a==0){a1=a1*10+k;writecom(0x01);shownum(1,15,a1);}else{a2=a2*10+k;writecom(0x01);shownum(1,15,a2);}}else if(k==10||k==11||k==12||k==13) //+-*/键{a=1;writecom(0x01);switch(k){case 10:jsf='+';showstr(1,15,"+");break;case 11:jsf='-';showstr(1,15,"-");break;case 12:jsf='*';showstr(1,15,"*");break;case 13:jsf='/';showstr(1,15,"/");break;}}else if(k==14) //等号键{a=0;js();writecom(0x01);if(aa==' ')showstr(0,0,"Error"); //被除数为零不显示,第一行显示错误else shownum(1,15,aa);if(jsf=='-'&&a1<a2)showstr(1,0,"-"); // aa是负数,前边添加负号else showstr(1,0," ");}else if(k==15) //清零键{a=0;a1=a2=aa=0;jsf=0;writecom(0x01);shownum(1,15,0);}}}else if(keyscan()==16)b=0;}}。

ARM无符号整数乘除法

ARM无符号整数乘除法

ARM的无符号整数乘除法ARM无符号整数乘法一、实验目的掌握ARM的汇编语言程序设计方法。

二、实验原理及基本技术线路图ARM的乘法指令把一对寄存器的内容相乘,然后根据指令类型把结果累加到其它的寄存器。

长整形的“乘累加”要使用代表64位的一对寄存器,最终的结果放在一个目标寄存器或者一对寄存器中。

乘法指令的语法:MLA {<cond>}{S} Rd,Rm,Rs,Rn长整型乘法指令产生64位的结果。

由于结果太大,不能存放在一个32位寄存器,所以把结果存放在2个32位的寄存器RdLo和RdHi中。

RdLo存放低32位,RdHi存放高32位。

利用UMULL和SUMLL指令可以进行32位宽度的无符号或有符号的整数乘法运算,得到64位的结果。

在实际应用中,有许多需要长整型乘法运算的应用。

例如,处理C中long long整型算术运算等。

对于64位整数乘法运算可利用如下页图所示的扩展方法来实现。

其中:R0,R1分别存放被乘数的低32位和高32位;R2,R3分别存放乘数的低32位和高32位;128位结果由低到高依次存放在R4,R5,R6,R7中。

三、实验内容依据图2-1框图所示方法编制2个64位无符号整数乘法的程序。

四、所用仪器、材料PC一台EmbestIDE Education Edition for ARM五、实验方法、步骤●在Embest IDE环境中新建工程,编写程序;●编译成功后,连接下载进行调试。

六、实验过程原始记录(数据、图表、计算等)1. 实验A源程序:.global _start.text_start:MOV R8,#20 @低32位初始化为20MOV R9,#0 @高32位初始化为0MOV R0,R8,#1 @初始化计数器Loop:MOV R1,R9 @暂存高位值UMULL R8,R9,R0,R8×+图2-1:2个64位无符号整数乘法的扩展方法LHL HH H LLMlLA R9,R1,R0,R9SUBS R0,R0,#1BNE loopStop:B Stop.end七、实验结果、分析和结论(误差分析与数据处理、成果总结等。

实验报告 实验三无符号二进制数的乘法运算

实验报告  实验三无符号二进制数的乘法运算

EDA实验报告之实验三无符号双字节数的乘法运算1、实验目的:熟悉软件的操作,掌握算术操作类指令;2、实验要求:1)、进一步熟悉熟悉软件的操作;2)、熟悉算术操作类指令;3)、写出实验报告。

3、实验题目:无符号双字节数的乘法运算1)、编写程序,把内部RAM地址为5BH、5AH 和59H、58H中的两个双字节无符号二进制数相乘(其中5BH与5AH中的内容构成一个乘数,高位在5BH中;59H与58H中的内容构成另一个乘数,高位在59H中),把乘积放在内部RAM的5FH、5EH、5DH和5CH单元中(高位在5FH单元中)。

2)、把乘积转换为压缩的BCD码,结果放在内部RAM的4FH、4EH、4DH、4CH和4BH 单元中(高位在4FH单元中)。

4、实验内容:1)使用的仪器、仪表,开发平台型号本实验用到了wave6000软件。

电脑一台。

2)性能指标、技术要求、思路方案、软件流程图性能指标、技术要求见实验题目部分;思路方案:(下页)思路方案:双字节无符号二进制数相乘算法原理:设a、b、c、d都是8位二进制数,z是8位二进制数0,则abⅹcd=(az+zb)(cz+zd)+) 字节4 字节3 字节2 字节1 可见用4次乘法指令和多次加法指令可求出乘积.多字节二进制数转换为BCD 数子程序BINBCD2 算法原理:156700772012345672))2)2)2((((((22)(d d d d d d d d d d d d d d d +⨯+⨯+⨯+⨯=⨯++⨯= 举例:十进制数 二进制数1)二进制数左移1位, C=1 十进制ADDC \ DA2)二进制数左移1位, C=0 十进制ADDC \ DA3)二进制数左移1位, C=1 十进制ADDC \ DA4)二进制数左移1位, C=1十进制ADDC \ DA对应于原来二进制的高4位注意: * 例中乘2^7 ,但移位8次, 其中十进制单元第一次自身相加时扣除了一次乘2操作;* ADDC 配合DA 指令可以实现 ……i i d d +⨯+2)1 操作 ;流程图:双字节无符号二进制数相乘流程图1:设A,B,C,D都是8位二进制数,计算AB*CD多字节二进制数转换为BCD数子程序BINBCD2 流程图2:多字节二进制数转换为压缩BCD数:3)源程序ORG 0000HMOV R0,#5CH ;乘积存放地址低位MUL1:MOV A,5AH ;求b*dMOV B,58HMUL ABMOV @R0,A ;存放bdL,字节1MOV R3,B ;暂存bdHMOV A,5BHMOV B,58H ;求a*dMUL ABADD A,R3MOV R3,A ;(R3)=adL+bdH,字节2MOV A,BADDC A,#0MOV R2,A ;(R2)=adH+求字节2时可能的进位,字节3MOV A,5AH ;求b*cMOV B,59HMUL ABADD A,R3INC R0 ;地址加一MOV @R0,A ;字节2= adL+bdH+bcLMOV A,BADDC A,R2MOV R2,A ; (R2)=adH+bcH+求字节2时可能的进位,字节3 MOV R1,#0JNC LAST ;求刚才的字节3时有无向上的进位INC R1 ;地址加一LAST:MOV A,5BH ;求a*cMOV B,59HMUL ABADD A,R2INC R0 ;地址加一MOV @R0,A ;存放acL+ adH+bcH,字节3MOV A,BADDC A,R1 ;ach+进位INC R0MOV @R0,A ;存放ach+进位,字节4MOV R5,#04H ;二进制字节数计数器MOV R1,#10H ;内部RAM单元MOV R0,#5CH ;刚才的乘积低位地址LOOP: ;此循环实现数据的搬移MOV A,@R0MOV @R1,AINC R0INC R1DJNZ R5,LOOPBINBCD2:MOV R1,#4BH ;转换后存到地址(低位)MOV R2,#04H ;二进制数字节数INC R2 ;转换后的BCD字节数比二进制数字节数多一个CLR ABB0:MOV @R1,AINC R1DJNZ R2,BB0MOV A,#04H ;求“X”出现的总次数MOV B,#8MUL ABMOV R3,ABB3:M OV R0,#10HMOV R2,#04HCLR CBB1:MOV A,@R0 ;二进制数左移1位,最高位在C中RLC AMOV @R0,AINC R0DJNZ R2,BB1MOV R2,#04HINC R2 ;十进制字节数比二进制字节数多1MOV R1,#4BHBB2:MOV A,@R1 ;十进制数X 2 ,十进制调整ADDC A,@R1 ;二进制左移一位后的CDA AMOV @R1,AINC R1DJNZ R2,BB2DJNZ R3,BB3SJMP $4)实验步骤,完成情况4.1 在WAVE 6000中新建文件,并将代码写入文件中,保存为EXPERIMENT3.ASM;4.2 在WAVE 6000中新建项目,并在模块文件中包含上述EXPERIMENT3.ASM文件,最后保存为EXPERIMENT3.PRG。

MCS-51实验指导书

MCS-51实验指导书

单片机仿真实验系统MCS-51实验指导书南昌大学本实验指导是为适应单片机原理与应用方面的课程需做大量软硬件实验的需要而编写的,供学生编程用。

完成本实验指导中的实验,可使学生基本掌握MCS-51单片机的结构原理、接口技术、程序设计技巧。

实验指导书中详细叙述了各实验的目的、内容,列出了接线图、程序框图和实验步骤。

单片机实验注意事项:1:主CPU为8032,需要扩充一片6264作为数据区,连接6264的读写信号到CPU的读写信号,连接CS1到A15;连接数据线,连接地址高低线;2:实验仪上的波段开关必须选择9600波特率,和51系统;3:接线和拔线时必须断电, PC微机必须与本实验系统保持联机状态,即软件界面右上角有编译进度条,确定连机状态才可调试程序;4:通过RS232通信接口,利用上位机实现用户程序的编辑、编译和调试运行。

在软件的设置栏内,点击仿真模式,选择系统、系统;注意:上位机的存盘文件名只能用英文字母和数字组合,长度不能超过8位且存盘路径必须在默认的C 盘DAIS目录下;5:系统接口实验电路为单元电路方式,数据总线以8芯扁平线形式引出,硬件学生连线为电路图上粗实线。

部分机器硬件介绍可参考微机原理实验指导书。

目录软件实验部分:实验一清零程序实验二拆字程序实验三拼字程序实验四数据区传送子程序实验五数据排序实验实验六查找相同数个数实验七无符号双字节快速乘法子程序实验八多分支程序实验九脉冲计数(定时/计数器实验)实验十电脑时钟(定时器、中断综合实验)硬件实验部分:实验一 P1口亮灯实验实验二 P1口转弯灯实验实验三 P3.3口输入,P1口输出实验四工业顺序控制实验五继电器控制实验六 8255控制交通灯实验七 LED16×16点阵显示实验实验八串并转换实验实验九 A/D转换实验实验十 D/A转换实验十一电子音响实验十二步进电机控制实验十三 8032串行口应用实验㈠——双机通信实验十四小直流电机调速实验软件实验部分本节共编了十个软件实验,通过这些实验程序的调试,使学生熟悉MCS-51的指令系统,了解程序设计过程,掌握汇编语言设计方法以及如何使用实验系统提供的调试手段来排除程序错误。

实验三 两个数相乘实验

实验三 两个数相乘实验

实验三两个数相乘实验一、实验目的掌握乘法指令和循环指令的用法。

二、实验内容实现十进制数的乘法。

被乘数和乘数均以ASCII码形式存放在内存中,乘积在屏幕上显示出来。

三、程序框图四、程序清单及分析DAT A SEGMENT ; 定义数据段DAT A1 DB 32H,39H,30H,35H,34H ;定义被乘数DAT A2 DB 33H ; 定义乘数RESULT DB 6 DUP(00H) ; 定义乘积存放位置DAT A ENDSST ACK SEGMENT ;定义堆栈段ST A DB 20 DUP(?) ; 从ST A开始留出20个单元作为堆栈空间TOP EQU LENGTH ST A ; 给TOP赋值ST ACK ENDSCODE SEGMENT ; 定义代码段ASSUME CS:CODE,DS:DAT A,SS:ST ACK,ES:DAT AST ART: MOV AX,DAT AMOV DS,AX ; 给DS赋初值MOV AX,ST ACKMOV SS,AX ; 给SS赋初值MOV AX,TOPMOV SP,AX ; 给SP赋初值MOV SI,OFFSET DAT A2MOV BL,[SI] ;取乘数AND BL,00001111B ;乘数ASCLL转化为十六进制数MOV SI,OFFSET DAT A1 ;取被乘数偏移地址MOV DI,OFFSET RESULT ; 取乘积存放的偏移地址MOV CX,05 ; 乘5次LOOP1: MOV AL,[SI] ; 取被乘数AND AL,00001111B ;被乘数ASCLL转化为十六进制数INC SI ; 指向下一个被乘数字节(高位)MUL BL ; 乘法运算AAM ;乘法调整,AH←AL/10所得的商AL←AL/10所得的余数ADD AL,[DI] ;乘积低位加部分乘积AAA ;非压缩形式BCD码调整指令MOV [DI],AL ;存调整后的低位积INC DIMOV [DI],AH ;存调整后的高位积LOOP LOOP1 ;判断乘法运算是否结束MOV CX,06 ; 取六个乘积字节MOV SI,OFFSET RESULT ;给定乘积存放的起始地址DISPL: MOV AH,02 ; 调用2号系统功能调用MOV DL,[SI+5] ; 取出乘积(从高位开始取)ADD DL,30H ; 将乘积的十六位进制数转化为ACSLL码INT 21H ;调用2号调用进行显示DEC SILOOP DISPL ; 判断是否6位显示结束MOV AX,4C00H ;显示结束,调用4CH号系统功能调用INT 21H ; 返回系统提示符状态CODE ENDS ; 代码段结束END ST ART ; 整个程序结束程序运行结果如下图所示:。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档