;作者:HelloMsg
;网址:http://www.cnblogs.com/wbb2109/
;邮箱:wangbb844918243@gmail.com
;时间:2011.11.26
;带括号的四则运算
;算法:1.将键盘输入的计算式(中缀式)存入array1中sub8;
; 2.将中缀式转换为后缀式存入array2中,算法思想:
; 从左至右逐字(word)读取array1中的内容:
; a.当当前字符为数字时,直接输出到array2;
; b.当当前字符为"("时,将其压栈;
; c.当当前字符为")"时,则弹出堆栈中最上的"("之前的所
; 有运算符并输出到array2,然后删除堆栈中的"(" ;
; d.当当前字符为运算符时,则依次弹出堆栈中优先级大于
; 等于当前运算符的,存入array2.再将当前运算符压栈
; c.当为"="时,弹出所有栈中的内容存入array2.
; 3.建立一个栈,然后从左至右扫描array2,每遇到操作数
; 就压入栈中,每遇到运算符号,就弹出栈顶的操作数,
; 完成相应的操作并把结果再压入栈中。最后的结果将保
; 留在栈顶。
; 4.输出结果
;提示:该程序只对输入操作数小于65280,每步运算结果小于65535的
; 计算式有效。并且都是正整数。
assume cs:code,ds:data,ss:stack
data segment
array1 dw 100 dup(0) ;存放中缀表达式
array2 dw 100 dup(0) ;存放后缀表达式
;operator '(','=','+','-','*','/',作者约定优先级别为0,0,1,1,2,2
data ends
stack segment
dw 100 dup(0)
stack ends
code segment
main proc far
mov ax,data
mov ds,ax
mov ax,stack
mov ss,ax
mov sp,200
call sub8
call sub9
call sub10
call sub11
mov ah,0
int 16h
main endp
;使运算符高八位为0ffh,以区别内存中的操作数和运算符。
;这就是为什么规定输入的操作数要小于65280 。
sub8 proc near ;将计算式按中缀式存入array1中
push ax
push bx
push dx
lea di,array1
xor cx,cx
aa2: mov ah,1
int 21h
cmp al,30h ;判断若小于48,则为运算符
jc aa5
cmp al,3ah ;判断若大于57,则为等于号
jnc aa1
add cx,cx ;否则为0~9,将其由ascii转换为数值
mov bx,cx
add cx,cx
add cx,cx
add cx,bx
and ax,0fh
add cx,ax
jmp aa2
aa3: mov [di],cx
inc di
inc di
mov cx,0 ;将数值存入内存,并cx赋0,标记其以存入内存
aa4: mov ah,0ffh ;通过高8位区别数字还是运算符
mov [di],ax
inc di
inc di
jmp aa2
aa5: cmp cx,0 ;判断前面输入的是不是数字
jz aa4
jmp aa3
aa6: mov [di],cx
inc di
inc di
mov cx,0
aa1: cmp cx,0 ;判断若在输入等号的前一位是数值
jnz aa6 ;则存入内存
mov ah,0ffh
mov [di],ax
pop dx
pop bx
pop ax
ret ;返主
sub8 endp
sub9 proc near ;中缀式转后缀式,存入array2
sub cx,cx
push ax
push bx
push dx
mov ax,'='
mov ah,0ffh
push ax
inc cx
lea di,array1
lea si,array2
bb1: mov ax,[di]
inc di
inc di
cmp ah,0ffh ;小于0ffh就为数字
jnc bb2 ;大于0ffh就为运算符
mov [si],ax
inc si
inc si
bb3: jmp bb1
bb2: cmp al,'('
jz bb4 ;若为“(”,则压入栈
cmp al,')' ;若为“)”,则弹出栈中最上的
jz bb5 ;'('之前的所有运算符并输出到array2
cmp al,'=' ;若为“=”,则弹出栈中的所有
jz bb6
bb11:mov bp,sp
cmp al,'+'
jz bb7
cmp al,'-'
jz bb7
cmp al,'*'
jz bb9
cmp al,'/'
jz bb9
bb4: push ax
inc cx
jmp bb1
bb5: pop ax
dec cx
cmp al,'('
jz bb1
;cmp al,'='
; jz bb6
mov [si],ax
inc si
inc si
jmp bb5
bb7: cmp byte ptr [bp],'+'
jz bb12
bb8: cmp byte ptr [bp],'-'
jz bb12
bb9: cmp byte ptr [bp],'*'
jz bb12
bb10:cmp byte ptr [bp],'/'
jz bb12
jmp bb4
bb12: pop bx
dec cx
mov [si],bx
inc si
inc si
jmp bb11
bb6: pop ax
mov [si],ax
inc si
inc si
loop bb6
pop dx
pop bx
pop ax
ret
sub9 endp
sub10 proc near
push ax
push bx
push dx
lea si,array2
pp1:mov ax,[si]
inc si
inc si
cmp ah,0ffh
jz pp2
push ax
jmp pp1
pp2:cmp al,'='
jz pp7
pop bx
pop dx
cmp al,'+'
jz pp3
cmp al,'-'
jz pp4
cmp al,'*'
jz pp5
cmp al,'/'
jz pp6
pp3:add dx,bx
push dx
jmp pp1
pp4:sub dx,bx
push dx
jmp pp1
pp5:mov ax,dx
mul bx
push ax ;用的是16位乘法,高位放在dx里,
jmp pp1 ;低位放在ax里,这里约定结果小于65535
pp6:mov ax,dx
mov dx,0 ;因为16位(除数)除法,则高16位默认在dx里,
;所以要将dx置零
div bx ;ax存商,dx存 余数
push ax
jmp pp1
pp7:pop cx
pop dx
pop bx
pop ax
ret ;返主
sub10 endp
sub11 proc near ;将结果以十进制形式输出到屏幕
push ax
push bx
push dx
cmp cx,10000
jnc a12
cmp cx,1000
jnc a4
cmp cx,100
jnc a6
cmp cx,10
jnc a8
jmp a10
a12:mov dl,-1
a3: sub cx,10000
inc dl
jnc a3
add cx,10000
or dl,30h
mov ah,2
int 21h
a4: mov dl,-1
a5: sub cx,1000
inc dl
jnc a5
add cx,1000
or dl,30h
mov ah,2
int 21h
a6: mov dl,-1
a7: sub cx,100
inc dl
jnc a7
add cx,100
or dl,30h
mov ah,2
int 21h
a8: mov dl,-1
a9: sub cx,10
inc dl
jnc a9
add cx,10
or dl,30h
mov ah,2
int 21h
a10:mov dl,cl
or dl,30h
mov ah,2
int 21h
pop dx
pop bx
pop ax
ret ;返主
sub11 endp
code ends
end main
欢迎访问我的bolg:http://www.cnblogs.com/wbb2109