(此代码仅供学习使用,请勿用作其他用途)
摘要
本论文介绍了一款使用汇编语言编写的简单整数计算器程序,该程序支持基本的四则运算操作,并能处理包含括号的数学表达式。本文通过分析程序的代码结构,宏定义、数据段、子程序以及关键功能的实现,详细介绍了其设计与实现。同时,还讨论了程序的输入输出流程、符号优先级处理、运算逻辑、错误处理机制等方面的内容,以及代码中所使用的宏定义的功能。通过本文的阐述,读者将能够了解汇编语言中如何实现一个简单但完整的计算器程序。
引言
计算器是现代计算机科学中的一个重要应用,能够进行数学运算,解决各种实际问题。虽然现代计算器通常是软件应用程序,但在本文中,我们将介绍如何使用汇编语言设计和实现一个简单的整数计算器。该计算器能够执行加法、减法、乘法、除法等基本运算,同时支持使用括号改变运算的优先级。
数据段(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
运行截图:
.