?? express.asm
字號:
;*************************************************************************
;題目:算式計算
;要求:輸入一個由“+,-,*,/,()”組成的算式,運算結(jié)果為:-32767至+32768,計算并顯示結(jié)果。
;提示:運用分支,循環(huán),子程序等編程形式,運用鍵盤,顯示器,文件的中斷調(diào)用,顯示時注意字符與符值的轉(zhuǎn)換。
;*************************************************************************
mpush macro opr
sub di,2
mov word ptr[di],opr
endm
mpop macro opr
mov opr,word ptr[di]
add di,2
endm
npush macro opr
sub bx,2
mov word ptr[bx],opr
endm
npop macro opr
mov opr,word ptr[bx]
add bx,2
endm
;***********************************************************
data segment
n db 49,?
express db 50 dup(?)
db 52 dup(?) ;運算符棧
toem label word
db 10 dup(0) ;數(shù)字棧
toen label word
;標志
flag db ?
brace db 0
negate db ?
;提示信息
result db 13,10,"The result is $"
mess0 db 13,10,"Error:Invalid expression!",13,10,'$'
mess1 db 13,10,"Error:Over flow!",13,10,'$'
mess2 db 13,10,"Error:Divide zero.",13,10,'$'
table dw ?,addition,subtration,multiplication,division
data ends
stack segment
dw 30 dup(?)
toe label word
stack ends
;***********************************************************
code segment
assume cs:code,ds:data
call_c proc far
mov ax,data
mov ds,ax
mov es,ax
mov ax,stack ;load ss,sp
mov ss,ax
mov sp,offset toe
mov di,offset toem ;運算符棧棧頂
mov bx,offset toen ;數(shù)字棧棧頂
;MAIN PART OF THE PROGRAM GOES HERE:
mov ah,0ah ;輸入表達式
mov dx,offset n
int 21h
push bx ;在表達式末尾加';'
mov bl,n+1
mov bh,0
mov express[bx],';'
pop bx
lea si,express
call compute ;計算表達式
mov dx,offset result ;輸出提示信息
mov ah,9
int 21h
mov ax,[bx]
call binidec ;輸出結(jié)果
mov ax,4c00h ;返回DOS
int 21h
call_c endp
;-----------------------------------------------------------
;function:對表達式中的元素判斷并分類
;input: es:si the head of the express
;output:toen棧中bx所指向的為表達式的值
;Require:表達式以分號結(jié)尾
;-----------------------------------------------------------
compute proc near
;現(xiàn)場保護
;初始化
mpush 0 ;';'入運算符棧
mov dl,0
mov flag,0
mov negate,0
;-------------------------------
;是否結(jié)束的判斷
rotate: cmp byte ptr [si],';'
jne not_semicolon
cmp brace,0 ;錯誤判斷
jne error0_m
judge_error_flag:
cmp flag,2
jne error0_m
judge_stack_top_semicolon: ;遇到';'或')'時
cmp word ptr [di],0 ;是';'嗎?
je exit_r
call account ;運算符棧棧頂不是分號時計算
jmp judge_stack_top_semicolon
exit_r: mpop ax ;讀到表達式結(jié)尾并且運算符棧棧頂為分號時退出(';'出棧)
;現(xiàn)場恢復
ret
not_semicolon:
cmp byte ptr [si],')'
jne judge
dec brace
js error0_m
jmp judge_error_flag
error0_m:
jmp error0
;--------------------------------
;判斷是否為數(shù)字
judge: mov al,byte ptr [si]
sub al,30h
cmp al,9
jbe number
jmp operator
number: call convey_number
jmp next
;--------------------------------
;判斷是否為運算符
operator:
cmp byte ptr [si],'+'
jne judge_subtration
mov dh,1
mov cx,0101h
cmp flag,0
jne judge_error
mov flag,1
jmp next
judge_subtration:
cmp byte ptr [si],'-'
jne judge_multiplication
mov dh,1
mov cx,0102h
cmp flag,0
jne judge_error
mov negate,1
mov flag,1
jmp next
judge_multiplication:
cmp byte ptr [si],'*'
jne judge_division
mov dh,2
mov cx,0203h
jmp judge_error
judge_division:
cmp byte ptr [si],'/'
jne judge_bracket
mov dh,2
mov cx,0204h
judge_error:
cmp flag,2
jne error0
call calculate
jmp next
;-----------------------------------
;判斷是否為'('
judge_bracket:
cmp byte ptr [si],'('
jne error0
cmp flag,1
ja error0
inc brace
inc si
call compute
mov flag,2
jmp next
;-----------------------------------
;出錯信息
error0: mov ah,9
mov dx,offset mess0
int 21h
mov ax,4c00h
int 21h
;-----------------------------------
next: inc si
jmp rotate
compute endp
;-----------------------------------------------------------
;function:將一串ASCII碼轉(zhuǎn)換為一個二進制數(shù)
;input:Si指向表達式
; 用negate指示是否對轉(zhuǎn)換好的數(shù)求補(negate=1則求補)
;output:將轉(zhuǎn)換好的數(shù)入toen棧(數(shù)字棧)
;Require:已定義好數(shù)字棧,并用宏npush進行入棧操作
; 需調(diào)用decibin子程,請注意其要求
;-----------------------------------------------------------
convey_number proc near
push ax
call decibin
cmp negate,1
jne plus
neg ax
mov negate,0
plus: npush ax
mov flag,2
pop ax
ret
convey_number endp
;-----------------------------------------------------------
;function:將十進制數(shù)轉(zhuǎn)換為二進制數(shù)
;input:Si指向表達式
;output:轉(zhuǎn)換后的數(shù)放在AX中
;instruction:遇到非數(shù)字字符就認為該串數(shù)字結(jié)束
; 如數(shù)字過大導致溢出,則輸出提示信息后程序結(jié)束
; 出錯信息名為mess1,請在數(shù)據(jù)段中定義
;-----------------------------------------------------------
decibin proc near
push bx
push cx
push dx
mov bx,0
newchar:mov al,byte ptr [si]
sub al,30h
jl exit
cmp al,9d
jg exit
cbw
;digit is now in AX
;Multiply number in BX by 10 decimal
xchg ax,bx
mov cx,10d
imul cx
jno c1
jmp decibin_error1
c1: xchg ax,bx
;Add digit in AX to number in BX
add bx,ax
jno c2
jmp decibin_error1
c2: inc si
jmp newchar
exit: mov ax,bx ;將得數(shù)存入AX
dec si ;保證SI指向的是數(shù)字的最后一個
pop dx
pop cx
pop bx
ret
decibin_error1: ;出錯處理
mov ah,9
mov dx,offset mess1
int 21h
mov ax,4c00h
int 21h
decibin endp
;-----------------------------------------------------------
;function:按優(yōu)先級順序判斷并計算表達式
;input:cx:運算符編號
; dh:當前運算符的優(yōu)先級
; dl:前一運算符的優(yōu)先級
;require:已定義好運算符棧,并使用宏mpush,mpop進行初入棧操作
; 需調(diào)用account子程
;-----------------------------------------------------------
calculate proc near
judge_PRI:
cmp dh,dl ;比較當前運算符與前一運算符的優(yōu)先級
jbe below_equal
mpush cx ;大于
mov dl,dh
mov flag,1
ret
below_equal:
jb below
call account ;等于
mpush cx
mov flag,1
ret
below: call account
mov dl,byte ptr [di+1]
jmp judge_PRI
calculate endp
;-----------------------------------------------------------
;function:根據(jù)運算符計算表達式
;-----------------------------------------------------------
account proc near
push cx
push dx
push si
npop cx ;彈出兩個操作數(shù)
npop ax
mpop si ;彈出運算符
and si,0ffh ;將si的高字節(jié)清零
shl si,1
jmp table[si]
addition:
add ax,cx
jo error1
jmp account_exit
subtration:
sub ax,cx
jo error1
jmp account_exit
multiplication:
imul cx
jo error1
jmp account_exit
division:
cmp cx,0
je error2
cwd
idiv cx
jmp account_exit
error1: mov ah,9
mov dx,offset mess1
int 21h
mov ax,4c00h
int 21h
error2: mov ah,9
mov dx,offset mess2
int 21h
mov ax,4c00h
int 21h
account_exit:
npush ax
pop si
pop dx
pop cx
ret
account endp
;-----------------------------------------------------------
;function:將ax中的數(shù)轉(zhuǎn)換為10進制數(shù)輸出。
;input:ax
;output:none
;-----------------------------------------------------------
binidec proc near
push cx
push dx
push ax
push bx
;MAIN PART OF THE PROGRAM GOES HERE:
mov ch,0 ;CH為0則AX為正數(shù),CH為1則Ax為負數(shù)
cmp ax,0
jge normal
neg ax
mov ch,1
normal: mov cl,0 ;計數(shù)器置零
mov bx,10
binidec_next:
mov dx,0
div bx
push dx
inc cl
cmp ax,0
jne binidec_next
cmp ch,1
jne print
mov ah,2
mov dl,'-'
int 21h
print: pop ax
mov dl,al
add dl,30h
mov ah,2
int 21h
dec cl
jne print
pop bx
pop ax
pop dx
pop cx
ret
binidec endp
code ends
end call_c
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -