📄 e3.asm
字号:
DATA SEGMENT
CRLF DB 0AH,0DH,"$" ;此处输入数据段代码
INPUTHINT DB 0AH,0DH,"input the expression: ",'$'
ERRORINPUTMSG DB 0AH,0DH,"ILLEAGLE INPUT.",0AH,0DH,'$'
ERRORTWOOPERATOR DB 0AH,0DH,"THERE ARE TWO OPERATOR ADJACENT!",0AH,0DH,'$'
ERRORFIRSTCHAR DB 0AH,0DH,"THE FIRST CHARACTER MUST BE '(','+','-',OR A DIGIT.",0AH,0DH,'$'
OPSTACK DB 256 DUP(0) ; operator stack
INFIX DB 512 DUP(0) ; infix expression stack
CHLAST DB -1 ; the character that is reat last time.
DATASTACK DW 256 DUP(0) ; data stack
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE, DS:DATA
MAIN PROC FAR
MOV AX, DATA
MOV DS, AX
MOV AH, 9
LEA DX, INPUTHINT
INT 21H
CALL INPUT
CALL CALCULATE
CALL PRINT
MOV AH, 4CH
INT 21H
INPUT PROC NEAR
PUSH AX
PUSH BX
LEA BX, INFIX
INPUT_EXP: MOV AH, 1
INT 21H
CMP AL, 13 ;huiche
JE EXIT_INPUT
; call inputCheck ;is the character illegal?
MOV [BX], AL
INC BX ;infix as stack
JMP INPUT_EXP
EXIT_INPUT: MOV BYTE PTR [BX], '='
POP BX
POP AX
RET
INPUT ENDP
CALCULATE PROC NEAR ;计算中缀表达式函数
PUSH AX ; ax -- 计算结果累加器
PUSH CX ; ch -- 运算符栈顶元素, compute 函数的入口参数之一
PUSH DX ; cl -- 当前从中缀表达式中读入的元素
PUSH BX ; bx -- opStack 栈顶指针
PUSH DI ; di -- dataStack 栈顶指针
PUSH SI ; si -- 中缀表达式下标
MOV BX, -1
MOV SI, -1
MOV DI, -2
ANALYZE: INC SI ;读入待分析字符, 存入在CL寄存器中
MOV CL, BYTE PTR INFIX[SI]
CMP CL, '='
JE CASE_EXIT
CMP CL, '('
JE CASE_LEFT
CMP CL, ')'
JE CASE_RIGHT
CMP CL, '+'
JE CASE_ADD
CMP CL, '-'
JE CASE_SUB
JMP CASE_DATA
CASE_EXIT: JMP EXIT_CALCULATE
CASE_LEFT: JMP LEFT
CASE_RIGHT: JMP RIGHT
CASE_ADD: JMP ADDSUB
CASE_SUB: JMP ADDSUB
CASE_DATA: JMP READ_DATA
LEFT: INC BX
MOV BYTE PTR OPSTACK[BX], '('
MOV CHLAST, '('
JMP ANALYZE
RIGHT: MOV CL, BYTE PTR OPSTACK[BX]
DEC BX
CMP CL, '('
JE ANALYZE
MOV CH, CL
CALL COMPUTE
JMP RIGHT
ADDSUB: CMP CHLAST, -1
JZ PUSH_DATA_0
CMP CHLAST, '('
JZ PUSH_DATA_0
CMP CHLAST, '+'
JZ ERRTWOOPERATOR
CMP CHLAST, '-'
JZ ERRTWOOPERATOR
JMP PUSH_CL
PUSH_DATA_0: ADD DI, 2
MOV WORD PTR DATASTACK[DI], 0
PUSH_CL: CMP BX, -1 ; is opStack empty ?
JZ PUSH_CL_DIRECT
MOV CH, BYTE PTR OPSTACK[BX]
CMP CH, '(' ; the top of opStack is '(' ?
JZ PUSH_CL_DIRECT
MOV BYTE PTR OPSTACK[BX], CL
CALL COMPUTE
MOV CHLAST, CL
JMP ANALYZE
PUSH_CL_DIRECT: INC BX
MOV BYTE PTR OPSTACK[BX], CL
MOV CHLAST, CL
JMP ANALYZE
ERRTWOOPERATOR: LEA DX, ERRORTWOOPERATOR
MOV AH, 9
INT 21H
MOV AH, 4CH
INT 21H
MULDIV: CMP CHLAST, -1
JZ ERRFIRSTCHAR
CMP CHLAST, '+'
JZ ERRTWOOPERATOR
CMP CHLAST, '-'
JZ ERRTWOOPERATOR
CMP CHLAST, '('
JZ ERRFIRSTCHAR
JMP MULDIV_X
ERRFIRSTCHAR: LEA DX, ERRORFIRSTCHAR
MOV AH, 9
INT 21H
MOV AH, 4CH
INT 21H
MULDIV_X: CMP BX, -1 ; is stack empty ?
JE PUSH_MULDIV
MOV CH, BYTE PTR OPSTACK[BX] ;peek the element on the top
CMP CH, '*'
JE COMP_MULDIV
CMP CH, '/'
JE COMP_MULDIV
JMP PUSH_MULDIV ; the top is neither '*' nor '/', push cl directly
COMP_MULDIV: MOV BYTE PTR OPSTACK[BX], CL ; replace
CALL COMPUTE
MOV CHLAST, CL
JMP ANALYZE
PUSH_MULDIV: INC BX
MOV BYTE PTR OPSTACK[BX], CL
MOV CHLAST, CL
JMP ANALYZE
READ_DATA: XOR AX, AX
READ: ADD AX, AX ; use add, never use adc
MOV DX, AX
ADD AX, AX
ADD AX, AX
ADD AX, DX
AND CX, 0FH
ADD AX, CX
INC SI
MOV CL, BYTE PTR INFIX[SI]
CMP CL, '0'
JC FINISH_READ
CMP CL, 3AH
JNC FINISH_READ
JMP READ
FINISH_READ: ADD DI, 2
MOV WORD PTR DATASTACK[DI], AX
DEC SI
MOV CHLAST, '2'
JMP ANALYZE
PRE_EXIT_CALCULATE: MOV CH, BYTE PTR OPSTACK[BX]
DEC BX
CALL COMPUTE ; no jump, just fall down
EXIT_CALCULATE: CMP BX, -1 ; is operator stack empty ?
JNE PRE_EXIT_CALCULATE
POP SI
POP DI
POP BX
POP DX
POP CX
POP AX
RET
CALCULATE ENDP
COMPUTE PROC NEAR ;用来计算每一步结果,两个入参:ch-运算符,di-数据栈顶指针
PUSH AX
PUSH DX
CMP DI, 2
JC EXIT_COMPUTE
MOV DX, WORD PTR DATASTACK[DI] ; the second operator
SUB DI, 2
MOV AX, WORD PTR DATASTACK[DI] ; the first operator
SUB DI, 2
AND AX, AX ; set cf = 0
CMP CH, '+'
JE ADDF
CMP CH, '-'
JE SUBF
ADDF: ADC AX, DX
JMP FINISH_C
SUBF: SBB AX, DX
JMP FINISH_C
FINISH_C: ADD DI, 2
MOV WORD PTR DATASTACK[DI], AX
EXIT_COMPUTE: POP DX
POP AX
RET
COMPUTE ENDP
PRINT PROC NEAR ;输出结果函数
LEA DX,CRLF
MOV AH,9
INT 21H
PUSH AX
PUSH CX
PUSH DX
MOV CX, WORD PTR DATASTACK
TEST CX, 8000H ;是否为负数
JNZ NEGATIVE
BEGIN: CMP CX, 10000
JNC TEN_THOUSAND
CMP CX, 1000
JNC THOUSAND
CMP CX, 100
JNC HANDRED
CMP CX, 10
JNC TEN
JMP REMAINS
NEGATIVE: MOV DL, '-'
MOV AH, 2
INT 21H
NEG CX
JMP BEGIN
TEN_THOUSAND: MOV DL, -1
AA: SUB CX, 10000
INC DL
JNC AA
ADD CX, 10000
OR DL, 30H
MOV AH, 2
INT 21H
THOUSAND: MOV DL, -1
BB: SUB CX, 1000
INC DL
JNC BB
ADD CX, 1000
OR DL, 30H
MOV AH, 2
INT 21H
HANDRED: MOV DL, -1
CC: SUB CX, 100
INC DL
JNC CC
ADD CX, 100
OR DL, 30H
MOV AH, 2
INT 21H
TEN: MOV DL, -1
DDD: SUB CX, 10
INC DL
JNC DDD
ADD CX, 10
OR DL, 30H
MOV AH, 2
INT 21H
REMAINS: MOV DL, CL
OR DL, 30H
MOV AH, 2
INT 21H
EXIT_PRINT: POP DX
POP CX
POP AX
RET
PRINT ENDP
MAIN ENDP
CODE ENDS
END MAIN
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -