- 基于汇编语言的简单整数计算器设计与实现
(此代码仅供学习使用,请勿用作其他用途)
摘要
本论文介绍了一款使用汇编语言编写的简单整数计算器程序,该程序支持基本的四则运算操作,并能处理包含括号的数学表达式。本文通过分析程序的代码结构,宏定义、数据段、子程序以及关键功能的实现,详细介绍了其设计与实现。同时,还讨论了程序的输入输出流程、符号优先级处理、运算逻辑、错误处理机制等方面的内容,以及代码中所使用的宏定义的功能。通过本文的阐述,读者将能够了解汇编语言中如何实现一个简单但完整的计算器程序。
引言
计算器是现代计算机科学中的一个重要应用,能够进行数学运算,解决各种实际问题。虽然现代计算器通常是软件应用程序,但在本文中,我们将介绍如何使用汇编语言设计和实现一个简单的整数计算器。该计算器能够执行加法、减法、乘法、除法等基本运算,同时支持使用括号改变运算的优先级。
数据段(Datas Segment)
程序的数据段包括字符串、标志、数值和运算符缓冲区。其中,字符串用于用户界面和错误信息的显示,标志用于跟踪输入状态,数值缓冲区用于存储数字,运算符缓冲区用于存储运算符和其优先级。这些数据段在程序运行时将用于输入、输出和计算。
宏定义
程序中使用了三个宏定义,分别是show
、fq
和hchh
。这些宏用于实现代码的复用和简化,使代码更加易读。show
宏用于显示字符串,fq
宏用于为运算符赋权值,hchh
宏用于在控制台输出时添加回车换行。
主程序(Main Procedure)
主程序是程序的入口点,它包括初始化数据段、显示用户界面、处理用户输入、进行运算和输出结果。主程序使用循环来不断接收用户输入,并根据用户的操作执行相应的计算和输出。如果用户输入的表达式不合法,程序会进行错误处理并提供相应的错误提示。
子程序(Procedures)
程序中包含了多个子程序,用于实现不同的功能。其中,dyfq
子程序用于为运算符赋予优先级,output
子程序用于输出计算结果,ys
子程序用于执行实际的运算操作。这些子程序提高了代码的可维护性和模块化程度。
运算逻辑
程序使用栈来处理运算符的优先级。栈中存储了运算符和它们的优先级,通过比较运算符的优先级来决定执行哪个运算。程序会根据用户输入的数学表达式,依次处理数字和运算符,同时根据运算符的优先级进行相应的计算。
错误处理
程序实现了错误处理机制,当用户输入的表达式存在括号不匹配、运算符不合法或其他错误情况时,程序会输出错误提示信息,并允许用户重新输入。这增加了程序的健壮性和用户友好性。
datas segment str1 db 0ah,0dh,'*******************************************$' str2 db 0ah,0dh,'* 1 2 3 4 5 *$' str3 db 0ah,0dh,'* 6 7 8 9 0 *$' str4 db 0ah,0dh,'* + - * / = *$' str5 db 0ah,0dh,'*******************************************$' str6 db 0ah,0dh, 'please input a formula: $' str7 db 'continue(y/n)$' sign1 dw 0 ;值为0代表输入的不是数字,为1代表输入的是数字 sign2 dw 0,0 ;值为0代表输入的符号是匹配的,为1输入的符号不匹配 number dw 20 dup(0) ;保存输入的数值 operator db '$' ;判断输入的运算符是否为空 db 10 dup(0) ;保存该运算符对应的权值 error db 'wrong!$' datas ends
STACKS SEGMENT STACKS ENDS
show macro str ;宏定义,显示字符串 lea dx,str mov ah,9 int 21h endm fq macro ascii,a,b ;宏定义,给运算符赋权值 cmp al,ascii jne s&a mov ch,b jmp s7 endm hchh macro ;宏定义,回车换行 mov ah,2 mov dl,0dh int 21h mov ah,2 mov dl,0ah int 21h endm
codes segment main proc far assume cs:codes,ds:datas start: mov ax,datas mov ds,ax lea di,number lea si,operator show str1 show str2 show str3 show str4 show str5 show str6 mov ax,0 mov bx,0 mov cx,0 mov dx,0 start1: hchh input: mov ah,1 int 21h cmp al,'=' je let0 cmp al,1bh je exit cmp al,28h ;第二种情况,第一次输入的与28h也就是‘(’比较 jb input ;小于28h=(则重新输入 因为不管数字还是符号都比(大 cmp al,39h ja input ;大于39h=9则重新输入 再大也用不着 cmp al,2fh ;判断是数字还是符号 jbe let1 ;是符号转入响应操作 inc word ptr sign1 ;是数字的话将数字标志位加1 sub al,30h ;ASCII码与数字差 mov ah,0 xchg ax,[di] ;mul用ax中数乘源操作数 mul bx mov bx,10 xchg ax,[di] add [di],ax jmp input call fun ret main endp fun proc near ;***********************************************************
let0: cmp word ptr sign2,0 ;判断配对标志位 je let1 ;经过左括号和右括号抵消为0则跳转 jmp let8 ;否则跳转到bc显示输入错误 let1: cmp word ptr sign1,0 je let2 add di,2 ; mov word ptr sign1,0 ;将数字标志位sign1复0 let2: call dyfq ;设定优先级 cmp ch,5 ;判断输入的符号是否是左括号 jne let3 ;不是则判断输入的是否是右括号 inc word ptr sign2 ;是左括号,括号标志位sign2加1 let3: cmp ch,1 ;判断输入的是否是右括号 jne let4 dec word ptr sign2 ;是右括号,括号标志位减1 let4: cmp byte ptr[si],'$' ;判断运算符存储区是否为空 je let6 cmp ch,[si] ;[si]的内容为前一个符号或其权值 ja let6 cmp byte ptr[si],'(' jne let5 dec si jmp input let5: dec si mov cl,[si] call ys ;判断是什么运算符并进行相应的计算 jmp let4 let6: cmp ch,0 ;判断是否是等号 je output cmp ch,1 je input ;“)”不保存,输入下一个数 inc si mov [si],al ;保存符号 inc si cmp ch,5 ;判断是否是左括号 jne let7 mov ch,2 ;改变(的权值 let7: mov [si],ch ;紧跟着保存符号的权值 jmp input let8: lea dx,error mov ah,9 int 21h jmp exit ret fun endp ;********************************************************************** dyfq proc ;子程序dyfq调用宏fq,判断优先级 fq 28h,1,5 ;调用宏fq为(赋权值 s1: fq 29h,2,1 ;调用宏fq为)赋权值 s2: fq 2ah,3,4 ;调用宏fq为*赋权值 s3: fq 2fh,4,4 ;调用宏fq为/赋权值 s4: fq 2bh,5,3 ;调用宏fq为+赋权值 s5: fq 2dh,6,3 ;调用宏fq为-赋权值 s6: fq 3dh,7,0 ;调用宏fq为=赋权值 s7: ret dyfq endp ;********************************************* output: ;输出运算结果 sub di,2 cmp word ptr[di],0 jge k1 neg word ptr[di] ;求负数的绝对值 mov dl,'-' mov ah,2 int 21h k1: mov bx,10000 mov cx,5 mov si,0 k2: mov ax,[di] cwd ;字到双字符的扩展 div bx mov [di],dx cmp al,0 jne k3 cmp si,0 jne k3 cmp cx,1 je k3 jmp k4 k3: mov dl,al add dl,30h mov ah,2 int 21h mov si,1 k4: mov ax,bx ;实现进制转换 mov dx,0 mov bx,10 div bx mov bx,ax loop k2 hchh show str7 mov ah,1 int 21h cmp al,'n' ;判断是否继续输入,输入n则结束操作 je exit cmp al,'N' je exit mov word ptr[di+2],0 lea di,number lea si,operator jmp start1 exit: mov ah,4ch int 21h ys proc near ;子程序,进行相应的运算 push ax mov ax,0 mov bx,0 cmp cl,2ah ;乘法运算 jne chu sub di,2 xchg bx,[di] sub di,2 xchg ax,[di] imul bx mov [di],ax add di,2 jmp finish chu: cmp cl,2fh ;除法运算 jne jia sub di,2 xchg bx,[di] sub di,2 xchg ax,[di] cwd idiv bx mov [di],ax add di,2 jmp finish jia: cmp cl,2bh ;加法运算 jne jian sub di,2 xchg bx,[di] sub di,2 add [di],bx add di,2 jmp finish jian: cmp cl,2dh ;减法运算 jne finish sub di,2 xchg bx,[di] sub di,2 sub [di],bx add di,2 finish: pop ax ret ys endp ;************************************************************** codes ends end start 运行截图:
.
标签:fq,di,汇编语言,手把手,mov,运算符,计算器,bx,cmp From: https://www.cnblogs.com/zzbcoder/p/17760895.html