第三次作业
一、
[要求] 使用函数表 完成乘、除、十六进制转十进制、十进制转十六进制、二进制转十进制等5个函数
源程序如下:
STACK1 SEGMENT PARA STACK ;堆栈段定义
STACK_AREA DW 100H DUP(?)
STACK_BOTTOM EQU $-STACK_AREA
STACK1 ENDS
DATA1 SEGMENT ;数据段定义
FUNC DW 5 DUP(?)
HELP DB "1-MUL 2-DIV 3-HEX2DEC 4-DEC2HEX 5-BIN2DEC",0
MULTI_HEAD DB "MULTIPLY FUNCTION:",0
DIVI_HEAD DB "DIVIDE FUNCTION:",0
H2D_HEAD DB "HEX TO DEC FUNCTION:",0
D2H_HEAD DB "DEC TO HEX FUNCTION:",0
B2D_HEAD DB "BIN TO DEC FUNCTION:",0
SPACE DB ' '
DATA1 ENDS
CODE1 SEGMENT
MAIN PROC FAR
ASSUME CS:CODE1,SS:STACK1,DS:DATA1
MOV AX,STACK1 ; 初始化堆栈寄存器
MOV SS,AX
MOV AX,STACK_BOTTOM
MOV SP,AX
MOV AX,DATA1
MOV DS,AX
MOV ES,AX
LEA SI,FUNC ; 初始化函数表
LEA AX,MULTI
MOV [SI],AX
LEA AX,DIVI
MOV [SI+2],AX
LEA AX,HEX2DEC
MOV [SI+4],AX
LEA AX,DEC2HEX
MOV [SI+6],AX
LEA AX,BIN2DEC
MOV [SI+8],AX
MAINLOOP:
LEA AX,HELP ; 使用键盘输入(0-5)控制循环,0代表推出
CALL DISP
CALL GETNUM
CMP AX,0
JZ EXIT
JB MAINLOOP
CMP AX,5
JA MAINLOOP
SUB AX,1
SHL AX,1
PUSH SI
ADD SI,AX
CALL [SI]
POP SI
LEA AX,SPACE
CALL DISP
JMP MAINLOOP
EXIT:
MOV AX,4C00H
INT 21H
MAIN ENDP
MULTI PROC NEAR
LEA AX,MULTI_HEAD
CALL DISP ; 显示头部文字
CALL GETNUM ; 获取第一个输入
PUSH AX ; 压栈
CALL GETNUM ; 获取第二个输入
POP BX ; 将第一个输入取出
XOR DX,DX ; 将DX清0
MUL BX ; 执行乘法
PUSH AX ; 显示结果
CALL DISPNUM
RET
MULTI ENDP
DIVI PROC NEAR
LEA AX,DIVI_HEAD ; 显示头部文字
CALL DISP
CALL GETNUM ; 获取被除数
PUSH AX ; 压栈
CALL GETNUM ; 获取除数
POP BX ; 弹出被除数
XCHG AX,BX ; 交换AX,BX
XOR DX,DX ; 将DX清0
DIV BX ; 执行除法
PUSH AX ; 显示商
CALL DISPNUM
PUSH DX
LEA AX,SPACE ; 打印空格
CALL DISP
CALL DISPNUM ; 显示余数
RET
DIVI ENDP
HEX2DEC PROC NEAR
LEA AX,H2D_HEAD
CALL DISP
CALL GETNUMHEX ; 获取16进制输入
PUSH AX
CALL DISPNUM ; 使用10进制数出
RET
HEX2DEC ENDP
DEC2HEX PROC NEAR
LEA AX,D2H_HEAD
CALL DISP
CALL GETNUM ; 获取10进制输入
PUSH AX
CALL DISPNUMHEX ; 使用16进制输出
RET
DEC2HEX ENDP
BIN2DEC PROC NEAR
LEA AX,B2D_HEAD
CALL DISP
CALL GETNUMBIN ; 获取2进制输入
PUSH AX
CALL DISPNUM ; 10进制输出
RET
BIN2DEC ENDP
GETNUM PROC NEAR
PUSH DX ; DX用于保存乘法高位
PUSH BX ; BX用于存中间结果
PUSH CX ; CX用于输入位数计数
MOV BX,0
MOV CX,5 ; 最多输入5位
MOV DX,0
GETNUM_LP:
MOV AH,1
INT 21H
XOR AH,AH
CMP AX,0DH ; 0dH 为回车 判断为回车即跳出
JZ GETNUM_EXIT
SUB AX,'0'
PUSH AX
MOV AX,BX ; 将中间结果x10 并累加
MOV BX,10
MUL BX
MOV BX,AX
POP AX
ADD BX,AX
LOOP GETNUM_LP
GETNUM_EXIT:
MOV AX,BX
POP CX
POP BX
POP DX
RET
GETNUM ENDP
GETNUMBIN PROC NEAR ; 二进制输入与十进制类似,CX置为16其余不需赘述
PUSH DX
PUSH BX
PUSH CX
MOV BX,0
MOV CX,16
MOV DX,0
GETNUMBIN_LP:
MOV AH,1
INT 21H
XOR AH,AH
CMP AX,0DH
JZ GETNUMBIN_EXIT
SUB AX,'0'
PUSH AX
MOV AX,BX
MOV BX,2
MUL BX
MOV BX,AX
POP AX
ADD BX,AX
LOOP GETNUMBIN_LP
GETNUMBIN_EXIT:
MOV AX,BX
POP CX
POP BX
POP DX
RET
GETNUMBIN ENDP
GETNUMHEX PROC NEAR ; 十六进制输入需要判断输入数位是数字还是字母 并且区别对待
PUSH DX ; 为了简化,这里仅处理了对大写字母的判断
PUSH BX
PUSH CX
MOV BX,0
MOV CX,5
MOV DX,0
GETNUMHEX_LP:
MOV AH,1
INT 21H
XOR AH,AH
CMP AX,0DH
JZ GETNUMHEX_EXIT
CMP AX,'9'
JA GETNUMHEX_HEX
SUB AX,'0'
JMP GETNUMHEX_LP_TAIL
GETNUMHEX_HEX:
SUB AX,'A'
ADD AX,10
GETNUMHEX_LP_TAIL:
PUSH AX
MOV AX,BX
MOV BX,10H
MUL BX
MOV BX,AX
POP AX
ADD BX,AX
LOOP GETNUMHEX_LP
GETNUMHEX_EXIT:
MOV AX,BX
POP CX
POP BX
POP DX
RET
GETNUMHEX ENDP
DISPNUM PROC NEAR ; 数字显示,使用除法并倒序显示余数即可
PUSH BP
MOV BP,SP
PUSH BX
PUSH CX
PUSH DX
MOV AX,[BP+4] ; AX存输入参数及中间结果
MOV CX,0 ; CX存的是数字位数
MOV BX,10 ; BX存的是进制数
DISPNUM_DIV:
XOR DX,DX ; 执行除法前先将DX清0
DIV BX
PUSH DX
INC CX
CMP AX,0 ; 如果商为0,代表得到了最后一位数,可以退出
JZ DISPNUM_DISPLAY
JMP DISPNUM_DIV
DISPNUM_DISPLAY: ; 取出余数并显示
MOV AH,2
POP DX
ADD DX,'0'
INT 21H
LOOP DISPNUM_DISPLAY
DISPNUM_EXIT:
POP DX
POP CX
POP BX
POP BP
RET 2 ; 由于使用了一个参数 所以RET 2
DISPNUM ENDP
DISPNUMHEX PROC NEAR ; 十六进制输出类似,只需要判断是数字还是字母,区分对待即可
PUSH BP
MOV BP,SP
PUSH BX
PUSH CX
PUSH DX
MOV AX,[BP+4]
MOV CX,0
MOV BX,10H
DISPNUMHEX_DIV:
XOR DX,DX
DIV BX
PUSH DX
INC CX
CMP AX,0
JZ DISPNUMHEX_DISPLAY
JMP DISPNUMHEX_DIV
DISPNUMHEX_DISPLAY:
MOV AH,2
POP DX
CMP DX,9 ; 比较数位与9,大于则进入字母处理,小于等于进入数字处理
JA DISPNUMHEX_HEX
ADD DX,'0'
JMP DISPNUMHEX_PRINT
DISPNUMHEX_HEX:
ADD DX,'A'
SUB DX,10
DISPNUMHEX_PRINT:
INT 21H
LOOP DISPNUMHEX_DISPLAY
DISPNUMHEX_EXIT:
POP DX
POP CX
POP BX
POP BP
RET 2
DISPNUMHEX ENDP
DISP PROC ; 字符串显示函数,用于显示以0结尾的字符串
PUSH AX
PUSH DX
PUSH SI
MOV SI,AX
MOV AH,2
XOR DX,DX
CLD
DISP_LP:
LODSB
CMP AL,0 ; 判断是否结束
JZ DISP_EXIT
MOV DL,AL
INT 21H
JMP DISP_LP
DISP_EXIT:
MOV DX,0AH ; 输出回车符
INT 21H
MOV DX,0DH
INT 21H
POP SI
POP DX
POP AX
RET
DISP ENDP
CODE1 ENDS
END MAIN
[运行截图]
二、
[要求] 使用函数表 完成字符串的大小写转换、增、删、查、替换、复制、比较
源程序如下:
STACK1 SEGMENT PARA STACK ; 定义栈
STACK_AREA DW 100H DUP(?)
STACK_BOTTOM EQU $ - STACK_AREA
STACK1 ENDS
DATA1 SEGMENT
STR1 DB "Tom and Marry dont go to school on Sunday",50 DUP(?),0 ;
STR2 DB 'Sunday',0
STR3 DB 'TOM',0
STR4 DB 'Jerry',0
STR5 DB 'on',0
STR6 DB '520 day',0
BUFFER DB 0,100 DUP(?)
BUFFER2 DB 0,100 DUP(?)
FUNC DW 5 DUP(?)
DATA1 ENDS
CODE1 SEGMENT
MAIN PROC FAR
ASSUME CS:CODE1,SS:STACK1,DS:DATA1
MOV AX,STACK1
MOV SS,AX
MOV AX,STACK_BOTTOM
MOV SP,AX
MOV AX,DATA1
MOV DS,AX
MOV ES,AX
LEA AX,STR1
PUSH AX
LEA AX,STR2
PUSH AX
LEA AX,STR6
PUSH AX
CALL REPLACE
LEA AX,STR1
CALL DISP
EXIT:
MOV AX,4C00H
INT 21H
MAIN ENDP
;BIJIAO PAIXU TIHUAN
STRCAT PROC
PUSH BP
MOV BP,SP
PUSH AX
PUSH SI
PUSH DI
MOV SI,[BP+4] ;mov dst string to SI
CLD
STRCAT_FINDEND:
LODSB
CMP AL,0
JZ STRCAT_CAT
JMP STRCAT_FINDEND
STRCAT_CAT:
MOV AX,[BP+6]
PUSH AX
DEC SI
PUSH SI
CALL STRCPY
POP DI
POP SI
POP AX
POP BP
RET 2
STRCAT ENDP
STRCAT2 PROC
PUSH SI
MOV SI,DI
STRCAT2_FIND:
LODSB
CMP AL,0
JZ STRCAT2_EXIT
JMP STRCAT2_FIND
STRCAT2_EXIT:
RET
STRCAT2 ENDP
STRCUT PROC
PUSH BP
MOV BP,SP
PUSH SI
PUSH DI
PUSH CX
MOV CX,[BP+4] ;new length
MOV SI,[BP+6] ;source string
REP LODSB
MOV [SI],CX ;set 0
POP CX
POP DI
POP SI
POP BP
RET 4
STRCUT ENDP
STRCPY PROC
PUSH BP
MOV BP,SP
PUSH AX
PUSH SI
PUSH DI
MOV DI,[BP+4]
MOV SI,[BP+6]
CLD
STRCPY_LP:
LODSB
STOSB
CMP AL,0
JZ STRCPY_END
JMP STRCPY_LP
STRCPY_END:
POP DI
POP SI
POP AX
POP BP
RET 4
STRCPY ENDP
STRCPY2 PROC
PUSH AX
STRCPY2_LP:
LODSB
CMP AL,0
JZ STRCPY2_EXIT
STOSB
JMP STRCPY2_LP
STRCPY2_EXIT:
POP AX
RET
STRCPY2 ENDP
STRCMP PROC
PUSH BP
MOV BP,SP
PUSH SI
PUSH DI
MOV SI,[BP+6]
MOV DI,[BP+4]
MOV AX,0
STRCMP_LP:
CLD
CMPSB
JZ STRCMP_EQ
JG STRCMP_GT
JL STRCMP_LS
STRCMP_EQ:
CMP [SI-1],AL
JNZ STRCMP_LP ;两字符相同而不为0 则继续比较
JMP STRCMP_EXIT ;为0 则结束 AX本身为0 不用再置于0
STRCMP_GT:
MOV AX,1 ;大于则置1 小于置-1
JMP STRCMP_EXIT
STRCMP_LS:
MOV AX,-1
JMP STRCMP_EXIT
STRCMP_EXIT:
POP DI
POP SI
POP BP
RET 4
STRCMP ENDP
UPPERCASE PROC
PUSH BP
MOV BP,SP
PUSH SI
PUSH AX
MOV SI,[BP+4]
UPPERCASE_LP:
LODSB
CMP AL,0
JZ UPPERCASE_EXIT
CMP AL,'a'
JAE UPPERCASE_a
JMP UPPERCASE_LP
UPPERCASE_a:
CMP AL,'z'
JBE UPPERCASE_z
JMP UPPERCASE_LP
UPPERCASE_z:
XOR AL,20H
MOV [SI-1],AL
JMP UPPERCASE_LP
UPPERCASE_EXIT:
POP AX
POP SI
POP BP
RET 4
UPPERCASE ENDP
REPLACE PROC
PUSH BP
MOV BP,SP
PUSH SI
PUSH DI
PUSH AX
PUSH BX
PUSH CX
MOV SI,[BP+8] ;src : string to be operated
LEA BX,BUFFER ;store buffer address
CLD
REPLACE_LP:
MOV DI,[BP+6] ;rep : string to be replaced
PUSH SI
PUSH DI
CALL FIND
CMP AX,-1
JNZ REPLACE_FOUND
JZ REPLACE_NOT_FOUND
REPLACE_FOUND:
MOV CX,AX ;copy src to buffer
SUB CX,SI
MOV DI,BX
REP MOVSB
PUSH SI ;copy dst to buffer
MOV SI,[BP+4]
CALL STRCPY2
POP SI
MOV BX,DI
MOV CX,-1
MOV DI,[BP+6] ;calculate length of rep
MOV AL,0
REPNE SCASB
NEG CX
SUB CX,2 ;CX=1+len(rep)+1
ADD SI,CX
JMP REPLACE_LP
REPLACE_NOT_FOUND:
MOV DI,BX ;copy left src to buff
CALL STRCPY2
LEA SI,BUFFER ;copy buffer to src
MOV DI,[BP+8]
CALL STRCPY2
POP CX
POP BX
POP AX
POP DI
POP SI
POP BP
RET 6
REPLACE ENDP
FIND PROC
PUSH BP
MOV BP,SP
PUSH SI
PUSH DI
PUSH CX
MOV SI,[BP+6] ;string to find in
MOV DI,[BP+4] ;string to match
MOV AX,0
MOV CX,0
CLD
FIND_LP:
CMP [DI],AL
JZ FIND_SUCCESS
CMP [SI],AL
JZ FIND_FAILED
CMPSB
JZ FIND_MATCH
JNZ FIND_NOTMATCH
FIND_MATCH:
INC CX
JMP FIND_LP
FIND_NOTMATCH:
MOV CX,0
MOV DI,[BP+4]
JMP FIND_LP
FIND_SUCCESS:
SUB SI,CX
MOV AX,SI
JMP FIND_EXIT
FIND_FAILED:
MOV AX,-1
JMP FIND_EXIT
FIND_EXIT:
POP CX
POP DI
POP SI
POP BP
RET 4
FIND ENDP
GETSTR PROC
PUSH AX
PUSH SI
MOV DI,AX
MOV AH,1
CLD
GETSTR_LP:
INT 21H
CMP AL,0DH
JZ GETSTR_EXIT
STOSB
JMP GETSTR_LP
GETSTR_EXIT:
MOV AL,0
STOSB
POP SI
POP AX
RET
GETSTR ENDP
DISP PROC ;
PUSH AX
PUSH DX
PUSH SI
MOV SI,AX
MOV AH,2
XOR DX,DX
CLD
DISP_LP:
LODSB
CMP AL,0
JZ DISP_EXIT
MOV DL,AL
INT 21H
JMP DISP_LP
DISP_EXIT:
MOV DX,0AH ;NEW LINE
INT 21H
MOV DX,0DH
INT 21H
POP SI
POP DX
POP AX
RET
DISP ENDP
CODE1 ENDS
END MAIN