文档视界 最新最全的文档下载
当前位置:文档视界 > 简单计算机程序设计

简单计算机程序设计

专业综合课程设计任务书

学生姓名: aaaaaa 专业班级: 电信 1102班

指导教师: 李达工作单位: 信息工程学院

题目5:简单计算器程序设计

初始条件:

(1)提供实验室机房及PC机;

(2)微机原理与通信接口的基本理论学习。

要求完成的主要任务:(包括课程设计工作量及其技术要求,以及说明书撰写等具

体要求):

(1)编写一个程序实现十进制加减乘除运算;

(2)在命令提示后输入算式,运算符号不超过四个;

(3)回车后进行计算并以十进制显示结果;

(4)程序采用汇编语言在PC机上完成;

(5)写出系统需求分析、原理图和程序实现流程图;

(6)对结果进行分析;

(7)要求阅读相关参考文献不少于5篇;

(8)根据课程设计有关规范,按时、独立完成课程设计说明书。

时间安排:

(1) 布置课程设计任务,查阅资料,确定方案四天;

(2) 进行编程设计一周;

(3) 完成课程设计报告书三天;

指导教师签名: 年月日系主任(或责任教师)签名: 年月日

目录

1.引言 (1)

1.1设计目的 (1)

1.2 设计要求及需求分析 (1)

1.2.1设计要求 (1)

1.2.2需求分析 (1)

1.3 软件运行环境 (2)

2.总体设计分析 (2)

2.1题目分析 (2)

2.2 设计概述 (2)

3.设计步骤 (3)

3.1运算表达式输入 (3)

3.1.1 运算表达式合法性的检查方法 (3)

3.2 数值的补码转换方法 (4)

3.3 表达式计算 (5)

3.3.1 运算优先级别的静态确定法 (6)

3.3.2 正负数区分 (7)

3.3.3 补码到ASCII码转换 (7)

3.3.4除法运算 (9)

4.软件运行结果 (10)

5.软件改进计划 (12)

6.程序源代码 (13)

7.心得体会 (20)

参考文献 (21)

1.引言

1.1设计目的

本次课程设计的题目是用汇编语言实现一个简单的计算器,要求:编写一个程序,每运行一次可执行程序,可以实现加减乘除四则运算。计算器是最简单的计算工具,简单计算器具有加、减、乘、除四项运算功能。通过使用汇编语言设计实现简单计算器,以此进一步了解和掌握对数据存储,寄存器的使用,加减乘除相关指令以及模块的调用等汇编语言知识的有效运用。本次课程设计以实现一个基本功能完善,界面友好,操作简便易行的计算器为最终目的。通过对具有加减乘除基本功能的计算器的设计实现,学会使用汇编语言实现输入输出模块的设计,模块合理调用的设计,加减乘除运算的判断以及退出程序的判断的设计。通过对各种指令的合理使用,熟悉并加深对各种指令的用法。学会使用汇编语言设计各个功能模块。当实现各个程序模块后,学会通过程序的调用最终实现一个具有基本计算功能的简单计算器。

简单计算器项目设计,主要是对汇编语言运算的应用,要完成该项目必须对汇编的四则运算语法和逻辑有深入的了解。除此之外,还必须对汇编各种指令、伪指令集和计算机系统有很好的了解。

1.2 设计要求及需求分析

1.2.1设计要求

(1)编写一个程序实现十进制加减乘除运算;

(2)在命令提示后输入算式,运算符号不超过四个;

(3)回车后进行计算并以十进制显示结果

1.2.2需求分析

用8086汇编语言编写一个能实现四则混合运算计算器程序。程序能实现键盘十进制运算表达式的输入和显示(例如输入:“1+2*3-4”),按回车键后输出十进制表示的运算结果。

该计算器能够对输入的符号进行实时的读取和分析,它接收0-9,+、-,*,/,=符号,用来对操作数进行运算,如果输入的操作数大于9,还需要对数字进行数码转换;

如果识别用户输入ESC,那么计算器会提示退出消息,如果输入是L,它将会执行清屏操作。程序将获取的有效运算符保存在内存中,当获取到回车键后,即刻进行运算操作,最终将运算结果显示在计算机屏幕上。

1.3 软件运行环境

使用的设备及软件为8086兼容机及轻松汇编开发软件。

2.总体设计分析

2.1题目分析

根据题目要求,可以把程序的工作过程划分为运算表达式输入、计算式运算、结果输出三部分。因此在编写程序时可以按此把程序大致划分为三个模块。总体设计流程图如下图2.1所示

简单计算机程序设计

图2.1 软件总体设计流程图

2.2 设计概述

输入模块分为包含运算表达式合法性检查,只有输入+,-,*,/,=,0-9,ESC,L,才算合法,其中ESC是退出程序功能,L是清屏功能

表达式运算模块包含,数值正负性判断,ASCII码转换,数值计算模块。

输出模块分为两个部分,第一个部分是程序启动时的提示语句输出,第二部分是运算结果进行转换输出。详细的流程和设计方案将在设计步骤中说明。

3.设计步骤

3.1运算表达式输入

用户通过键盘输入的运算表达式为一个ASCII码字符串,字符串的最后一个字符是“=”号。对于这个运算表达式,“+、-、*、/、0~9、=,ESC,L”是合法的表达式内容,其他的字符则是无法进行运算的非法内容,因此需要首先进行表达式合法性检查。另外,由于计算机能进行计算的是2进制的补码,因此还需要把以ASCII码表示的数值转换为补码的形式并加以保存。当然,控制运算方式的符号也要进行保存。因此,“运算表达式输入”这个模块可以细化为:表达式合法性检查、数值的ASCII码到补码转换及保存、符号的保存三个小部分,如图3-1所示。

简单计算机程序设计

退出

清屏

图3-1 “运算表达式输入”的流程图

3.1.1 运算表达式合法性的检查方法

观察“ASCII字符编码表”,可以发现“+、-、*、/”的ASCII码由2AH到2FH,而“0~9”的ASCII码则由30H到39H,因此只需对输入的字符一个一个地进行数值范围比较,看看是否处于28H~39H这个范围里面,即可区分输入的表达式是否合法,流程图如图5-2所示。此流程图是采用循环输入字符的方法,每输入一个字符即进行判断。

简单计算机程序设计

退出

清屏

图3-2 运算表达式合法性检查

3.2 数值的补码转换方法

要进行数值的ASCII码到补码的转换,首先就得判断输入的字符是数值还是符号。根据上文所提,“+、-、*、/”的ASCII码由2AH到2FH,而“0~9”的ASCII 码则由30H到39H,只需比较字符是否小于等于2FH(或小于30H)即可判断是否为符号,否则则是数值,如图3-2所示。

众所周知,要把一个ASCII码数值转换为二进制补码的形式,只需要对其减30H即可实现。但如果输入的是多位数,例如123,那么计算机获得的是31H、32H、33H三个字节,即使分别对这三个字节进行减30H操作,也只是获得1、2、3三个数而已。实际上可以利用加权的方法合并这几个数:

123=1×100+2×10+3×1

但另一个问题是,由于输入是随机的,即输入的运算数有多少位是未知的,因此无法使用上面的方面静态确定每一位的权重。这里介绍的方法是,每输入运算数的一位,则把前面的合并结果(称为原值)乘以10再与这一位相加,实现动态的加权合并。例如:

令原值为0,输入1,结果为:0×10+1=1

输入2,结果为:1×10+2=12

输入3,结果为:12×10+3=123

即:123=(((0×10+1)×10+2)×10)+3。数值的补码转换流程如图3-3所示,当然,在获得第一个数值输入前要先把原值设置为0。

简单计算机程序设计

图3-3 数值的补码转换流程图

3.3 表达式计算

由于运算表达式有多个数值和符号,而符号有不同的优先级别,因此上文提到的数值保存和符号保存应该分开两个地方进行保存,这样有利于表达式的计算算法设计。下面把“+、-、*

、/”称为运算符,+、-

的运算优先级要低于*、/,在

运算时要先处理优先级高的运算。

简单计算机程序设计

简单计算机程序设计

简单计算机程序设计

简单计算机程序设计

(a)

(b)

简单计算机程序设计

简单计算机程序设计

图3.4 运算表达式的存储举例

观察图3.4的三条运算表达式,再联系四则混合运算的优先原则,可以归纳出几点:

数值的数量是运算符的数量加1(优先符不算),第1个运算符代表第1、2个数值的运算操作,第N 个运算符代表第N 、N+1个数值的运算操作……

每进行一次运算,相应的运算符即被消除,而参与运算的两个数值合并为一个数值,仍然满足(a )。例如图3.4(a ),当完成乘法运算后,数值存储区有408、56两个数,符号存储区有“+”一个运算符。

括号(优先符)的作用是把括号内的运算符的优先级别提高到比外部高。因此,要实现运算表达式的运算,最重要的就是确定所有运算符的优先级别。下面讨论运算符优先级别的编程设计方法。

3.3.1 运算优先级别的静态确定法

此方法是完成了把整条运算表达式全部存入数值存储区和符号存储区后才开始对运算符优先级进行判断的方法:

设置“*、/”的优先级为2、“+、-”的优先级为1;

运用优先级别静态确定法处理图3.4的三条表达式的运算符,结果如图3.5所示。其中图3.5的“12*34+56”,其数据与优先级如图3.5所示。由于*的优先级高于+,那么计算时先计算12*34

简单计算机程序设计

简单计算机程序设计

简单计算机程序设计

简单计算机程序设计

简单计算机程序设计

简单计算机程序设计

(a)(b)

图3.5 运算符的静态优先级别

最后,由于四则混合运算遵循从左往右计算的原则,即相同优先级别的运算符靠左的优先。因此,只需计算出符号存储区里面的所有运算符的优先级别,然后根据优先级的大小先后执行运算符对应的运算即可实现计算(当然每进行一次运算,相应的运算符即被消除,而参与运算的两个数值合并为一个数值)。当数值存储区里面剩下一个数值时,运算结束,这个最后的数值就是运算的最终结果。

分析运算结果的特点:运算结果为一个2进制补码,整数,如果数据长度为16位,则运算结果范围是:-32768~32767。运算结果的输出要解决的主要问题是:正负数区分、补码到ASCII 码转换并输出显示。运算结果的输出流程如图3.6所示。

整数

简单计算机程序设计

小数

4/3=1余1,将1放入整数内存中;将余数乘以10再除以3,10/3=3余1,将3放在小数第一位,再将余数乘

10除以3……

简单计算机程序设计

图3.6 结果输出流程图

3.3.2 正负数区分

运算结果有三种情况:正整数、负整数、零。运算结果以补码形式对这三种情况进行统一的存储,但显示输出时则有所不同。负整数前面需要显示“-”号,因此需要对运算结果的符号进行判断。另一方面,正整数和零的补码与原码相同,而负整数的补码则不一样。把负整数进行取补码运算,把它转换为原码,可以实现运算结果统一的ASCII 码转换输出方法,而不需要分别为正整数和零、负整数分别设计两个不同的ASCII 码转换程序,如图3.7所示。

简单计算机程序设计

整数小数4/3=1余1,将1放入整数内存中;将余数乘以10再除以3,10/3=3余1,将3放在小数第一位,再将余数乘10除以3……

简单计算机程序设计

图3.7 正负数区分流程图

3.3.3 补码到ASCII 码转换

计算结果在屏幕上的输出显示实际上是ASCII 码的输出显示。假设程序采用的数据长度为16位,则运算结果范围是:-32768~32767,即屏幕最多得显示5位ASCII 码。由于上文已经把结果统一为原码,下面介绍如何把原码转换为ASCII 码。

这个转换过程实际上跟上文的“数值的补码转换方法”是相反操作。例如要把123在屏幕上输出显示,即要把123的百位、十位、个位分离,得到1、2、3,然后转换为31H 、32H 、33H 三个ASCII 码。众所周知,把一位数转换为ASCII 码只需加30H 即可,下面介绍把一个多位数的各位分离的方法。 (a)除十法

分离方法是:对一个多位数进行除10处理,得到的余数即为个位数,而商则是删除个位后的多位数。对商反复进行除10处理,直到商为0为止,即可把各位数分离。例如对123进行除十法处理:

123/10,商是12,余数是3 12/10,商是1,余数是2 1/10,商是0,余数是1

可见经过三次除十计算,得到的三个余数刚好就是对123的各位的分离结果。接着只需分别对这些余数加30H 即可转换为ASCII 码,实现输出转换。

除十法的优点是不需要理会要输出的数值有多少位,不断除以10直到商为0即可;缺点是得到的余数的顺序跟输出的方向相反,不方便输出。例如上例得到的三个余数的顺序是3、2、1,加30H 转换输出后屏幕显示为“321”,跟期望显示的顺序相反,要作进一步处理。处理方法是把余数放进堆栈里面,然后再出栈显示。由于堆栈是先进后出的,即可解决该输出的顺序问题。

简单计算机程序设计

整数小数4/3=1余1,将1放入整数内存中;将余数乘以10再除以3,10/3=3余1,将3放在小数第一位,再将余数乘10除以3……

简单计算机程序设计

图3.8 除十法流程图

(b)除最高位法

分离方法是先除以10位数-1,得到的商即为最高位,余数为删除最高位后的多位数。接着令余数除以10位数-2,得到的商为次高位,……。例如123,其位数是3(个位、十位、百位),则计算过程为: 123/103-1,商是1,余数是23 23/103-2,商是2,余数是3 3/103-3,商是3,余数是0

可见经过三次计算,得到的三个商刚好是对123的各位的分离结果,而且顺序跟输出方向相同。可以直接加30H 转换输出,屏幕显示为“123”。

该方法的缺点是:必须首先确定要输出的数值有多少位,编程者必须十分清楚需要输出的数值的数值范围。

本次软件设计过程中用的是(a)除十法

简单计算机程序设计

整数小数4/3=1余1,将1放入整数内存中;将余数乘以10再除以3,10/3=3余1,将3放在小数第一位,再将余数乘10除以3……

简单计算机程序设计

图3.9 除最高位法流程图

3.3.4除法运算

除法运算不同于其他的几种运算,因为除法运算中可能会产生小数,在汇编中没有直接获取小数的除法运算指令,一般除法我们用DIV 指令,用DIV 做除法运算,根据除数占字节数不同,结果保存的方法也不一样。

被除数默认放在AX 或(DX 和AX )中,如果除数为8位,被除数为16位,被除数默认在AX 中存放,如果除数为16位,被除数为32位,被 除数则在(DX 和AX )中存放,DX 存放高16位,AX 存放低16位。

如果除数是8位,则AL 存储除法操作的商,AH 存储除法操作的余数;如果除数是16位,则AX 存储除法操作的商,DX 存储除法操作的余 两个整数相除得到小数时,虽然我们不能直接得到小数部分,但是我们可以通过不断的将余数除以除数的方法得到小数部分,而将小数部分整数部分分开存放,分开显示,是一种可取的方法。如图3.10所示,是具体操作过程

例求4/3的结果

简单计算机程序设计

整数小数

4/3=1余1,将1放入整数内存中;将余数乘以10再除以3,10/3=3余1,将3放在小数第一位,再将余数乘

10除以3……

简单计算机程序设计

图3.10除法取小数操作

4.软件运行结果

简单计算机程序设计

图4.1 个位数加减法运算

简单计算机程序设计

图4.2 多位数加减法运算

简单计算机程序设计

图4.3 乘除法运算

简单计算机程序设计

图4.4 混合运算

简单计算机程序设计

图4.5 ESC退出操作

5.软件改进计划

由上述设计步骤和结果展示可知,软件能实现常规的四则运算,并且经测试软件稳定性和健壮性能够达到设计要求,完成了软件设计的要求。

在后期,将对软件功能进行改进或者扩展,主要有以下两个方面:

(1)软件现在不支持()参与的运算;

(2)软件只支持2个字节数据运算。

对于括号运算功能的添加,我们将括号也当成一种运算符,也有优先级,只是它不参与运算而已。而现在软件不能进行更高字节的数据运算,主要是因为设定时,默认将存放数据的寄存器、堆栈等空间设置为DW,如果将它们设置为更高字节,它们可以满足范围更广的运算

6.程序源代码

STACKS SEGMENT STACK

DW 20 DUP(?)

STACKS ENDS

DATA SEGMENT

_NUM DW 0

TAB1 DB " PLEASE INPUT A FORMULA:(ENTER ESC TO EXIT)",13,10,"$"

NUM1 DW 100 DUP(?)

NUM2 DW 10 DUP(?) ;存放除法产生的小数位

NUM4 DW 100 DUP(?)

C0 DW 0

C1 DW 0

C2 DW 0

RESULT DW 0

WRONG DB 13,10,"WRONG INPUT!$"

;OVER DB 13,10,"NOT OPERATIONAL CHARACTER!$"

DATA ENDS

;----------------------------

;------代码段----------------

CODE SEGMENT

ASSUME CS:CODE,DS:DA TA

;------主程序---------------

START: MOV AX,STACKS

MOV SS,AX

MOV AX,DATA

MOV DS,AX

CALL DISPMENU ; 显示汇编计算器菜单

STARTA:

MOV BX,-1

MOV SI,0

MOV DI,30

MOV CX,0

MOV NUM2,0

; 初始化各个变量

CALL INPUT

CALL CALC

CALL OUTPUT

EXIT:

MOV AH,4CH

INT 21H

;------计算器显示菜单子程序--------

DISPMENU PROC NEAR

MOV DX,OFFSET TAB1

MOV AH,09H

INT 21H

RET

DISPMENU ENDP

;---------------------------

;输入字符及转换程序模块

;----输入并转换子程序,结果式存入NUM1-------

INPUT PROC NEAR

STARTW:

MOV AH,1

INT 21H

MOV AH,0

CMP AL,1BH ; 'ESC' 退出

JZ EXIT

CMP AL,2AH ; '*'

JZ MARK

CMP AL,2FH ; '/'

JZ MARK

CMP AL,2BH ; '+'

JZ MARK

CMP AL,2DH ; '-'

JZ MARK

CMP AL,3DH ; '='

JE EQUAL

CMP AL,'L' ;'L' 清屏

JE CLS

SUB AL,30H

CMP AL,0 ;非数字和运算符则报错

JL ERROR

CMP AL,9

JG ERROR

JMP ARITH

ERROR: ;显示输入错误

LEA DX,WRONG

MOV AH,9

INT 21H

JMP STARTA

CLS: MOV AX,03H

INT 10H

ARITH:

CMP C1,0

JE TTOM

MANA: ;数值的补码转换

MOV C0,AX

ADD C1,1

MOV AX,BX ;AX->BX

MOV CX,10

MUL CX

ADD AX,C0 ;AX=BX*10+AX

MOV BX,AX ;AX->BX,下次转换使用

JMP STARTW

TTOM:

MOV BX,0

JMP MANA

MARK:

CMP BX,-1 ;BX=-1表示上一次输入的是数字

JE GGON

MOV NUM1[SI],BX ;将操作符和运算符都放入NUM1

ADD SI,2

MOV NUM1[SI],AX

MOV BX,-1

MOV C1,0

ADD SI,2

JMP STARTW

GGON:

MOV NUM1[SI],AX

ADD SI,2

JMP STARTW

EQUAL: ;输入是等号时,调到主程序执行运算CMP BX,-1

JE LLOP

MOV NUM1[SI],BX

ADD SI,2

MOV NUM1[SI],AX

JMP ENDW

LLOP:

MOV NUM1[SI],AX

JMP ENDW

ENDW:

RET

INPUT ENDP

;---------------------------------

;------ 计算混合运算的子程序(不含括号的)------------------

CALC PROC NEAR

MOV AX,NUM1

MOV NUM4,AX

MOV NUM2,0

MOV DI,2

MOV CX,0

MOV SI,2

INT1: ;检测算式的运算符,并根据运算符进行MOV BX,NUM1[SI] ;相关的操作

CMP BL,2AH ;'*'

JE MULL

CMP BL,2FH ;'/'

JE DIVV

CMP BL,3DH ;'='

JE JMP_CB

CMP BL,29H ;')'

JE JMP_CB

CMP BL,2BH ;'+'

JE POTT

CMP BL,2DH ;'-'

JE POTT

INT2:

MOV NUM4[DI],BX

ADD DI,2

ADD SI,2

MOV AX,NUM1[SI]

MOV NUM4[DI],AX

ADD DI,2

ADD SI,2

JMP INT1

POTT:

SUB DI,2

MOV NUM4[DI],AX ;运算结果存放在NUM4

ADD DI,2

JMP INT2

MULL:

ADD SI,2

MOV BX,NUM1[SI]

MUL BX ;AX存放计算结果

ADD SI,2

JMP INT1

JMP_CB: JMP CHUBU

DIVV:

ADD SI,2 ;是除法则直接运算

MOV BX,NUM1[SI]

XOR DX,DX

DIV BX

PUSH AX ;将AX值保存起来,防止取小数操作改变

MOV CX,DI

MOV DI,0

XS: MOV AX,DX ;得到小数部分

MOV _NUM,10

MUL _NUM ;余数乘以10,继续除

DIV BX ;AX/BX 商保存在AX,余数保存在DX

MOV NUM2[DI],AX ;将得到的商存入NUM2中,成为小数部分

ADD DI,2

CMP DI,4

JL XS

POP AX

MOV DI,CX

ADD SI,2

JMP INT1

ADDD: ;最终的加法运算

ADD DI,2

MOV BX,NUM4[DI]

ADD AX,BX

ADD DI,2

JMP INT3

SUBB: ;最终加法运算

ADD DI,2

MOV BX,NUM4[DI]

SUB AX,BX

ADD DI,2

JMP INT3

CHUBU: MOV NUM4[DI],BX ;对结果进行初步处理

SUB DI,2

MOV NUM4[DI],AX

MOV AX,NUM4

MOV DI,2

INT3:

MOV BX,NUM4[DI]

CMP BX,2BH ;'+'

JE ADDD

CMP BX,2DH ;'-'

JE SUBB