📄 caculatorv20.asm
字号:
;算术表达式计算,16位定点,溢出,除0报告,要求运算错误能恢复,
;尽量压缩文件大小,紧奏。
;CaculatorV2.0
.8086
;*******************************************************************************
;*******************************************************************************
prognam segment
assume cs:prognam, ds:prognam, ss:prognam,
;*******************************************************************************
main proc near ;enter proc
;-----------------------------------------------------------------------
mov ax, prognam ;initial ritual
mov ds, ax
;-----------------------------------------------------------------------
mov oldsp, sp ;save sp and show welcome
call nextline
mov dx, offset welcome_str
call showbuffer
jmp short initial
;-----------------------------------------------------------------------
continuteornot: ;test whethe to continute
mov dx, offset continute_str
call showbuffer
mov ah, 1h
int 21h
cmp al, 'y'
jz short initial
cmp al, 'Y'
jz short initial
cmp al, 0dh
jz short initial
cmp al, 'n'
jz near ptr main_end
cmp al, 'N'
jz near ptr main_end
call nextline
jmp short continuteornot
;-----------------------------------------------------------------------
initial: call nextline
call nextline
mov dx, offset initial_str ;show initial information
call showbuffer
mov ah, 0ah ;get in char buffer
mov dx, offset char_lenght
int 21h
;-----------------------------------------------------------------------
sub cx, cx ;add "="
mov cl, actlen
jcxz short continuteornot
call nextline
mov bx, offset char_buffer
add bx, cx
mov [bx], '='
inc actlen
;-----------------------------------------------------------------------
call caculation ;real caculation
;-----------------------------------------------------------------------
mov dx, offset result_str
call showbuffer
mov ax, opnd ;show result
mov bx, offset char_buffer
add bx, 10h
mov byte ptr [bx], '$'
;-------------------------------------------------------
sub si, si
cmp ax, 0h ;if result is below 0
jz short printzero
jg short abovezero
neg ax
mov si, 1h
;-------------------------------------------------------
abovezero: mov cx, 10 ;if result is above 0
loopdigit: sub dx, dx
div cx
add dl, '0'
dec bx
mov byte ptr [bx], dl
cmp ax, 0
jnz short loopdigit
cmp si, 0
jz short showend
dec bx
mov byte ptr [bx], '-'
jmp short showend
;-------------------------------------------------------
printzero: dec bx ;if result equ 0
mov byte ptr [bx], '0'
;-------------------------------------------------------
showend: mov dx, bx
call showbuffer
call nextline ;turn to next line
jmp near ptr continuteornot
;-----------------------------------------------------------------------
main_error: mov dx, offset error_str ;due with error
jmp short showerror
overflow: mov dx, offset overflow_str
jmp short showerror
divisorzero: mov dx, offset divisor_str
showerror: call showbuffer
mov sp, oldsp
jmp near ptr continuteornot
;-----------------------------------------------------------------------
main_end: call nextline
mov ax, 4c00h
int 21h
;-----------------------------------------------------------------------
main endp
;*******************************************************************************
showbuffer proc near ;show a line of char
mov ah, 9h ;using ah adn dx
int 21h
ret
showbuffer endp
;*******************************************************************************
nextline proc near ;show a line of char
mov ah, 9h ;using ah adn dx
mov dx, offset nextline_str
int 21h
ret
nextline endp
;*******************************************************************************
caculation proc near
;-----------------------------------------------------------------------
mov opnd_top, offset opnd ;initial for caculation
mov optr_top, offset optr
inc optr_top
mov optr, 6
mov char_top, offset char_buffer
mov char_end, offset actlen
mov al, actlen
sub ah, ah
add char_end, ax
mov al, char_buffer
mov currentchar, al
mov caculat_cnt, 100h
;-----------------------------------------------------------------------
nextopr: dec caculat_cnt ;has it reach the end?
jz near ptr main_error
cmp opnd_top, offset opndtest
jnz short notendyet
mov ax, char_end
cmp char_top, ax
jz near ptr caculat_end
;-------------------------------------------------------
notendyet: cmp currentchar, ' ' ;skip blank
jnz short notblank
inc char_top
mov bx, char_top
mov al, [bx]
mov currentchar, al
jmp short nextopr
;-------------------------------------------------------
notblank: cmp currentchar, '0' ;is it opratand?
jl short notopnd
cmp currentchar, '9'
jg short notopnd
;-------------------------------------------------------
sub ax, ax ;char to volume
mov bx, char_top
nextdigit: mov cl, [bx]
cmp cl, '0'
jl short pushopnd
cmp cl, '9'
jg short pushopnd
mov dx, 10
mul dx
jo near ptr overflow
mov dh, 10000000b
and dh, ah
jnz near ptr overflow
sub cl, '0'
add al, cl
adc ah, 0h
jo near ptr overflow
inc bx
jmp short nextdigit
;-------------------------------------------------------
pushopnd: mov char_top, bx ;push the opnd
mov currentchar, cl
mov bx, opnd_top
mov [bx], ax
add opnd_top, 2h
jmp near ptr nextopr
;-----------------------------------------------------------------------
notopnd: mov al, currentchar ;test whethe ( and )
cmp al, ')'
jnz otheropnd
mov bx, optr_top
mov dl, [bx-1]
cmp dl, 04h
jnz otheropnd
dec optr_top
inc char_top
mov bx, char_top
mov dl, byte ptr [bx]
mov currentchar, dl
jmp near ptr nextopr
;-------------------------------------------------------
otheropnd: cmp al, '+' ;test what optr is it
jz charadd
cmp al, '-'
jz charsub
cmp al, '*'
jz charmul
cmp al, '/'
jz chardiv
cmp al, '('
jz charleft
cmp al, ')'
jz charright
cmp al, '='
jz charequ
jmp near ptr main_error
;-------------------------------------------------------
charadd: mov ch, 10000000b ;get ready for precedence test
sub ah, ah
jmp short testpreced
charsub: mov ch, 01000000b
mov ah, 1h
jmp short testpreced
charmul: mov ch, 00100000b
mov ah, 2h
jmp short testpreced
chardiv: mov ch, 00010000b
mov ah, 3h
jmp short testpreced
charleft: mov ch, 00001000b
mov ah, 4h
jmp short testpreced
charright: mov ch, 00000100b
mov ah, 5h
jmp short testpreced
charequ: mov ch, 00000010b
;-------------------------------------------------------
testpreced: mov bx, optr_top ;test the precedence of optr
sub dx, dx
mov dl, [bx-1]
xchg dx, bx
mov cl, pritable[bx]
xchg dx, bx
and cl, ch
jnz to_caculat ;if former optr in pri
;-------------------------------------------------------
mov [bx], ah ;later optr in pri
inc optr_top
inc char_top
mov bx, char_top
mov dl, byte ptr [bx]
mov currentchar, dl
jmp nextopr
;-----------------------------------------------------------------------
to_caculat: dec optr_top ;real caculat, get ready
sub opnd_top, 2h
mov cl, dl
mov bx, opnd_top
mov dx, [bx]
mov ax, [bx-2]
;-------------------------------------------------------
cmp cl, 0 ;test what kind of optr
jz short toadd
cmp cl, 1
jz short tosub
cmp cl, 2
jz short tomul
cmp cl, 3
jz short todiv
jmp near ptr main_error
;-------------------------------------------------------
toadd: add ax, dx
jmp short newopnd
tosub: sub ax, dx
jmp short newopnd
tomul: imul dx
jmp short newopnd
todiv: cmp dx, 0h
jz near ptr divisorzero
mov cx, dx
cwd
idiv cx
clc
;-------------------------------------------------------
newopnd: jo near ptr overflow
mov [bx-2], ax
jmp near ptr nextopr
;-----------------------------------------------------------------------
caculat_end:
ret
caculation endp
;*******************************************************************************
;-----------------------------------------------------------------------
char_lenght db 50 ;data buffer
actlen db ?
char_buffer db 51 dup(?)
opnd dw ?
opndtest dw 10 dup(?)
optr db 10 dup(?)
;-----------------------------------------------------------------------
currentchar db ?
opnd_top dw ?
optr_top dw ?
char_top dw ?
char_end dw ?
caculat_cnt dw ?
oldsp dw ?
;-----------------------------------------------------------------------
pritable db 11000110b ;precedence information
db 11000110b
db 11110110b
db 11110110b
db 00000010b
db 11111110b
db 00000010b
;-----------------------------------------------------------------------
welcome_str db 0dh, 0ah, 0dh, 0ah,"Caculator2.0", 0dh, 0ah
db "Public by SilentEcho, all right reserved",'$'
result_str db "RESULT: ", '$'
overflow_str db "ERROR: Overflow, only 16 Bit available", 0dh, 0ah, '$'
initial_str db "Please enter an expression", 0dh, 0ah, '$'
error_str db "ERROR: Invalid expression", 0dh, 0ah, '$'
divisor_str db "ERROR: Divisor is Zero", 0dh, 0ah, '$'
continute_str db "Would you want to continute? [Yes/No] [Y]", '$'
nextline_str db 0dh, 0ah, '$'
db 10 dup(?)
result db 0dh, 0ah, '$'
;-----------------------------------------------------------------------
;*******************************************************************************
prognam ends
;*******************************************************************************
;*******************************************************************************
end main
;-----------------------------------------------------------------------
;-------------------------------------------------------
;-------------------------------------------------------
;-------------------------------------------------------
;-----------------------------------------------------------------------
;-------------------------------------------------------
;-------------------------------------------------------
;-------------------------------------------------------
;-----------------------------------------------------------------------
;-------------------------------------------------------
;-------------------------------------------------------
;-------------------------------------------------------
;-----------------------------------------------------------------------
;-------------------------------------------------------
;-------------------------------------------------------
;-------------------------------------------------------
;-----------------------------------------------------------------------
;-------------------------------------------------------
;-------------------------------------------------------
;-------------------------------------------------------
;-----------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -