前言
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

效果截图 :

05 简易计算器_bc