您的位置:首页 > 其它

05 简易计算器

2015-12-14 22:11 423 查看
前言

1 仅仅支持两个操作数一个操作符的计算

2 输入为十进制, 输出为十六进制

参考代码

assume cs:code, ds:data, ss:stack

data segment
notice  db 'please input a plus/subtract/multiply/divide expression : $ '      ; notice information
buffer  db 16                               ; the buffer to saved the information user inputed, and result show information
db 0
db 32 dup (0), ' $ '
operand dw 4 dup (0)                        ; save the operand and operator and calcute result
; result db 32 dup (0)
errInfo db 0aH, 0dH, 'have no operator.... $ ' ; save the error information
tmp     dw 2 dup (0)                        ; the temp memory for save offset

data ends

stack segment
db 128 dup (0)

stack ends

code segment

start:
mov ax, data
mov ds, ax
mov ax, stack
mov ss, ax      ; initilization ds, ss

lea dx, notice
mov ah, 9
int 21H         ; output notice information

lea dx, buffer
mov ah, 10
int 21H         ; let user to input

mov cl, buffer[1]
mov ch, 0       ; get the length of user inputed

call getOperator    ; get operator, and offset saved in si, and save it into 'operand[1]'

; call getNumValue

call getOperand     ; get the operand, save it into 'operand', 'operand[2]'

call calcuteIt      ; to calcute the expression

call putResultIntoMemory    ; put the information into specified memory

lea dx, buffer+2    ; show the result information
mov ah, 9
int 21H

mov ax, 4c00H       ; return to cmd
int 21H

; getNumValue proc near

; getNumValueLoop1:

; loop getNumValueLoop1

; getNumValue endp

putResultIntoMemory proc near           ; put the result into memory for show
push di
push bx

mov di, cx
add di, 2
mov buffer[di], '='
mov bx, operand[6]
call calcOneWord

pop bx
pop di

ret

putResultIntoMemory endp

calcHalfByte    proc near   ; calc the bl [----just judge lower four bit----]' s corresponding ascii code, save in bl
; push bx           ; bl record the data[need to be transfer]
push cx         ; record the offset to save in exp data segment

cmp bl, 9
ja abc
; bl not bigger than 9
; mov [exp+cx], bl+48       ; 1 ~ 8
add bl, 48
jmp calcHalfByteEnd

abc:            ; bl bigger than 9
; mov [exp+cx], bl+87       ; A ~ F
add bl, 87

calcHalfByteEnd:
pop cx

ret

calcHalfByte endp

calcHalfWord proc               ; to calcute two hexadecimal number, number saved in bl, need to push two offset relative exp flag to save data
push bx
push di
push dx
push cx

; add sp, 4                 ; mov stack pointer to save data offset, why there need just add 2 bit ? it just push ip in stack ?

mov dx, bx
mov cl, 4                   ; calc the upper 4 bit
shr bl, cl
call calcHalfByte
; pop di
mov di, ds:[tmp]            ; the segment of tmp must match the left value[cx], use dw to define data
mov ds:[buffer+di], bl

mov bx, dx                  ; calc the lower 5 bit
and bl, 15
call calcHalfByte
; pop di
mov di, ds:[tmp+2]
mov ds:[buffer+di], bl

; sub sp, 6                 ; mov stack pointer to the real stack top
; why the value in stack changed ???        --2014.07.25

pop cx
pop dx
pop di
pop bx

ret

calcHalfWord endp

calcOneWord proc near           ; to calcute two hexadecimal number, number saved in 'bx', 'di' saved the memory offset,
push dx
push di

mov dx, bx

mov cl, 8                   ; calc the upper 8 bit of bx
shr bx, cl
inc di
mov ds:[tmp], di
inc di
mov ds:[tmp+2], di
call calcHalfWord

mov bx, dx                  ; calc the lower 8 bit of bx
mov bh, 0
inc di
mov ds:[tmp], di
inc di
mov ds:[tmp+2], di
call calcHalfWord

pop di
pop dx

ret

calcOneWord endp

calcuteIt proc near             ; to calcute the value of expression, and save it to specified memory
push bx
push ax
push dx

mov bx, operand[2]
cmp bx, 1
jz opePlus2
cmp bx, 2
jz opeSub2
cmp bx, 3
jz opeMul2
cmp bx, 4
jz opeDiv2

jmp calcuteItEnd

opePlus2:
mov ax, ds:[operand]
add ax, operand[4]
mov operand[6], ax

jmp calcuteItEnd

opeSub2:
mov ax, ds:[operand]
sub ax, operand[4]
mov operand[6], ax

jmp calcuteItEnd

opeMul2:
mov ax, ds:[operand]
mul  operand[4]
mov operand[6], ax              ; for simple, ignore dx

jmp calcuteItEnd

opeDiv2:
mov ax, ds:[operand]
div  operand[4]
mov operand[6], ax              ;

jmp calcuteItEnd

calcuteItEnd:

pop dx
pop ax
pop bx

ret

calcuteIt endp

getOperand proc near                ; to get two operand, and put them into specified meomry
push di
push si
push dx
push cx

cmp operand[1], 0
jz getOperandOnError

; mov cx, si-2              ; error
; mov di, si-1

mov cx, si
sub cx, 2
mov di, si
dec di
mov al, 1
mov dx, 0

call getOperandValue
mov ds:[operand], dx

pop cx
push cx
; mov cx, dx+1-si           ; error
; mov di, dx+1

sub cx, si
inc cx

mov di, cx
add di, si

mov al, 1
mov dx, 0
call getOperandValue
mov ds:[operand+4], dx

jmp getOperandEnd

getOperandOnError:          ; address flag can't duplicated with others flag
call onError

getOperandEnd:

pop cx
pop dx
pop si
pop di

ret

getOperand endp

getOperandValue proc near               ; get operand NumberValue by the number string in memory 1 2 3 -> 123
push di
push ax

getOperandValueLoop1:
mov ah, buffer[di]
call getNumValue

push ax
mul ah
add dx, ax
pop ax
mov ah, 10
mul ah

dec di
loop getOperandValueLoop1

pop ax
pop di

ret

getOperandValue endp

getNumValue proc near                   ; get NumberValue by ascii

cmp ah, 48
jae numFlag1
jmp getNumValueEnd

numFlag1:
cmp ah, 57
jbe numFlag2
jmp alphaFlag1

numFlag2:
sub ah, 48
jmp getNumValueEnd

alphaFlag1:
cmp ah, 97
jae alphaFlag2
jmp getNumValueEnd

alphaFlag2:
cmp ah, 102
ja getNumValueEnd
sub aH, 87

getNumValueEnd:

ret

getNumValue endp

onError proc near               ; deal while error happened
push dx
push ax

lea dx, errInfo
mov ah, 9
int 21H

pop ax
pop dx

ret

onError endp

getOperator proc near           ; get the operator in expression, the offset of operator saved in 'si'
push cx
push bx

mov si, 2

getOperatorLoop1:
mov bl, buffer[si]
call ifIsOperator

jc getOperatorEnd
inc si
loop getOperatorLoop1

getOperatorEnd:

pop bx
pop cx

ret

getOperator endp

ifIsOperator proc near              ; to judge if 'bl' is a operator

cmp bl, 43
jz opePlus
cmp bl, 45
jz opeSub
cmp bl, 42
jz opeMul
cmp bl, 47
jz opeDiv

jmp ifIsOperatorEnd

opePlus:
mov operand[2], 1
jmp ifIsOperatorBeforeEnd

opeSub:
mov operand[2], 2
jmp ifIsOperatorBeforeEnd

opeMul:
mov operand[2], 3
jmp ifIsOperatorBeforeEnd

opeDiv:
mov operand[2], 4
jmp ifIsOperatorBeforeEnd

ifIsOperatorBeforeEnd:
stc

ifIsOperatorEnd:

ret

ifIsOperator endp

code ends

end start

; made by 970655147         2014.07.27


效果截图 :
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: