汇编语言解一元二次方程程序设计

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

课程设计
题目求解一元二次方程程序设计学院
专业
班级
姓名
指导教师
2013 年 1 月11 日
课程设计任务书
学生姓名: 专业班级:
指导教师: 工作单位:
题 目:求解一元二次方程程序设计
初始条件:带有编辑器、汇编程序、连接程序和调试程序的电脑一台。

要求完成的主要任务:
(包括课程设计工作量及其技术要求,以及说明书撰写等具体要求)
采用汇编语言设计一个程序,求解一元二次方程02=++x bx ax 。

实现从键盘输
入a,b,c 的值,且-128≤a,b,c≤127;显示方程的解,-32768≤X1,X2≤32767; 考虑所有的情况,包含共轭复根。

(1)设计任务及要求分析
(2)方案比较及认证说明
(3)系统原理阐述
(4)软件设计课题需要说明:软件思想,流程图,源程序及程序注释
(5)调试记录及结果分析
(6)总结
(7)参考资料
(8)附录:芯片资料或程序清单,软件演示屏幕拷贝图或硬件实物图
时间安排:
12月31日~1月2日: 收集资料,方案选择
1月3日~1月8日: 整体流程,程序细节
1月9日~1月10日: 调试程序,报告撰写
1月11日: 交设计报告,程序演示,答辩
指导教师签名: 年 月 日
系主任(或责任教师)签名: 年 月 日
目录
摘要 (1)
1 DOS 功能调用 (2)
1.1DOS 功能简介 (2)
1.2DOS 输入/输出功能 (2)
1.2.1单字符输入——0AH 号 (2)
1.2.2单字符输出——2号 (2)
1.2.3过程终止——4CH 号 (2)
1.2.4子程序设计 (3)
2解方程计算过程 (3)
2.1一元二次方程
02=++c bx ax 分析 ............................................................... 3 2.2 求解一元二次方程的流程 .. (4)
2.3各程序段分析编程 (4)
2.3.1DATA 数据段的定义 (4)
2.3.2处理a 、b 、c 的键盘输入 (6)
2.3.3对a 、b 、c 输入的数进行处理 (7)
2.3.4对24b ac -进行的计算处理 (9)
2.3.5对24b ac -的开方计算 (11)
2.3.6计算处理及输出 (13)
2.3.7结果显示操作 (18)
3结果显示分析 (19)
总结与体会 (22)
参考文献 .................................................................................................................................. 23 附录 .......................................................................................................... 错误!未定义书签。

摘要
解一元二次方程02=++x bx ax 。

实现从键盘输入a,b,c 的值,且-
128≤a,b,c≤127;显示方程的解,-32768≤X1,X2≤32767;考虑所有的情况,包含共轭复根。

这本来是一个很简单的数学问题,而要用汇编语言进行解决,就得有一套完整的方案。

编写汇编程序时,要有一个完整的流程图,这需要把自己的方案用流程图的方式简单的体现出来。

根据流程图编写所需要的程序,以完成解方程的目的。

将结果显示到桌面上,按“Q ”或者“q ”则退出程序。

之中有DOS 功能的调用,也有一些新东西的学习。

解决这个编程问题,对微机原理的学习又加深啦!
汇编语言(AssemblyLanguage)是面向机器的程序设计语言。

汇编语言是一种功能很强的程序设计语言,也是利用计算机所有硬件特性并能直接控制硬件的语言。

汇编语言,作为一门语言,保持了机器语言的优点,具有直接和简捷的特点,可有效地访问、控制计算机的各种硬件设备,如磁盘、存储器、CPU 、I/O 端口等,且目标代码简短,占用内存少,执行速度快,是高效的程序设计语言。

虽然现在的高级语言很多,但汇编语言的作用并没有被取代,还在各个领域发挥重要的作用。

关键字:汇编语言 流程图 DOS 功能调用 指令
解方程程序设计
1 DOS功能调用
1.1DOS功能简介
DOS是美国Microsoft公司为IBM PC研制的磁盘操作系统(Disk Operating System),也成为IBM-DOS或MS-DOS。

DOS不仅为用户提供了许多使用命令,而且还有用户可以直接调用上百个常用子程序。

对这些子程序的调用,成为系统调用功能。

这些子程序的功能主要是进行磁盘读/写、控制管理、内存管理、基本输入/输出管理等。

在使用时,用户不需要了解各种I/O端口硬件的详细情况就能直接完成对I/O接口的控制和管理。

为了使用方便,将所有子程序从1号开始编号,这些编号成为DOS 功能调用号。

其调用过程为:
DOS功能调用号送AH寄存器;
如果需要,按要求给定输入参数;
写入中断指令“INT 21H”。

调用结束,按功能使用其输出参数。

1.2DOS输入/输出功能
1.2.1单字符输入——0AH号
功能:多个字符输入到缓冲区
输入参数:DS:DX=输入缓冲区首地址
输出参数:DS:DX=输入字符串所在缓冲区地址
1.2.2单字符输出——2号
功能:从键盘输出个字符
输入参数:DL=ASCII码
输出参数:无
1.2.3过程终止——4CH号
该调用的功能是结束当前程序,并且返回调用它的程序。

如果在DEBUG状态下运行,则返回DEBUG;如果在DOS下运行。

则返回DOS;在汇编语言程序结束处加上“MOV AX ,4C00H”和“INT 21H”两条指令,以便于程序执行完毕,返回操作系统控制。

1.2.4子程序设计
子程序设计思想与主程序设计思想没什么区别。

若程序设计中采用调用子程序的方式,则使程序阅读起来清晰。

因为一个子程序完成一个功能,使得程序调试也方便。

子程序不能单独运行,可以提供给主程序调用、设计子程序要提供以下信息:
子程序的功能;调用时需要的参数;调用后提供的输出参数;子程序中所使用的寄存器。

2解方程计算过程
2.1一元二次方程
02=++c bx ax 分析 一元二次方程02=++c bx ax 的求解,首先对其进行分析。

首先,a=0的情
况不给于讨论,即在a=0是此一元二次方程不成立,需要重新给点a 的值,同时,要对a 、b 、c 进行输入,要保证他们都为数字。

再者要判断所得到的跟是不是重跟,即
要判断24b ac -的大小,如果24b ac -=0,那么两个根重合,输出相同,如果24b ac -<
0,那么次方程有两个共轭虚数跟,24b ac ->0,那么这个方程有两个实数根,不论其跟的情况如何,最后其求根公式求解,由此便可求得方程的跟。

2.2 求解一元二次方程的流程
要用汇编语言对一元二次方程求解,首先编写流程图,根据思路,流程图如图1-1所示:
图1-1 主程序流程图
2.3各程序段分析编程
2.3.1DATA数据段的定义
DATA数据段的定义,首先要定义的就是a、b、c的区间。

本次课设的定义区间将他们设为DB字节型变量,范围是(-128 127),同时定义方程的两个解的以及他们的缓存区间,因为在做输入显示时,缓存区间的定义是很重要的,同时还要定义的就是Q/q返回程序和当a、b、c不在区间范围内的显示以及返回,代码指令如下所示:
data segment
mes0 db 0dh,0ah,'input coefficient of equation: -128<=a,b,c<=127:','$' mes1 db 0dh,0ah,'please input a=','$'
mes2 db 0dh,0ah,'please input b=','$'
mes3 db 0dh,0ah,'please input c=','$'
mes4 db 0dh,0ah,'input data not in the range ,please input again','$' mes5 db 0dh,0ah,'inputq or Q to exit,or input other key to continue....','$'
mes6 db 0dh,0ah,'a=0 leads the equation is not illegal !','$'
mes7 db 0dh,0ah,'the roots of the equation:','$'
mes8 db 0dh,0ah,'please input digital!','$'
crlf db 0dh,0ah,'$'
同时定义a、b、c的输入最大值,用的是0AH指令,因为它定义三个BUFF,可以限制输入a、b、c的字符数,将字符数定义为最多输入四个,限制字符输入,并设置字符输入缓存,定义BUFF指令如下:
buff1 db 5;输入数据字符缓存
db ?
db 10 dup(0)
设置字符缓存的用循环模式进行判断,储存。

0AH功能输入判断,设计了下面的程序:
process_indata proc
lea dx,buff1
lea si,buff1
mov ah,0ah
int21h
mov bx,dx;将0aH功能所得数据首地址备份
mov cl,[bx+1] ;取输入数据串中字符个数
add si,2
mov al,[si]
cmp al,'-'
jz first_ok
mylab0:
cmp al,'0'
jl char_not_ok
cmp al,'9'
ja char_not_ok
first_ok:
inc si
mov al,[si]
loop mylab0
jmp data_good
char_not_ok:
mov char_flag,1
jmp exit
2.3.2处理a、b、c的键盘输入
在键盘输入a、b、c时,会有不同的结果,首先,要输入a的值,有三种情况:(1)a=0时,因为本题只是考虑二次方程,则a=0时不做定义,也就是在a=0时要重新输入a的值,输出定义为:the equation is not illegal !
(2)-128<=a<=127时,则为正确的a值输入,正常操作下面的程序。

(3)当a不是以上两种情况是,也就是a的输入不符合数据段定义的要求,比如带字母,特护符号等,则要重新输入a的值,并显示:input digital!
下面讨论b、c的输入,b、c的输入是规则是相同的,也相同于a的输入,只是在0值时不做特殊讨论。

a、b、c的键盘输入定义在数据段已经定义,下面要做的就是判断a、b、c输入值的范围,判断范围的程序如下:
cmp ax,-128
jl data_over
cmp ax,127
jg data_over
mov over_flag, 0
jmp finish
data_over:
mov over_flag, 1
finish: ret
2.3.3对a、b、c输入的数进行处理
对a、b、c输入的数进行处理,因为a、b、c的字符输入在缓存中,要一个一个的判断,输入的字符的ASCII码是不是在“1”与.“9”之间,如果在,则继续循环判断,如果不是,则重新输入,判断结果是在一个整的字符全部输入完成后来判断的,比如a的字符全部输入完全,如果输入的字符符合条件,但是为负数,在汇编语言中,负数要用它的补码来进行计算,如果为整数则直接储存,指令如下:
data_good:
lea dx,buff1
lea si,buff1
mov cl,[bx+1] ;取输入数据串中字符个数
add si,2
mov al,[si]
xor ax,ax
xor bx,bx
xor dx,dx
mov al, [si] ;取键盘输入的第一个字符
dec cl
cmp al,'-'
jz mylab2 ; 输入为负数调入mylab2
sub al,'0'
mylab1: ;正数转换
cmp cl,0
jz exit
mov bl,10
mul bl
xor bx,bx
mov bl,[si+1]
sub bx,'0' ;将输入的字符转换为数值
add ax,bx
inc si
dec cl
jmp mylab1
mylab2: ;负数转换先处理符号位以后的数据,再用NEG指令变换mov al,[si+1]
sub al,'0'
dec cl
mylab4:
cmp cl,0
jz mylab3
mov bl,10
mul bl
xor bx,bx
mov bl,[si+2]
sub bx,'0'
add ax,bx
inc si
dec cl
jmp mylab4
mylab3: neg ax;将负数变为补码存储
exit:
ret,
下面进行对a 、b 、c 输入符合上面条件的值进行判断是不是如何范围,a 的处理比较复杂,因为a 的考虑要多一些,所以,这里只对a 进行讨论,其他同理可以得到,对a 的处理程序如下:
show mes1
call process_indata ;//处理输入的a 值
cmp char_flag,1
jnz not_char_a
show mes8
mov char_flag,0
jmp again_a
not_char_a:
cmp al ,0
jnz data_ok
show mes6
jmp again_a
data_ok:
call process_check ;
mov bl ,over_flag
cmp bl ,1
jnz data_ok_a
show mes4
jmp again_a
data_ok_a:
mov a,al
2.3.4对24b ac -进行的计算处理
对24b ac -的计算,要考虑很多。

首先处理2b ,首先计算时要将其扩展为32位来储存,为了防止数据的溢出,并在扩展后将其高16位清零,指令如下:
mov al,b
imul al ;求b 的平方 ,用带符号的乘法
mov b2_L ,ax ;b的平方要用32位存储,防止数据溢出
mov ax, b2_H
xor b2_H,ax ;b的平方高16位清零
下面对4ac计算处理,因为全为带符号数,那么要判断4ac的正负,判断的方式是使用指令test dx,8000h,判断正负之后,如果为负数,则取反加1,即利用补码来进行计算,正数直接参与下面的计算,并将结果存在DAT中。

计算指令如下:
mov al, a
imul c ;求a*c
mov bx,4;4*a*c
imul bx ;a,b,c为带符号的数,故所有乘法指令应该用带符号乘法
test dx,8000h;判断计算结果的正负;为保证b2-4*a*c运算
jz step1
not ax ;如果为负数,则转换为正数,取反+1,因为为32位所以不好用NEG指令
not dx
add ax,1
adc dx,0
mov dat_H,dx ;dat_H dat_L 存储4*a*c
mov dat_L,ax
下面对24
-的正负,如果为负数,取补吗,转换为
b ac
b ac
-进行计算,要判断24
正数计算,并且以sqrt_flag为标志位,负数为1,非负数为.0.。

并且减法运算为32为带符号减法,流程图如图2-1:
图2-1 判断结果为正负流程图
根据流程图设计程序如下:
mov dat_H,dx ;dat_H dat_L 存储4*a*c
mov dat_L,ax
mov ax ,b2_L ;32位减法 b2-4ac
sub ax ,dat_L
mov dx ,b2_H
sbb dx , dat_H
mov sqrt_flag ,1 ;b2-4ac 正负标志:1 为正数,0为负数
jnc next ;判断正负数
mov sqrt_flag,0
sub ax ,1 ;如果为负数,就转换为正数
sbb dx ,0
not ax not dx
2.3.5对24b ac -的开方计算
对24b ac -的开方计算,因为汇编语言中没有关于开方计算的代码,所以用迭代法进行计算,迭代为从1开始,依次平方,知道大于24b ac -为止,再进行一下的循环判
断,因为课设要求小数点后保留一位有效数字,那么计算之前将所以的数全部乘以10,那么24
就是乘以100,32位数不能直接乘以100,采用的方法是循环叠加100次,
b ac
因为要在正数部分循环迭代判断,得到的结果是原来计算结果的10倍。

指令如下:next: ;由于32位乘法系统不支持故转换为100次循环加法
mov solve_H,dx;将结果保存
mov solve_L,ax
mov cx,99;计算(b2-4ac)*100,将(b2-4ac)连续加100次
loop1:
add ax,solve_L
adc dx,solve_H
loop loop1
mov temp_H,dx
mov temp_L,ax
mov solve_H,dx;保存计算结果
mov solve_L,ax
xor cx,cx
step2: ;////////迭代运算从此开始
inc cx;从1开始迭代,求开方
mov ax,cx
mul ax
sub ax, solve_L ;求x*x并和b2-4ac作差,并转换为正数
sbb dx ,solve_H
jnc step3
sub ax,1
sbb dx,0
not ax
not dx;将此次作差结果和上次比较,如果大于上次结果,则
step3:
cmp dx,temp_H ;上次结果为开方的值,否则,继续迭代
ja last_step ;dx>temp_H
jb step4 ;dx<temp_H
cmp ax,temp_L ;dx=temp_H, ax>=temp_L
jae last_step
step4:
mov temp_H,dx;还没有找到开方的值,将此次结果保存,然后cx+1,继续迭代
mov temp_L,ax
jmp step2
last_step :
dec cx
ret
process_sqrt endp
2.3.6计算处理及输出
因为上面保存的结果为计算的10倍,在计算机显示的时候,字符是一位一位显示的,那么就要对得到的字符串进行处理,拆分,将各个字符拆分为单个的字符。

指令如下:
get_num :
cwd ;除10取余,将各个数据拆分
div divid
add dx,'0'
push dx
inc cx
cmp ax,0
jnz get_num
mov ax,cx
to_buff:
pop bx;存储拆分结果
inc si
add num_1,1
mov byte ptr [si],bl
为结果要求存储保留一位有效数字,分两种情况,一种是有小数部分,并且大于一位有效数字,那么结果取约分,如果结果为整数或者恰好为一位有效数字,那么直接参与下面的计算,指令如下:
loop2:
loop to_buff
cmp ax,1;小数点处理部分
jz one_bit
mov bl,byte ptr [si] ;计算结果大于1位,处理小数点
inc si
add num_1,1
mov byte ptr [si],bl
mov byte ptr [si-1],'.'
jmp solve_dis
one_bit: ;计算结果为1位,处理小数点
mov bl,[si]
inc si
inc si
mov byte ptr [si],bl
mov byte ptr [si-2],'0'
mov byte ptr [si-1],'.'
add num_1,2
solve_dis:
ret
计算-b/2a的数值,依然要考虑保留小数点后一位有效数字,计算时计算的数为-10b/a,计算出结果要拆分,还原为原来的正确结果,并保存,计算时要却a的绝对值
2a与上面相同。

计算(b-/2a的是两个值,首先判断的是开放结果的正负,开方结果
为正数则为输出第一个解;为负数,则为第二个解,最后结果进行储存,结果中实数和虚数的输出,先计算输出实数部分,后计算输出虚数部分,指令如下:
lea si,result_dis1
add si,2
mov num_1,3
lea di,result_dis2
add di,2
mov num_2,3
cmp sqrt_flag,1
jz pos_number ;开方为正数,则跳转
;方程的第一个解
show mes7
mov bx,s1 ;-b/2a
test bx,8000h;判断-b/2a的正负
jz disp1
neg bx
inc si
mov [si],'-'
add num_1,1
disp1:
mov ax,bx
call process_result1 ; -b/2a的值
inc si
add num_1,1
mov [si],'+'
mov ax,s2
disp2: call process_result1 ; sqrt(b*b-4*a*c)/2a 的值inc si
add num_1,1
mov [si],'i'
;方程的第二个解
mov bx,s1
test bx,8000h;判断-b/2a的正负
jz disp3
neg bx
inc di
add num_2,1
mov [di],'-'
disp3: mov ax,bx
call process_result2
inc di
add num_2,1
mov [di],'-'
mov ax,s2
disp4: call process_result2 ;存储显示计算结果的虚数部分inc di
add num_2,1
mov [di],'i'
jmp exit_p
pos_number: ;计算结果为实数,
;方程的第一个实数解
show mes7
mov ax,s1_real
push ax
.
mov al,a
xor ah,ah
cbw
mov bx,ax
pop ax
cwd
idiv bx
xor dx,dx
cwd
idiv two
mov bx,ax
test bx,8000h;判断方程解的正负
jz disp5
neg bx
inc si
add num_1,1
mov [si],'-'
disp5: mov ax,bx
call process_result1 ;计算方程的第二个解mov ax,s2_real
push ax
mov al,a
xor ah,ah
cbw
mov bx,ax
pop ax
cwd
idiv bx
xor dx,dx
cwd
idiv two
mov bx,ax
test bx,8000h;判断方程解的正负
jz disp6
neg bx
inc di
add num_2,1
mov [di],'-'
disp6:mov ax,bx
call process_result2 ;方程的第二个实数解
exit_p:
ret
2.3.7结果显示操作
运算完成之后,显示计算结果,用红字进行显示,并且两个解的显示分行,指令如下:
process_roots_dis proc;用红色字体显示方程的解
show crlf ;显示换行
mov es,ess
mov ah,03h
int10h
mov ah,02h
mov bh,1
int10h;取光标地址
lea bx,result_dis1 ;显示解1
mov bp,bx
xor bx,bx
inc dl;显示向前推一列
mov cx,num_1
mov al,01h
mov bl,24h
mov ah,13h
int10h
show crlf ;显示换行
mov es,ess
mov ah,03h
int10h
mov ah,02h
mov bh,1
int10h;取光标地址
lea bx,result_dis2 ;显示解1
inc dl;显示向前推一列
mov bp,bx
xor bx,bx
mov cx,num_2
mov al,01h
mov bl,24h
mov ah,13h
int10h
ret
3结果显示分析
根据要求所编程思路如上,根据所讨论的几种情况,不同的输出显示如下:
(1)所示的是a的输入不在范围的数,a为0或者不是数字,继续输入显示如图3-1所示。

图3-1 不符合条件输入(2)正确的输入系数,但是显示为共轭负数如图3-2所示:
图3-2 共轭负数输出
(3)跟为实数的结果显示如图3-3所示:
图3-3实数输出
(4)跟为纯虚数的结果显示如图3-4所示:
图3-4 纯虚数结果显示
结果分析显示出,所得到的跟是正确的,并且保留了一位有效数字,同时显示出了其负数部分,程序正确。

总结与体会
通过这次课程设计,真的学到了很多,拿到课设题目的时候,一看题目,很简单,但是,到设计程序的时候,才发现,一点都不简单,从头到尾,一直在思考,到底如何把这个课设做的完美,同时觉得自己所认为的那点骄傲被完全的击破,通过多方查阅资料,总算将程序编出来了,学到了很多,也彻底的知道了汇编语言的博大精深。

这不是第一次用汇编语言来设计一个小程序,平时做了很多实验,写了很多小程序。

但这次是一个综合的程序,平时的很多程序都用到了。

很多子程序的设计是固定的,因此可以直接从指导资料中调用,大多只需要修改几个参数就可以,这大大方便了我们的设计,为我们节省了很多的时间。

真正体会到了合作的重要性,遇到很多问题时,看书查资料不能解决时,这是去找同学讨论一下,收获很大,可以使很多问题迎刃而解,直到问题最终解决。

不可否认,本程序存在不少缺点和不足,但通过这次课程设计的却找出了自己在学习上的不足,对以后的工作也有指导作用。

相信在以后的学习中会克服这些不足,达到熟练掌握汇编语言的目的!
这次课程设计终于顺利完成了,在设计中遇到了很多编程问题,最后通过查阅资料与请教同学、老师,把问题一一解决了,在此谢过给以帮助的老师与同学。

参考文献
[1]彭虎,周佩玲,傅忠谦.微机原理与接口技术.第二版.北京:电子工业出版社
[2] 刘乐善,欧阳星明.微型计算机接口技术及应用.武汉:华中理工大学出版社
[3] 沈美明,温冬婵. IBM-PC汇编语言程序设计.北京:清华大学出版社
[4] 姚燕南,薛钧义. 微型计算机原理。

西安:西安电子科技大学出版社
[5]金汉均,金洋编著.汇编语言程序设计.武汉:武汉大学出版社
[6]荆淑霞.微机原理与汇编语言程序设计.北京:清华大学出版社,北京交通大学出版社。

相关文档
最新文档