基于nasm的计算器代码实现

第一章 项目介绍

        1.1 功能介绍

        1.2 设计思路

第二章 项目代码分析

        2.1 程序流程分析:

        2.2 程序代码分析

第三章 项目运行方式

        3.1 汇编,链接,运行,调试说明

        3.2 运行过程:

源代码链接: https://github.com/chenaaa1/nasm-calculator

第一章 项目介绍

1.1 功能介绍

利用汇编语言实现从键盘中输入两个10进制数之间的加、减、乘、除计算表达式,然后输出计算结果,再让用户选择根据计算结果再次计算或者结束程序。

1.2 设计思路

通过从键盘中循环读取字符,存入既定的内存空间中,以最后一位输入的非十进制数字符作为输入结束标志。两个10进制数字符串通过加、减、乘、除运算符作为分割。两个10进制数字符串边输入边转化为10进制数并通过判断运算符进行加、减、乘、除计算,然后输出结果。

第二章 项目代码分析

2.1 程序流程分析:

简易计算器程序的任务主要有处理输入数据,计算,显示算式结果。需要计算机先对输入数据进行转化分割然后进行计算,最后输出输入的算式及计算结果。

2.1.1 程序流程图解:

系统输出:Please input x [op] y:

用户输入四则运算式

系统输出:x/y=z (进行除法运算)

remainder=余数(其他运算没有这部分)

系统输出:Continue typing or no(y/n)

程序流程图如下:

2.1.2 主程序流程图解:

IMG_256

2.2 程序代码分析

2.2.1 初始变量设置子程序

声明段名,利用伪指令创建需要使用的变量及创建字符串提示信息

2.2.2 初始界面子程序(begin):

1. 依次调用对应的字符串提示信息来在控制台显示初始界面

2. 调用do_before子程序来读入用户输入的x值和y值和运算符

call do_before ; 调用do_before函数来读入第一位数字x
mov [op],al    ; 把运算符存入[op]中,al中存的为运算符
mov ax,[strtemp]         ; 把读到的x值移入[x]中,strtemp存的为数字的值
mov [x],ax
mov dword [strtemp],0         ; 恢复strtemp
call do_before         ; 读入第二位数字y
mov ax,[strtemp]
mov [y],ax

2.2.3 运算并输出结果子程序(whiledo):

1. 首先进入运算函数do_op

2. 以字符串拼接的方式将x,运算符,y,“=”这四个值或符号拼接在一起输出到界面上

3. 判断输出结果是否带负号,如果是的话就把符号标志变量symbol改为负号

mov dl,[symbol]    ; symbol初值为'+',如果减法出现负数那么改为'-'
cmp dl,'-'
jne lan     ; 不为'-'的话进入lan函数
mov ah,02h  ; 是'-'号的话就输出,注意这个是负号不是减号
int 21H

4. 把运算结果输出到“=”号的后面

5. 判断运算符是否为除法,如果是除法的话在运算结果后面加上余数的输出,不是除法的话则跳入二次运算do_move函数

mov bl,[op]
cmp bl,'/'
jne do_move
call crlf     ; 换行
mov dx,message5      ; 输出'remainder='
mov ah,09h;显示字符串
int 21h
mov bx,[remainder]
mov [strshow],bx
call show

2.2.4 让用户继续选择输入或结束子程序(do_move)

1. 输出字符串: Continue typing or no(y/n)

2. 对用户输入的y或n进行判断,然后转入不同的函数

2.2.5 二次运算子程序(lan2)和(done6)

1. 把上一次的运算的结果输出到界面上

2. 读入下一次运算的运算符

3. 判断运算符是什么符号,如果是非运算符则转入报错函数do_error

4. 如果是正确的运算符,则记录运算符,把上次运算结果z记为x,然后再次读入y值,最后转入运算总函数whiledo

mov [op],al; 读入运算符
mov  ax,[z]
mov [x],ax       ; 把上次运算结果z记为x
mov dword [strtemp],0       ; 准备再次读入新的y值
call do_before
mov ax,[strtemp]
mov [y],ax
jmp wihledo       ; 跳到运算总函数whiledo

2.2.6终止主程序函数(over)

1. 结束程序,返回操作系统

MOV    AH, 4CH
INT    21H

2.2.7 判断读入字符类型子程序(do_before):

1. 子程序设计思路:

在计算器中,输入的是10进制数字,而在汇编语言中读入字符只能一位一位的读取,故需要设置一个循环算法,将输入的数字以16进制形式放入寄存器中,而输出则再设置一个循环算法,将16进制转化为10进制后处理为ASCII码进行输出。

其次还有判断输入分割和结束的标志,我们这个程序的分割两个10进制数的标志为加减乘除运算符,结束标志为非10进制数字符(加减乘除运算符也是),对输入还未结束的非10进制数字符和非加减乘除运算符会视为错误输入,结束程序。

2. 实现方式:

先判断输入的字符是否为加减乘除符号或回车键,是的话返回主程序

不是运算符或回车键的话再判断是否为数字,对寄存器al的值减去符号“0”的值,这样即可将数字转为ASCII码所代表的数字,是数字的话保存到[temp]中,不是的话转入报错函数

mov dword [temp],0
sub al,'0'       ;将数字转化为ASCII码代表的数字
cmp al,0       ;判断输入的是否是数字(小于0)
jl do_error       ;不是数字的话结束输入
cmp al,9      ;判断输入的是否是数字(大于9)
jg do_error      ;不是数字的话结束输入

将[temp]内保存的单个数字存入保存整个数字的字符串[strtemp]中,然后给bx赋值10,再让ax乘bx以实现十进制进位。

重复上面的步骤,直到所有数字都存入[strtemp]中

xor ah,ah     ;高位清零
mov [temp],ax     ; 保留ax原来的值,temp存储一个数字,比如9
mov ax,[strtemp]  ; strtemp相当于整个数字,比如999
mov bx,10  ; 给bx赋10相当于十进制进位
; mul bx相当于ax * bx,然后就让ax中的值完成了进位
mul  bx    ; ten 中存储的是10
add ax,[temp]     ; 进位后在加上原来的数
mov [strtemp],ax  ; 把得到的多个数字存到strtemp中
; 数字没存完的话就再循环来存,直到遇到运算符或结尾符(回车符)
jmp do_before  ; 输入未结束,循环调用

3. 输入子程序流程图如下:

2.2.8 报错函数(do_error)

1. 调用报错信息字符串,在界面上输出input error

2. 清零al内的值,返回begin2函数重新读取数字

2.2.9 运算起始函数,也可以充当加法函数(do_op)

1. 对存储运算符的变量(op)进行判断,选择正确的四则运算方式对输入的两个运算数据变量(x和y)进行运算并存储在运算结果结果变量(z)中。

运算子程序流程图如下:

IMG_256

2.2.10 减法函数(done1)

1. 先判断运算符是否为减号,是的话继续程序,不是的话再转入乘法函数done2

2. 判断减法后的结果是否会产生负数,不产生负数的话转入无符号减法函数do_sub,产生负数的话就进行负号减法运算

cmp ax,[y] ;[x]和[y]进行比较
jge do_sub  ; 有符号大于等于则跳转到"无负号减法do_sub函数"
mov byte [symbol],'-'  ; x小于y的话就进行有负号减法运算
mov bx,[y]
sub bx,ax
mov ax,bx
jmp done4     ; 输出结果
do_sub:       ; 无负号减法函数
sub ax,[y]
JMP done4

2.2.11乘法函数(done2)

1. 先判断运算符是否为乘号,是的话继续程序,不是的话再转入除法函数done3

2. 进行乘法运算并输出结果

mul dword [y]

JMP done4     ; 输出结果

2.2.12 除法函数(done3)

1. 先判断运算符是否为除号,是的话继续程序,不是的话即用户输入了非法运算符,转入报错函数终止程序

2. 进行除法运算

mov bx,[y]
mov bh,0
div  bl

3. 把余数存入[remainder],然后输出结果

mov [remainder],ah
mov ah,0
jmp done4     ; 输出结果

2.2.13 保存结果函数(done4)

将结果存入[z]中,返回主程序

mov [z],ax
ret

2.2.14 非法运算符报错函数(done5)

1. 当存入用户输入的运算符时,先进行判断是否为加减乘除符号,如果都不是的话调用报错信息“input error”

2. 恢复断点,返回主程序

2.2.15 显示结果并结束子程序(show)

1. 给bx赋值10,为下一步的div指令做铺垫

2. 用div指令将结果每次除以10,然后把余数压入栈

3. 判断商是否小于0,这是作为判断是否除到了最后一位数的依据

4. 如果商小于0,则把余数和商都压入栈

如果商大于0,则重复②③的操作以保证整串数字都压入栈

5. 将数字依次出栈并打印至界面

6. 输出子程序流程图如下:

2.2.16 回车换行子程序(crlf)

对输出内容进行回车换行处理,使程序输出内容更加美观,更有层次性,具体源码如下:

crlf:      ;回车换行
mov ah,2
mov dl,0DH
int 21H
mov dl,0AH
int 21H
ret

第三章 项目运行方式

3.1 汇编,链接,运行,调试说明

3.1.1 汇编、链接使用nasm的过程

在windows下打开cmd,切换到文件所在位置,输入编译命令nasm kt3.asm -f bin -o kt3.com,编译成功后可以得到一个以.com结尾的二进制文件

3.1.2 运行、调试使用DoxBox

1. 挂载本地文件夹:mount c c:\Users\10799\Desktop\huibian

2. 切换到挂载的文件夹上:c:

3. 运行以.com为结尾的文件:例如: kt3.com

3.2 运行过程:

1. 打开nasm,切换到文件目录,输入nasm kt3.asm -f bin -o kt3.com进行编译

126d9394e813ac38b6aaf43133d755e

图:nasm汇编

2. 打开DOSbox,输入mount c c:\Users\10799\Desktop\huibian进行挂载本地文件夹,输入c;切换到挂载的文件夹上,打开文件kt3.com

0b24d08f65c51a1bbcac25720c69d4d

图:程序运行初始界面运行过程

3. 运行程序进行加减乘除的运算以及循环运算功能的展示

(1) 加法运算,如图进行111+45和222+766的运算

7afc2c6a316d9547345c0f8af051ef8

图:加法运行过程

(2) 减法运算,如图进行100-34和87-345的运算

44b1c672bc7158e50cf728f49db521c

图:减法运行过程

(3) 乘法运算,如图进行345*765和23+76的运算

9ae9c9f8525f3dc32c5d12b169c8277

图:乘法运行过程

(4) 除法运算,如图进行100/23和4/122的运算

d68b74cd0fa3ec89ecc6ada402934e0

图:除法运行过程

(5) 循环运算功能,如图进行100+40、140/20、07-10、-03*40的运算

c4c271368fad6a231f361ccb42b08a9

图:循环运算过程

  • 19
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值