汇编语言流程图++
- 格式:ppt
- 大小:493.50 KB
- 文档页数:67
【例】试编写一程序计算以下表达式的值。
w = (v- (x * y + z -540 )) /x式中x、y、z、v均为有符号字数据。
设x、y、z、v的值存放在字变量X、Y、Z、V中,结果存放在双字变量W之中,程序的流程图如图所示。
DATA SEGMENTX DW 200Y DW 100Z DW 3000V DW 10000W DW 2 DUP (?)DATA ENDSSTACK SEGMENT STACKDB 200 DUP (0)STACK ENDSCODESEGMENTASSUME DS DATA CS: CODE SS: STACKSTART MOV AX DATAMOV DS AX ; DATA>AXMOV AX XIMUL Y ; (X) * (DX AXMOV CX AXMOV BX,DX ;(DX AX)TBX:CX)MOV AX,ZCWD ;(Z)符号扩展ADD CX,AXADC BX,DX;(BX: CX)+( DX:AX)BX:CX)SUB CX,540SBB BX,0 ;( BX:CX) - 5 40~BX:CX)MOV AX,VCWD ;(V)符号扩展SUB AX,CXSBB DX,BX ;( DX:AX)-((BX CX DX: AX)IDIV X ;( DX:AX)/XMOV W,AX ;商5MOV W+2 DX ;余数D©W+2MOV AH,4CHINT 21HCODEENDS ;退出DOS 状态END START【例】已知某班学生的英语成绩按学号(从 1 开始)从小到大的顺序排列在要查的学生的学号放在变量NO中,查表结果放在变量ENGLISH中。
编写程序如下: STACK SEGMENT STACKDB 200 DUP(0)STACK ENDSDATA SEGMENTTAB DB 80 ,85,86,71,79,96DB 83 ,56,32,66,78,84NO DB 10ENGLIST DB ?DATA ENDSCODE SEGMENTASSUME DS: DATA,SS: STACK,CS: CODEBEGIN: MOV AX,DATAMOV DS,AXLEA BX,TABMOV AL,NODEL ALXLAT TABMOV ENGLIS,H ALMOV AH,4CHINT 21HCODEENDSTAB表中,END BEGIN【例】已知在内存中有一个字节单元NUM存有带符号数据,要求计算出它的绝对值后, 放入RESULT^元中。
课程设计报告--汇编程序设计(进制转换)汇编语言课程设计报告:代码与数制之间的转换内容提要:本课程设计的主要内容是代码与数制之间的转换~程序的主要功能如下:1. 将十六进制数转换成其对应的ASCII码2. 将ASCII码转换成其对应的十六进制数3. 实现二进制数与十六进制数之间相互转换4. 实现十进制数与二进制数之间相互转换5. 实现十六进制数与十进制数之间相互转换数制转换是计算机科学技术中最为基础的运算~在日常生活中~人们习惯性地使用十进制数进行计算。
而在计算机内部~所有的信息,数、字符、汉字、计算机的指令、状态,都是用二进制数来表示的。
在计算机中~二进制数的运算、处理比十进制数的更容易实现。
有时为了缩短书写~在计算机中还采用十六进制数。
所以~我们需要把数从二进制数形式转换成其他进制的形式~甚至在不同的进位制之间进行转换。
- 1 -汇编语言课程设计报告:代码与数制之间的转换目录一、前言〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃3 1.1 程设计的目的〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃3 1.2 代码与数制之间的转换程序的意义〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃3 1.3 数制之间的转换程序的主要功能〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃3正文〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃3 二、2.1 代码与数制之间相互转换程序的设计大纲〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃3 2.2 代码与数制之间相互转换程序的结构图〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃4 2.3 友好交互界面结构图〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃5 2.4 程序流程图〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃62.4.1 主程序流程图〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃62.4.2 键盘输入子程序流程图〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃62.4.3 ASC码转16进制子程序流程图〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃72.4.4 16进制转ASC进制子程序流程图〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃82.4.5 2,16进制子程序流程图〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃82.4.6 2?16进制子程序流程图〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃92.4.7 16?2进制子程序流程图〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃92.4.8 2~10进制子程序流程图〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃102.4.9 2?10进制子程序流程图〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃102.4.10 10?2进制子程序流程图〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃112.4.11 10~16进制子程序流程图〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃112.4.12 10?16进制子程序流程图〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃122.4.13 16?10进制子程序流程图〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃12三、源程序及其注释〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃13四、课程设计体会〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃29五、参考文献〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃〃29- 2 -汇编语言课程设计报告:代码与数制之间的转换课程设计题目:代码与数制之间的转换一、前言1.1 课程设计的目的, 加深对汇编语言课程理论方面的理解, 通过编写一定规模和难度的程序,进行一次较全面的汇编编程训练,提高分析问题和解决问题的能力, 提高调试程序的能力1.2 代码与数制之间的转换程序的意义数制转换是计算机科学技术中最为基础的运算,在日常生活中,人们习惯性地使用十进制数进行计算。
实验一汇编程序的汇编及运行1.实验目的和要求1、熟悉汇编程序的汇编、连接、执行过程2、生成LST文件,查看LST文件3、生成OBJ文件,修改语法错误4、生成EXE文件5、执行2.实验环境IBM—PC机及其兼容机实验的软件环境是:操作系统:DOS 2.0以上;调试程序:;文本编程程序:EDIT.EXE、WPS.EXE;宏汇编程序:MASM.EXE(或ASM .EXE);连接装配程序:LINK .EXE;交叉引用程序:CREF.EXE(可有可无)。
3.实验内容及实验数据记录1、将数据段输入,取名1.txt,保存在MASM文件夹下。
生成LST文件,(不必连接、运行)用EDIT查看1.LST文件。
试回答:DA1,DA2的偏移量分别是多少?COUNT的值为多少?DATA SEGMENTORG 20HNUM1=8NUM2=NUM1+10HDA1 DB ‘IBM PC’DA2 DB 0AH, 0DHCOUNT EQU $-DA1DATA ENDSEND2、输入有错误的文件,修改错误语句。
(MASM没有出现错误即可。
不必连接、运行。
)DATA SEGMENTVAR1 DB 0, 25, ODH, 300VAR2 DB 12H, A4H, 6BHVAR3 DB ’ABCDEF’VAR4 DW 1234H, 5678HVAR5 DW 10H DUP(?)DATA ENDSCODE SEGMENTASSUME CS: CODE, DE: DATA BEING MOV AX, DATAMOV DS, AXLEA SI, VAR5MOV BX, OFFSET VAR2MOV [SI], 0ABHMOV AX, VAR1+2MOV [BX], [SI]MOV VAR5+4, VAR4MOV AH, 4CHINT 21HCODE ENDSEND START3、输入正确的程序,汇编、连接、运行STACKS SEGMENT STACKDW 128 DUP(?)STACKS ENDSDATAS SEGMENTSTRING DB ‘WELCOME!’, 13, 10, ‘$’DATAS ENDSCODES SEGMENTASSUME CS: CODES, DS: DATASSTART:MOV AX, DATASMOV DS, AXLEA DX, STRINGMOV AH, 9INT 21HMOV AH, 4CHINT 21HCODES ENDSEND START4.算法描述及实验步骤(1)编写源程序。
. . . .一、设计题目编写计算N!的程序(数值N由键盘输入,结果在屏幕上输出。
N的围为0-65535,即刚好能被一个16位寄存器容纳)。
二、开发目的由于当N值较大时(N>10),N的阶乘计算很繁琐并且计算容易出错。
所以可以编写计算N!的程序,利用计算机强大的计算能力计算N!。
这不仅能节省繁琐计算的时间,而且得到的N!的积比起手工算的要准确。
三、设计方案N的阶乘为1*2*3……(N-1)*N,N的围为(0000H—FFFFH),N!以字为单位存在一个或几个定义的数据段中。
若已算到(n-1)!,假如它占4个字的空间,接下来它乘以n的原理,如图1所示。
图1 (n-1)!* n的原理因此计算N!的算法可以这样编写,当前n!的值为被乘数,容存在str2中,单位为字,n+1的值为乘数,存在str1中,单位也为字。
被乘数从str2首地址中容开始与乘数相乘,得到32位的积,它的低16位覆盖掉当前被乘数所在存储空间的容。
接着str2下一个字的容与乘数相乘,也得到32位的积,前一个积的高16位与现在积的低16位相加,它们的和覆盖掉当前被乘数所在存储空间的容,若它们的和有进位,把进位加到现在积的高16位。
直到把str2中容乘完。
然后乘数增1,循环上面的容。
直到执行完(N-1)!*N输入的N 为4位16进制数,输出也为16进制数。
四、 程序流程图YNNNNYY五、程序清单data1 segmentinput1 db 'please input the number :','$'input2 db 10,?,10 dup(?) ;输入的16进制数error db 'Out of range','$'output1 db 'The answer is 1','$'output2 db 'The answer is :','$'str1 dw 100 dup(?) ;保存1—N(后一个数覆盖前一个数)str2 dw 7000h dup(?) ;N!乘积的值(1)p dw 100 dup(?) ;上一个乘积的高16位data1 endsdata2 segmentstr3 dw 7fffh dup(?) ;N!乘积的值(2)data2 endscode segmentassume cs:code,ds:data1,es:data2org 100h ;程序从偏移地址100h开始执行start: mov ax,data1 ;程序初始化mov ds,axmov ax,data2mov es,ax ;初始化结束mov ah,9lea dx,input1int 21hmov ah,2 ;回车mov dl,0dhint 21hmov ah,2 ;换行mov dl,0ahint 21hmov ah,0ah ;输入所需求的N值(N为16进制数)lea dx,input2int 21hmov ah,2mov dl,0dhint 21hmov ah,2mov dl,0ahint 21hlea bx,input2mov al,[bx+1] ;判断输入的N值是否超过FFFFHcmp al,4ja s1mov cl,4 ;把输入的N值有ASCH码转成16进制数mov ah,[bx+2]mov al,[bx+3]cmp al,39hja abc1def1: shl al,clcmp ah,39hja abc2def2: shr ax,clmov dh,almov ah,[bx+4]mov al,[bx+5]cmp al,39hja abc3mov cl,4def3: shl al,clcmp ah,39hja abc4def4: shr ax,clmov dl,al ;转换结束mov ax,dx ;判断N值是否为0cmp ax,0jz s2jmp s3abc1: sub al,37hjmp def1abc2: sub ah,37hjmp def2abc3: sub al,37hjmp def3abc4: sub ah,37hjmp def4s1: mov ah,9 ;若N值超过FFFFH的输出lea dx,errorint 21hjmp nexts2: mov ah,9 ;N值为1的输出lea dx,output1int 21hjmp nexts3: mov cx,ax ;计算N的阶乘mov ax,1mov [str1],ax ;N从1开始,作为乘数lea si,str2mov [si],ax ;N!的积从1开始,作为被乘数mov ax,0mov [p],ax ;(n-1)!的乘积的低16位与n相乘后积的高16位mov bx,1 ;开始N!的乘积占一个字空间mov WORD ptr[p+10],0 ;(n-1)!的乘积的高16位与n相乘后积的低16位和(n-1)!的乘积的低16位与n相乘后积的高16位的和的进位,初始进位为0mov ah,9lea dx,output2int 21hmov ah,2mov dl,0dhint 21hmov ah,2mov dl,0ahint 21hlop2: mov [p+2],bxlop3: mov ax,[si] ;(n-1)!的乘积从最低16位的容与n相乘mov dx,[str1]mul dxclcadd ax,[p+10] ;前一次的进位与当前乘积的低16位容相加jnc k1 ;判断是否产生进位mov WORD ptr[p+10],1add ax,[p] ;前一个积的高16位与现在积的低16位相加jmp k2k1: add ax,[p]jnc k3 ;判断是否产生进位mov WORD ptr[p+10],1jmp k2k3: mov WORD ptr[p+10],0k2: mov [si],axmov [p],dxadd si,2dec bxcmp bx,0jnz lop3mov bx,[p+2]clcadd dx,[p+10]cmp dx,0jz re ;判断(n-1)!乘积的最高16位容与n的乘积的高16位是否为0inc bxmov [si],dxre: mov ax,[str1]cmp ax,9000h ;判断是N!乘积的容高位部分是否要存到es中jnc re1jmp re2re1: cmp cx,1ja s4re2: inc WORD ptr[str1] ;乘数增1lea si,str2mov WORD ptr[p],0mov WORD ptr[p+10],0loop lop2dec bxmov cx,bxlop4: add si,2loop lop4inc bxadd bx,bxinc sijmp lop5s4: inc WORD ptr[str1] ;若N的值超过8000h,8000h*8001h*8002h*N mov [p+6],bxmov [p+8],bxlea si,str2lea di,str3mov es:[di],dxmov WORD ptr[p],0mov WORD ptr[p+10],0mov bx,1dec cxlop6: mov [p+4],bxlop7: mov ax,[si]mov dx,[str1]mul dxclcadd ax,[p+10]jnc k4mov WORD ptr[p+10],1add ax,[p]jmp k5k4: add ax,[p] ;前一个积的高16位与现在积的低16位相加,产生进位jnc k6mov WORD ptr[p+10],1jmp k5k6: mov WORD ptr[p+10],0k5: mov [si],axadd si,2mov [p],dxdec WORD ptr[p+6]mov ax,[p+6]cmp ax,0jnz lop7mov ax,[p+8]mov [p+6],axlop8: mov ax,es:[di]mov dx,[str1]mul dxclcadd ax,[p+10]jnc k7mov WORD ptr[p+10],1add ax,[p]jmp k8k7: add ax,[p] ;前一个积的高16位与现在积的低16位相加,产生进位mov WORD ptr[p+10],1jmp k8k9: mov WORD ptr[p+10],0 k8: mov es:[di],axadd di,2mov [p],dxdec bxcmp bx,0jnz lop8mov bx,[p+4]clcadd dx,[p+10]cmp dx,0jz re4inc bxmov es:[di],dxre4: inc WORD ptr[str1]lea si,str2lea di,str3mov WORD ptr[p],0mov WORD ptr[p+10],0dec cxcmp cx,0jnz lop6dec bxmov cx,bxlop9: add di,2loop lop9inc bxadd bx,bxinc dilop10: dec bx ;若N>8000h,输出N!乘积的高位容mov al,BYTE ptr es:[di]mov ch,almov cl,4shr al,clcmp al,09hja op3add al,30hjmp ip3op3: add al,37h ip3: mov ah,2mov dl,alint 21hmov al,chand al,0fhcmp al,09hja op4add al,30hjmp ip4op4: add al,37h ip4: mov ah,2mov dl,alint 21hdec dicmp bx,0jnz lop10mov bx,[p+6]dec bxmov cx,bx lop11: add si,2inc bxadd bx,bxinc silop5: dec bx ;输出N!的乘积mov al,BYTE ptr [si]mov ch,almov cl,4shr al,clcmp al,09hja op1add al,30hjmp ip1op1: add al,37hip1: mov ah,2mov dl,alint 21hmov al,chand al,0fhcmp al,09hja op2jmp ip2op2: add al,37hip2: mov ah,2mov dl,alint 21hdec sicmp bx,0jnz lop5next: mov ah,1int 21hmov ah,4chint 21hcode endsend start六、程序运行结果与分析若输入的16进制数N为000A(10进制为10),程序运行后输出的N!应为375F00(H)。
汇编语言编程实验报告学号:姓名:成绩:目录一、实验一: ......................................................错误!未定义书签。
二、实验二: (4)三、实验三: (8)四、实验四: (10)五、实验五: ......................................................错误!未定义书签。
六、实验六: (19)七、汇编实验总结 (23)实验一一. 实验题目【汇编语言补充作业T20T20】编写完整程序,利用】编写完整程序,利用DOS 系统功能调用,从键盘输入一个字符串,并将该字符串从屏幕上换行后并输出。
二. 程序流程及思路实现字符串输入,需要分成三个步骤:实现字符串输入,需要分成三个步骤:1、在数据段中定义一个缓存区为存放字符串做准备;2、DOS 系统功能调用0AH 号子功能,(DS:DX DS:DX))= = 输入缓冲区首址;输入缓冲区首址;输入缓冲区首址;3、在输入的字符串尾加上‘、在输入的字符串尾加上‘$$’字符,以作为输出结束条件。
’字符,以作为输出结束条件。
实现字符串输出,则需要注意的问题是:实现字符串输出,则需要注意的问题是:1、缓冲区第三个字节才开始存放输入的字符,前两个字节分别存放缓冲区长度和字符串实际字符数;和字符串实际字符数;2、输出回车换行可利用字符串:、输出回车换行可利用字符串:CR DB 0AH,0DH,CR DB 0AH,0DH,CR DB 0AH,0DH,’’$’。
’。
三. 源程序清单DATA SEGMENTN EQU 50MAXLEN DB N ;MAXLEN DB N ;缓冲区字符的最大长度缓冲区字符的最大长度缓冲区字符的最大长度ACTLEN DB ? ;ACTLEN DB ? ;实际字符个数实际字符个数实际字符个数STRING DB N DUP(?) ;STRING DB N DUP(?) ;字符空间字符空间字符空间CR DB 0AH,0DH,'$'DATA ENDSCODE SEGMENTASSUME CS:CODE,DS:DATA,SS:STACKSTART: MOV AX,DATAMOV DS,AXLEA DX,MAXLENMOV AH,0AHINT 21H ;字符串输入字符串输入MOV AH,09HLEA DX,CRINT 21H ;回车换行回车换行MOV BL,MAXLEN+1 ;取实际的字符长度取实际的字符长度MOV BH,0LEA SI,MAXLEN+2 ;取字符开始的首地址取字符开始的首地址MOV BYTE PTR [SI+BX],'$' ;输出结尾要加上输出结尾要加上$ $MOV DX,SI ;把开始存放字符的首地址赋给DX(注:以下程序采用b方法)方法)。
安徽工程大学《汇编语言程序设计》大作业报告班级: XXXXX 学号: XXXXXXXX 完成人: XXXXXXX任课老师: XXXXXXX 时间: XXXXXXXXXX《汇编语言程序设计》大作业任务书大作业题目:四则运算程序程序功能要求:编写一个程序,每运行一次可执行程序,可以实现加减乘除四则运算。
计算器是最简单的计算工具,简单计算器具有加、减、乘、除四项运算功能。
1.设计目标运用汇编语言,制作一个计算的程序,实现简单计算器的一般功能,能够在DOS界面下进行简单的加、减、乘、除的简单计算。
程序应有操作提示、输入和输出。
自动闪烁光标,并提示输入信息。
输入正确的数值等符号后可以进行正确的运算,程序计算其结果值并输出。
程序无需查错功能,所输入的都是正确的四则运算表达式,并且表达式中运算分量均为无正负号整数,运算符为+、-、*、/,最后结果以十进制数表示。
且程序主界面需为一个由‘*’组成边框的矩形窗口。
2.软件设计2.1程序设计的基本思想主模块:首先提供一个主界面,提示用户按要求输入具体的数据和所要进行的操作,输入完毕后给出结果。
如果输入过程中发现非法输入,则立即给与提示,程序自动刷新界面,提示继续输入。
计算显示完毕后,按提示选择是否要继续计算,不选择继续则结束。
对屏幕上输入字符串的接受,为INPUT语句段,见源代码,主要是将数字和运算符分开存放。
MATCH子程序,子程序内有三次跳转,将运算符选择正确的语句进行计算。
由于操作符只有+、-、*、/,没有涉及到括号,不用考虑括号的匹配问题。
流程图如下:图1 主模块流程图子模块:完成对数据的进一步加工处理,转换格式并得出结果。
首先根据输入调用对应的“+”、“-”、“*”、“/”四个函数模块,这是本程序的核心模块,其他部分的一些小模块都是为这几个模块服务的,大致的流程图如下图2:图2 子模块流程图3.系统调试3.1测试目标(1)在屏幕上显示一个由‘*’组成边框的矩形窗口;(2)自动闪烁光标,并提示输入信息;(3)能够完成单项表达式的输入、显示和运算;(4)编制并调试出程序。
实验报告课程名称微机原理与汇编语言学院计算机工程学院班级 11计3Z 学号 ******** 姓名王祖陆2013年05月27日设计一个汇编语言程序,具体内容如下:一、功能:(1)从键盘输入N个带符号数(N的值也从键盘输入,N<=65535);带符号数为16位二进制数范围);(2)找出这N个数中的最大值和最小值,并且显示出来;(3)计算这N个数的平均值,并且显示出来。
二、程序分析:(1)需要对程序进行N的值的输入,来确定循环的次数,决定了循环的次数就可以确定数组元素的个数,为下一步数组元素的值的输入做准备。
(2)由(1)中确定N的值来决定循环的次数,每一次的循环,指针向后移两位,因为我们定义的时候是字大小,占用2个字节的空间,每一次的循环调用一次输入函数,以确定数组中每个元素的值。
(3)调用清屏语句将屏幕上的输入的痕迹清除,同时用循环调用输出函数,将用户之前输入的值按一定的格式输出到屏幕上。
(4)判断最大数最小数,用循环遍历数组中的每一个元素,同时与最大数最小数进行比较,如果该数比最大数大,则将其保存到最大数中,如果该数比最小数小,则将其保存到最小数中。
(注:最大数和最小数需要开辟内存空间来保存,同时在进入循环之前应该给其一个值,这里我给的是数组中第一个元素的值)(5)计算平均数,同样用循环将其累加的和除以N的值即得到最终的结果三、程序相关说明:(1)程序中,COUNT保存的是循环的次数,即数组的个数N(2)A RRAY为定义的数组,MAXAY,MINAY分别对应的是最大数,最小数,WTEMP为临时变量(3)M ESS系列保存的内容为输入输出时的提示信息无实际作用(4)I NPUT子函数为输入N的值,READ函数为输入一个-32768~+32767的数,WRITE为输出函数,即将数组中某一元素的值输出,IFMAX函数为判断最小值最大值函数,MEAN函数为求平均值函数(5)D PCRLF、NDPCRLF子函数为输出格式控制函数四、程序流程图主程序流程图 INPUT函数流程图NREAD函数流程图 WRITE函数流程图IFMAX函数流程图 MEAN函数流程图五、源程序列表文件内容:Microsoft (R) Macro Assembler Version 5.00 5/27/13 18:44:33Page 1-10000 DSEG SEGMENT ;数据段 0000 50 6C 65 61 73 65 20 MESS1 DB 'Please input N "N<=65535":','$'69 6E 70 75 74 20 4E20 22 4E 3C 3D 36 3535 33 35 22 3A 24001B 50 6C 65 61 73 65 20 MESS2 DB 'Please input a number:','$'69 6E 70 75 74 20 6120 6E 75 6D 62 65 723A 240032 59 6F 75 72 20 69 6E MESS3 DB 'Your input is as follows:',0AH,0DH,'$'70 75 74 20 69 73 2061 73 20 66 6F 6C 6C6F 77 73 3A 0A 0D 24004E 0A 0D 4D 41 58 3A 24 MESS4 DB 0AH,0DH,'MAX:','$'0055 0A 0D 4D 49 4E 3A 24 MESS5 DB 0AH,0DH,'MIN:','$'005C 0A 0D 41 56 45 52 41 MESS6 DB 0AH,0DH,'AVERAGE:','$',0AH,0DH47 45 3A 24 0A 0D0069 03E8[ ARRAY DW 1000 DUP(0)0000]0839 COUNT DW ?083B WTEMP DW ?083D MAXAY DW ?083F MINAY DW ?0841 DSEG ENDS0000 SSEG SEGMENT STACK ;堆栈段 0000 0080[ DB 80H DUP(0)00]0080 SSEG ENDS0000 CSEG SEGMENT ;代码段ASSUME DS:DSEG,SS:SSEG,CS:CSEG0000 B8 ---- R START: MOV AX,DSEG0003 8E D8 MOV DS,AX0005 BA 0000 R MOV DX,OFFSET MESS10008 B4 09 MOV AH,09H000A CD 21 INT 21H000C E8 009F R CALL INPUT ;调用INPUT函数 000F 8B 0E 0839 R MOV CX,COUNT0013 BB 0069 R MOV BX,OFFSET ARRAY0016 BA 001B R AGAIN1: MOV DX,OFFSET MESS20019 B4 09 MOV AH,9H001B CD 21 INT 21H001D E8 00AB R CALL READ ;调用READ函数0020 89 07 MOV [BX],AXMicrosoft (R) Macro Assembler Version 5.00 5/27/13 18:44:33Page 1-20022 83 C3 02 ADD BX,20025 E8 0185 R CALL DPCRLF ;循环COUNT次0028 E2 EC LOOP AGAIN1002A B0 03 MOV AL,3H002C CD 10 INT 10H002E 8B 0E 0839 R MOV CX,COUNT0032 BB 0069 R MOV BX,OFFSET ARRAY0035 BA 0032 R MOV DX,OFFSET MESS30038 B4 09 MOV AH,9H003A CD 21 INT 21H003C 8B 07 AGAIN2: MOV AX,[BX]003E A3 083B R MOV WTEMP,AX0041 E8 00EC R CALL WRITE ;调用WRITE函数 0044 83 C3 02 ADD BX,20047 E8 0196 R CALL NDPCRLF ;调用NDPCRLE函数 004A E2 F0 LOOP AGAIN2 ;执行COUNT次循环 004C B4 02 MOV AH,2004E B2 0D MOV DL,0DH0050 CD 21 INT 21H0052 B2 0A MOV DL,0AH0054 CD 21 INT 21H0056 8B 0E 0839 R MOV CX,COUNT005A B8 0069 R MOV AX,OFFSET ARRAY005D E8 0130 R CALL IFMAX ;调用IFMAX函数0060 BA 004E R MOV DX,OFFSET MESS40063 B4 09 MOV AH,09H0065 CD 21 INT 21H0067 A1 083D R MOV AX,MAXAY006A A3 083B R MOV WTEMP,AX006D E8 00EC R CALL WRITE ;调用WRITE函数输出MAXAY0070 BA 0055 R MOV DX,OFFSET MESS50073 B4 09 MOV AH,09H0075 CD 21 INT 21H0077 A1 083F R MOV AX,MINAY007A A3 083B R MOV WTEMP,AX007D E8 00EC R CALL WRITE ;调用WRITE函数输出MINAY0080 BA 005C R MOV DX,OFFSET MESS60083 B4 09 MOV AH,09H0085 CD 21 INT 21H0087 A1 0839 R MOV AX,COUNT008A 50 PUSH AX008B B8 0069 R MOV AX,OFFSET ARRAY008E 50 PUSH AX008F E8 0157 R CALL MEAN0092 83 C4 04 ADD SP,40095 A3 083B R MOV WTEMP,AX0098 E8 00EC R CALL WRITE ;调用WRITE函数输出平均值Microsoft (R) Macro Assembler Version 5.00 5/27/13 18:44:33Page 1-3009B B4 4C MOV AH,4CH009D CD 21 INT 21H009F INPUT PROC009F 50 PUSH AX00A0 E8 00AB R CALL READ00A3 A3 0839 R MOV COUNT,AX00A6 E8 0185 R CALL DPCRLF00A9 58 POP AX00AA C3 RET00AB INPUT ENDP00AB READ PROC00AB 53 PUSH BX00AC 51 PUSH CX00AD 52 PUSH DX00AE 33 DB XOR BX,BX ;寄存器BX,CX清零00B0 33 C9 XOR CX,CX00B2 B4 01 MOV AH,1H00B4 CD 21 INT 21H00B6 3C 2B CMP AL,'+' ;是“+”,继续输入字符 00B8 74 07 JZ READ100BA 3C 2D CMP AL,'-' ;是“-”,设置-1标志00BC 75 07 JNZ READ200BE B9 FFFF MOV CX,-100C1 B4 01 READ1: MOV AH,1H ;继续输入字符00C3 CD 21 INT 21H00C5 3C 30 READ2: CMP AL,'0' ;不是0-9之间的字符,则输入结束00C7 72 16 JB READ300C9 3C 39 CMP AL,'9'00CB 77 12 JA READ300CD 2C 30 SUB AL,30H ;是0-9之间的字符,则转换为二进制数,利用移位指令,实现数值乘1000CF D1 E3 SHL BX,100D1 8B D3 MOV DX,BX00D3 D1 E3 SHL BX,100D5 D1 E3 SHL BX,100D7 03 DA ADD BX,DX00D9 B4 00 MOV AH,0H00DB 03 D8 ADD BX,AX ;已输入数值乘10后,与新输入数值相加00DD EB E2 JMP READ100DF 83 F9 00 READ3: CMP CX,000E2 74 02 JZ READ400E4 F7 DB NEG BX ;是负数,进行求补00E6 8B C3 READ4: MOV AX,BX00E8 5A POP DX00E9 59 POP CX00EA 5B POP BX00EB C3 RET00EC READ ENDP00EC WRITE PROC00EC 50 PUSH AXMicrosoft (R) Macro Assembler Version 5.00 5/27/13 18:44:33Page 1-400ED 53 PUSH BX00EE 52 PUSH DX00EF A1 083B R MOV AX,WTEMP ;列出显示数据00F2 85 C0 TEST AX,AX ;判断数据是零、正数或负数00F4 75 09 JNZ WRITE100F6 B2 30 MOV DL,'0' ;是零,显示‘0’后退出00F8 B4 02 MOV AH,200FA CD 21 INT 21H00FC EB 2E 90 JMP WRITE500FF 79 0C WRITE1: JNS WRITE2 ;是负数,显示‘-’ 0101 8B D8 MOV BX,AX0103 B2 2D MOV DL,'-'0105 B4 02 MOV AH,20107 CD 21 INT 21H0109 8B C3 MOV AX,BX010B F7 D8 NEG AX ;数据求补010D BB 000A WRITE2: MOV BX,100110 53 PUSH BX0111 3D 0000 WRITE3: CMP AX,00114 74 0A JZ WRITE40116 2B D2 SUB DX,DX0118 F7 F3 DIV BX011A 80 C2 30 ADD DL,30H ;余数转换为ASCII 码011D 52 PUSH DX011E EB F1 JMP WRITE30120 5A WRITE4: POP DX0121 80 FA 0A CMP DL,100124 74 06 JE WRITE50126 B4 02 MOV AH,20128 CD 21 INT 21H ;进行显示012A EB F4 JMP WRITE4012C 5A WRITE5: POP DX012D 5B POP BX012E 58 POP AX012F C3 RET0130 WRITE ENDP0130 IFMAX PROC0130 56 PUSH SI0131 53 PUSH BX0132 8B F0 MOV SI,AX0134 49 DEC CX0135 8B 04 MOV AX,[SI]0137 8B D8 MOV BX,AX0139 83 C6 02 MAXCK: ADD SI,2013C 39 04 CMP [SI],AX013E 7E 05 JLE MINCK0140 8B 04 MOV AX,[SI] ;如果AX<[SI]则将[SI]值存入AX0142 EB 07 90 JMP NEXT0145 39 1C MINCK: CMP [SI],BX0147 7D 02 JGE NEXT0149 8B 1C MOV BX,[SI] ;如果BX>[SI]则将[SI]值存入BX014B E2 EC NEXT: LOOP MAXCKMicrosoft (R) Macro Assembler Version 5.00 5/27/13 18:44:33Page 1-5014D A3 083D R MOV MAXAY,AX0150 89 1E 083F R MOV MINAY,BX0154 5B POP BX0155 5E POP SI0156 C3 RET0157 IFMAX ENDP0157 MEAN PROC0157 55 PUSH BP0158 8B EC MOV BP,SP015A 53 PUSH BX ;保护寄存器015B 51 PUSH CX015C 52 PUSH DX015D 56 PUSH SI015E 57 PUSH DI015F 8B 5E 04 MOV BX,[BP+4] ;从堆栈中取出缓冲区偏移地址存入BX0162 8B 4E 06 MOV CX,[BP+6] ;从堆栈中取出数据个数存入CX中0165 33 F6 XOR SI,SI ;SI清零,保存求和低16位0167 8B FE MOV DI,SI ;DI 保存求和高16位0169 8B 07 MEAN1: MOV AX,[BX]016B 99 CWD ;符号扩展 DX016C 03 F0 ADD SI,AX016E 13 FA ADC DI,DX0170 83 C3 02 ADD BX,2H0173 E2 F4 LOOP MEAN10175 8B C6 MOV AX,SI0177 8B D7 MOV DX,DI0179 8B 4E 06 MOV CX,[BP+6]017C F7 F9 IDIV CX ;有符号数除法,求的平均值在AX中017E 5F POP DI ;恢复寄存器017F 5E POP SI0180 5A POP DX0181 59 POP CX0182 5B POP BX0183 5D POP BP0184 C3 RET0185 MEAN ENDP0185 DPCRLF PROC0185 50 PUSH AX0186 52 PUSH DX0187 B4 02 MOV AH,20189 B2 0D MOV DL,0DH018B CD 21 INT 21H018D B4 02 MOV AH,2018F B2 0A MOV DL,0AH0191 CD 21 INT 21H0193 5A POP DX0194 58 POP AX0195 C3 RET0196 DPCRLF ENDPMicrosoft (R) Macro Assembler Version 5.00 5/27/13 18:44:33 Page 1-60196 NDPCRLF PROC0196 50 PUSH AX0197 52 PUSH DX0198 B4 02 MOV AH,2019A B2 09 MOV DL,9H019C CD 21 INT 21H019E 5A POP DX019F 58 POP AX01A0 C3 RET01A1 NDPCRLF ENDP01A1 CSEG ENDSEND STARTMicrosoft (R) Macro Assembler Version 5.00 5/27/13 18:44:33 Symbols-1Segments and Groups:N a m e Length Align Combine ClassCSEG . . . . . . . . . . . . . . 01A1 PARA NONEDSEG . . . . . . . . . . . . . . 0841 PARA NONESSEG . . . . . . . . . . . . . . 0080 PARA STACKSymbols:N a m e Type Value AttrAGAIN1 . . . . . . . . . . . . . L NEAR 0016 CSEGAGAIN2 . . . . . . . . . . . . . L NEAR 003C CSEGARRAY . . . . . . . . . . . . . L WORD 0069 DSEG Length = 03E8 COUNT . . . . . . . . . . . . . L WORD 0839 DSEGDPCRLF . . . . . . . . . . . . . N PROC 0185 CSEG Length = 0011 IFMAX . . . . . . . . . . . . . N PROC 0130 CSEG Length = 0027INPUT . . . . . . . . . . . . . N PROC 009F CSEG Length = 000CMAXAY . . . . . . . . . . . . . L WORD 083D DSEGMAXCK . . . . . . . . . . . . . L NEAR 0139 CSEGMEAN . . . . . . . . . . . . . . N PROC 0157 CSEG Length = 002E MEAN1 . . . . . . . . . . . . . L NEAR 0169 CSEGMESS1 . . . . . . . . . . . . . L BYTE 0000 DSEGMESS2 . . . . . . . . . . . . . L BYTE 001B DSEGMESS3 . . . . . . . . . . . . . L BYTE 0032 DSEGMESS4 . . . . . . . . . . . . . L BYTE 004E DSEGMESS5 . . . . . . . . . . . . . L BYTE 0055 DSEGMESS6 . . . . . . . . . . . . . L BYTE 005C DSEGMINAY . . . . . . . . . . . . . L WORD 083F DSEGMINCK . . . . . . . . . . . . . L NEAR 0145 CSEGNDPCRLF . . . . . . . . . . . . N PROC 0196 CSEG Length = 000B NEXT . . . . . . . . . . . . . . L NEAR 014B CSEGREAD . . . . . . . . . . . . . . N PROC 00AB CSEG Length = 0041 READ1 . . . . . . . . . . . . . L NEAR 00C1 CSEGREAD2 . . . . . . . . . . . . . L NEAR 00C5 CSEGREAD3 . . . . . . . . . . . . . L NEAR 00DF CSEGREAD4 . . . . . . . . . . . . . L NEAR 00E6 CSEGSTART . . . . . . . . . . . . . L NEAR 0000 CSEGWRITE . . . . . . . . . . . . . N PROC 00EC CSEG Length = 0044 WRITE1 . . . . . . . . . . . . . L NEAR 00FF CSEGWRITE2 . . . . . . . . . . . . . L NEAR 010D CSEGWRITE3 . . . . . . . . . . . . . L NEAR 0111 CSEGWRITE4 . . . . . . . . . . . . . L NEAR 0120 CSEGWRITE5 . . . . . . . . . . . . . L NEAR 012C CSEGWTEMP . . . . . . . . . . . . . L WORD 083B DSEGMicrosoft (R) Macro Assembler Version 5.00 5/27/13 18:44:33 Symbols-2@FILENAME . . . . . . . . . . . TEXT ex263 Source Lines263 Total Lines39 Symbols50026 + 451030 Bytes symbol space free0 Warning Errors0 Severe Errors六、程序运行截图程序输入截图程序输出截图七、总结我比较的满意地方我对程序进行一步步的编写的,这样无形中减轻了自己不小的工作量,因为对一个比较大的程序来说,一次编好整条程序是不可能的,因为无论如何你都不可避免一些错误,如果你一次编好整个程序,那么出现的错误的数量将是不可小觑的,所以我采取的方法是分部来进行的,先把输入函数编好,用debug测试通过后,再进行下一个模块功能的编辑,同样测试通过后才进行下一个模块的编写,主程序不应该包含太多的功能,它存在的目的就是调用子程序,而一个子程序,只要完成一个功能就可以了,我不满意的就是程序格式的书写没掌握好,看程序源代码的时候很费力,后来花了不少的功夫修改了下格式,有时删了一个字母,使得程序在编译的时候出错,所以在编写程序时,程序格式的书写一定要控制好,不然后面很麻烦,记得有一个人曾经说过,具体是谁我忘记了,不过是这样的说的,“好的程序,给人能带来一种美感”所以呢,格式的书写很重要。
用汇编语言实现多字节乘除法计算CPU一般都提供乘除法运算指令,不过能够直接运算的乘除法受限于CPU的字长,如MCS-51单片机是8位的,就只能计算8位二进制乘除法,也就是被乘数、乘数、被除数、除数都小于256的计算。
如果需要计算的数据较大怎么办?加减法我们还可以用先加/减低字节,再带进/借位加/减高字节的方法来计算,但乘除法这样子显然不行。
下面通过分析二进制乘法的计算特点介绍通用的部分积右移乘法运算:首先看乘法,列竖式我们都会的,二进制乘法和十进制的其实也差不多,都是按位相乘,再将各部分积错位相加,不同的是二进制乘法各位相乘时结果只有两种:乘数该位为0时乘积为0,乘数该位为1时乘积即被乘数本身。
如下图所示:图1 二进制乘法竖式计算过程这是一个8位二进制数乘法,过程简明易懂,但是我们怎么将这个过程转化为汇编语言程序呢?下面是根据图1竖式设计的程序流程,很容易看懂,但对于写程序来讲就比较繁琐了,对于乘数的每一位处理方法都不一样,对于每一位乘数我们都要判断它是第几位,然后它和被乘数的积要左移几位相加,这样编出来的程序冗长而且效率很低。
其实我们反过来看,乘数由低到高位每位对应的乘积依次左移一位相加,和每次乘积不动而将结果右移一位相加效果是不是一样的呢?如图3所示:乘数第1位=1?积存储器清零积+被乘数积+0YN乘数第2位=1?积+被乘数左移1位积+0YN乘数第3位=1?积+被乘数左移2位积+0YN。
图2 乘法流程图图3 部分积右移乘法计算过程如此详细的图示相信大家都看明白了,图中第二步到第九步所有的操作都是一样的,乘数带进位右移→积+被乘数或0→积右移。
因此我们可以用循环的方法来设计程序,对于上述8位*8位的乘法需要循环8次,循环次数取决于乘数的位数。
用这样的算法,不管数据的长度是多少,每一位的操作都是一样的,只需要根据乘数的位数修改循环次数就可以了。
下面给出long类型,也就是32位数据的乘法计算程序流程。