汇编语言实现计算器---可加减乘除括号负数混合运算

微机原理的大作业,用汇编写一个简单的计算器
实现中缀表达式计算
即(X–Y)*z/y+x=
可以输入负数,可以输入多位数

DATAS   SEGMENT
STR6    DB  'please input a formula:' ,'$'
STR7    DB  'CONTINUE(Y/N)?$'
SIGN1   DW  0
SIGN2   DW  0
SIGN3   DB  1    ;记录上一个输入的字符是数字还是符号
sign4   DB  0    ;记录打印输出中的非零
WARN DB 'You are tring to divide 0!',0AH,0DH,'$'
num     db  0        ;测试用
NUMBER  DW  40 DUP(0)
OPERATOR    DB  '$'
            DB  30  DUP(0)
ERROR   DB  'parenthesis not paired! syntax error!$'
INPUTWARN       DB      'ILLEGAL INPUT! ERROR$'
DATAS   ENDS
STACKS SEGMENT STACK
S  DB 256 DUP(?)
STACKS ENDS
SHOW    MACRO   STRING
        push    AX
        PUSH    DX
        MOV     DX,OFFSET   STRING
        MOV     AH,09H
        INT     21H
        POP     DX
        POP     AX
ENDM
char    MACRO   char      ;调试用
       push    DX
       push    AX
        MOV     DL,char
        add     dl,30h
        MOV     AH,02H
        INT     21H
        pop     AX
       pop     DX
ENDM
FQ      MACRO   ASCII,A,B
        CMP     AL,ASCII
        JNE     S&A
        MOV     CH,B
        JMP     S7
ENDM

HHHC    MACRO   
        MOV     AH,02H
        MOV     DL,0DH
        INT     21H
        MOV     AH,02H
        MOV     DL,0AH
        INT     21H
ENDM

CODES SEGMENT
;MAIN PROC FAR
ASSUME  CS:CODES,DS:DATAS,ES:DATAS,SS:STACKS
;重写除0中断************************************************************************
INT0 PROC FAR
PUSH DX
PUSH AX
HHHC
SHOW WARN
HHHC
POP AX
POP DX
MOV AH,4CH
INT 21H	
IRET
INT0 ENDP
START:
        MOV AX,0
        MOV ES,AX
        MOV DI,0
        MOV AX,OFFSET INT0
        CLD 
        STOSW
        MOV AX,SEG INT0
        STOSW
;将程序地址写入中断向量表
    MOV AX,DATAS
    MOV DS,AX
    MOV ES,AX
    LEA DI,NUMBER
    LEA SI,OPERATOR
START1:
    MOV SIGN1,0
    MOV SIGN2,0
    MOV SIGN3,1
    MOV SIGN4,0
    MOV AX,0
    MOV BX,0
    MOV CX,0
    MOV DX,0
    HHHC
    SHOW  STR6  

    HHHC
INPUT:

    MOV AH,01H
    INT 21H
    CMP AL,'='
    JE  LET0
    CMP AL,28H
    JB  INPUTWRONG
    CMP AL,39H
    JA INPUTWRONG
    CMP AL,2FH  ;判断是否是符号,2F是最后一个符号除号
    JBE LET1     ;转入符号处理
    INC SIGN1   ;数字处理
    MOV SIGN3,0
    SUB AL,30H    
    MOV AH,0
    XCHG AX,[DI]   ;第一次放入的数字不乘十,之后放入的数字先乘十在加上新来的
    MUL BX
    MOV BX,10
    ADD [DI],AX
    JMP INPUT
INPUTWRONG:
        HHHC
        SHOW INPUTWARN
        HHHC
        JMP INPUT

LET0:             ;=号转入
        CMP WORD PTR SIGN2,0   ;如果不缺括号继续往下处理
        JE  LET1
        JMP LET8
LET1:

        CMP WORD PTR SIGN1,0   ;没有数字
        JE  LET2                        
        ADD DI,2               ;已有数字而且检测到了运算符 数字堆栈后移一位  
        MOV WORD PTR SIGN1,0   ;清空标记
       
LET2:

        CALL DYFQ 
        cmp  ch,1
        jz   nex 
        mov  SIGN3,1
        jmp  next

nex:
        mov sign3,0
next:
        CMP  CH,5                ;是不是左括号
        JNE  LET3                ;不是下跳       
        INC  WORD PTR SIGN2      ;是变更配对标志位
LET3:
        CMP  CH,1                ;是不是右括号
        JNE  LET4                ;       
        DEC  WORD PTR SIGN2
LET4:
        CMP  BYTE PTR[SI],'$'    
        JE LET6
        CMP CH,[SI]               ;比较堆栈栈顶运算符优先级
        JA LET6                   ;若栈顶的小     
        CMP BYTE PTR [SI], 2           ;是不是左括号?
        JNE LET5
        DEC SI 
        
        JMP INPUT
LET5:
        CMP [SI],6
        JZ  NEGATIVE
RETURN:
        DEC SI                   ;吐出堆栈中运算符进行相应运算
        MOV CL,[SI]
        
        CALL YS
        JMP LET4

NEGATIVE:
        DEC SI
        MOV [SI],3FH    ;以问号作为求反操作码
        inc SI
        JMP RETURN

LET6:                              ;运算符堆栈空跳过来的或者要存放入栈
        CMP CH,0                  ;等号?
        JE OUTPUT
        CMP CH,1                  ;右括号      
        JE  INPUT                 ;右括号不保存
        INC SI                    ;指向栈的开始,第一个是$
        MOV [SI],AL               ;放进堆栈   放的是符号
        INC SI                    ;移位
        CMP CH,5                  ;是不是左括号
        JNE LET7                 
        MOV CH,2                 
LET7:
        MOV [SI],CH               ;SI里放得是优先级编码   
        JMP INPUT
LET8:
        LEA DX,ERROR
        MOV AH,09H
        INT 21H
        JMP EXIT
FQ      MACRO   ASCII,A,B
        CMP     AL,ASCII
        JNE     S&A
        MOV     CH,B
        JMP     S7
ENDM

DYFQ PROC 
    FQ 28H,1,5
S1: FQ 29H,2,1
S2: FQ 2AH,3,4
S3: FQ 2FH,4,4
S4: FQ 2BH,5,3
S5: FQ 3DH,6,0
S6: 
        CMP SIGN3,1
        JZ NEWQ
        FQ 2DH,7,3
        
NEWQ:
        FQ 2DH,7,6

S7: 
        RET
DYFQ ENDP

OUTPUT:
        SUB DI,2        ;初始是指向新数的
        CMP WORD PTR[DI],0
        JGE K1
        NEG WORD PTR[DI]
        MOV DL,'-'
        MOV AH,2
        INT 21H        
        and [di],7fh                  ;输出负数
K1:     MOV BX,10000
        MOV CX,5
        
K2:     MOV AX,[DI]
        CWD
        DIV BX
        MOV [DI],DX
        CMP AL,0    ;如果是0就不打印出来
        JNZ K3
        CMP SIGN4,0
        JNZ K3
        CMP CX,1
        JNZ DO2

        MOV AH,02h
        MOV DL,2EH
        INT 21H

DO2:
        CMP CX,1
        JZ K3
        JMP K4
K3:
        MOV DL,AL
        ADD DL,30H
        MOV AH,02H
        INT 21H
        MOV sign4,1

K4:     MOV AX,BX
        MOV DX,0
        MOV BX,10
        DIV BX
        MOV BX,AX    ;基值除10
        LOOP K2

        HHHC
        SHOW STR7
        MOV AH,01H
        INT 21H
        CMP AL,'N'
        JE EXIT
        CMP AL,'n'
        JE EXIT
        MOV WORD PTR[DI+2],0
        LEA DI,NUMBER
        LEA SI,OPERATOR
        JMP START1
EXIT:
        MOV AH,4CH
        INT 21H
YS PROC NEAR
        PUSH AX
        MOV AX,0
        MOV BX,0
        CMP CL,2AH
        JNE CHU
        SUB DI,2
        XCHG BX,[DI]
        SUB DI,2
        XCHG AX,[DI]
        IMUL BX             ;有符号乘法
        MOV [DI],AX
        ADD DI,2
        JMP FINISH
CHU:
        CMP CL,2FH
        JNE JIA
        SUB DI,2
        XCHG BX,[DI]
        SUB DI,2
        XCHG AX,[DI]
        CWD
        IDIV BX
        MOV [DI],AX
        ADD DI,2
        JMP FINISH
JIA:
        CMP CL,2BH
        JNE JIAN
        SUB DI,2
        XCHG BX,[DI]
        SUB DI,2
        ADD [DI],BX
        ADD DI,2
        JMP FINISH
JIAN:

        CMP CL,2DH
        JNE NEGA
        SUB DI,2
        XCHG BX,[DI]
        SUB DI,2
        SUB [DI],BX
        ADD DI,2
        JMP FINISH
NEGA:
        CMP CL,3FH
        JNE FINISH
        SUB DI,2
        NEG word ptr [DI]
        ADD DI,2

        
FINISH:
        POP AX
        RET
YS ENDP
CODES ENDS
END START

测试结果如下图所示
在这里插入图片描述

  • 8
    点赞
  • 64
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
以下是一个简单的51单片机汇编语言实现0-9的计算器的示例代码: ``` ORG 0H MOV P0,#0FFH ;设置P0口为输入口 MOV P1,#0H ;设置P1口为输出口 MOV P2,#0H ;设置P2口为输出口 MAIN: ACALL READ_NUM1 ;读取第一个数字 ACALL READ_NUM2 ;读取第二个数字 ACALL READ_OP ;读取运算符 ACALL CALC ;计算结果 ACALL DISPLAY ;显示结果 SJMP MAIN READ_NUM1: MOV R0,#10 ;设置循环次数 MOV A,#0H ;清零累器 LOOP1: MOV C,P0.0 ;读取P0.0口的值 JNC LOOP1 ;等待输入 ACALL DELAY ;延时去抖 MOV C,P0.0 ;再次读取P0.0口的值 JNC LOOP1 ;等待输入 ADD A,#0FH ;十进制转换 MOV B,A ;保存累器的值 MOV A,P0 ;读取输入值 ANL A,#0FH ;取低四位 ADD A,B ;上之前的结果 MOV B,A ;保存结果 DJNZ R0,LOOP1 ;循环10次结束 RET READ_NUM2: MOV R0,#10 ;设置循环次数 MOV A,#0H ;清零累器 LOOP2: MOV C,P0.0 ;读取P0.0口的值 JNC LOOP2 ;等待输入 ACALL DELAY ;延时去抖 MOV C,P0.0 ;再次读取P0.0口的值 JNC LOOP2 ;等待输入 ADD A,#0FH ;十进制转换 MOV B,A ;保存累器的值 MOV A,P0 ;读取输入值 ANL A,#0FH ;取低四位 ADD A,B ;上之前的结果 MOV B,A ;保存结果 DJNZ R0,LOOP2 ;循环10次结束 RET READ_OP: MOV R0,#10 ;设置循环次数 LOOP3: MOV C,P0.0 ;读取P0.0口的值 JNC LOOP3 ;等待输入 ACALL DELAY ;延时去抖 MOV C,P0.0 ;再次读取P0.0口的值 JNC LOOP3 ;等待输入 MOV A,P0 ;读取输入值 CPL A ;取反 ANL A,#0FH ;取低四位 CJNE A,#0EH,LOOP3 ;如果输入的不是+或-,重新输入 MOV B,A ;保存运算符 RET CALC: MOV A,B ;读取运算符 CJNE A,#0DH,ADD1 ;如果是+,跳转到ADD1 MOV A,R1 ;读取第一个数字 ADD A,R2 ;上第二个数字 MOV R3,A ;保存结果 SJMP CALC_END ADD1: MOV A,R1 ;读取第一个数字 SUBB A,R2 ;去第二个数字 MOV R3,A ;保存结果 CALC_END: RET DISPLAY: MOV A,R3 ;读取结果 MOV R0,#10 ;设置循环次数 LOOP4: MOV B,#0AH ;除以10 DIV AB MOV P2,B ;输出余数 INC P1 ;P1口指向下一位 DJNZ R0,LOOP4 ;循环10次结束 RET DELAY: MOV R7,#0FFH DELAY_LOOP: DJNZ R7,DELAY_LOOP RET END ``` 这个程序通过检测P0.0口的状态,读取用户输入的数字和运算符,并通过P2口输出余数,P1口控制位数,从而实现了一个简单的0-9计算器

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值