📄 32060624_王克_asmhomework_3.asm
字号:
;----------------------------------------------------------------
; ╭══════┤ 32060624___王克 ├═════╮
; ║ ║
; ║ ║
; ║ ★ 汇编语言 第三次作业 ★ ║
; ║ |---------------------------------------------| ║
; ║ ║
; ║ 2004.11.25 ║
; ║ ║
; ╰ ════════════════════════════╯
;汇编程序说明:
; 1.完全实现词典功能,可进行查找任意长度的单词,
; 2.从控制台输入一个单词,如果已存在此单词,则打印出相近的单词及位置
; 3.词典保存在文件中,为CET-4的词汇
; 4.对边界情况均做了处理,词典大小不大于64K。
; 5.程序用了大量的子程序,但结构还是很混乱。有待再思考。
; 2004.11.25
;━┅━┅━┅━┅━┅━┅━┅━┅━━┅━┅━┅━┅━┅━┅━┅━━┅━┅━━┅━
.MODEL SMALL
STACK SEGMENT STACK
BYTE 100 DUP(?)
STACK ENDS
DATA SEGMENT PARA ;用户交互信息
msg_input_word byte 0dh,0ah,'Please input the word you want to scan or insert(NOT NULL): ','$'
msg_open_error byte 0dh,0ah,'Sorry,Dict lost.',0dh,0ah,'$'
msg_read_error byte 0dh,0ah,'Sorry,read file error.',0dh,0ah,'$'
msg_find_word byte 2 dup(0dh,0ah),'I seek you in the Dic in line ','$'
msg_insert_ok byte 2 dup(0dh,0ah),'I insert you into the Dic in line: ','$'
msg_disp_word byte 3 dup(0dh,0ah),'OK! Show some near words to you:',0dh,0ah,'$'
msg_save_ok byte 2 dup(0dh,0ah),'OK! Save file success!',0dh,0ah,'$'
msg_Esc byte 2 dup(0dh,0ah),'Press ESC to quit. else to continue seek...',0dh,0ah,'$'
dict_file_name BYTE 'DICT.TXT',0
;数据
dict_file_handle WORD 0
dict_word_len word 0
word_max_len byte 64,0
insert_word BYTE 32 DUP(0),'$'
insert_word_len word 0
dict_data_len word 0
len_equal byte 0
line_num word 0
line_buffer byte 5 dup(?),'$'
dict_data_buffer BYTE 3000H DUP(0),'$'
buffer_len equ $-dict_data_buffer
DATA ENDS
CODE SEGMENT PARA
ASSUME CS:CODE,DS:DATA,SS:STACK
MAIN PROC FAR
MOV AX,DATA ;初始化DS,ES
MOV DS,AX
MOV ES,AX
EXIT_QUERY: ;判断用户是否要退出,不是则继续查询
LEA DX,MSG_ESC
MOV AH,09H
INT 21H
MOV AH,10H
INT 16H
CMP AH,01H
JNE CONTINUE
CALL RETURN ;是ESC则返回DOS
CONTINUE:
CALL GET_WORD ;从键盘读入要查找或插入的单词并处理,最长64位
CMP INSERT_WORD_LEN,0 ;判断输入是否为空
JE CONTINUE
CALL OPEN_FILE ;打开文件
CALL READ_FILE ;读入缓冲区
CALL CLOSE_FILE ;关闭文件
CALL SCAN_FILE ;开始查找单词,不存在则插入。并显示
CALL SAVE_FILE ;保存文件
MAINOK:
CALL RETURN ;返回DOS
MAIN ENDP
;*******************************************************
GET_WORD PROC NEAR ;从键盘读入要查找或插入的单词并处理,最长64位
MOV DX,OFFSET MSG_INPUT_WORD
MOV AH,09H
INT 21H
MOV AH,0AH
LEA DX,WORD_MAX_LEN
INT 21H
MOV AL,WORD_MAX_LEN+1 ;保存读入单词的长度
XOR AH,AH
MOV INSERT_WORD_LEN,AX
RET
GET_WORD ENDP
;********************************************************
OPEN_FILE PROC NEAR
MOV DX,OFFSET DICT_FILE_NAME ;打开所读文件
MOV AL,2H
MOV AH,3DH
INT 21H
JC OPEN_FILE_ERROR
MOV DICT_FILE_HANDLE,AX ;保存文件句柄
JMP OPENOK
OPEN_FILE_ERROR:
LEA DX,MSG_OPEN_ERROR ;打开文件错误处理
MOV AH,09H
INT 21H
CALL RETURN
OPENOK:
RET
OPEN_FILE ENDP
;*******************************************************
READ_FILE PROC NEAR
MOV BX,DICT_FILE_HANDLE
MOV CX,BUFFER_LEN ;最多读入的字节数
LEA DX,DICT_DATA_BUFFER
MOV AH,3FH
INT 21H
JC READ_FILE_ERROR
MOV DICT_DATA_LEN,AX ;保存实际读进的字节数
LEA DI,DICT_DATA_BUFFER
ADD DI,AX
MOV BX,0A0DH
MOV [DI],BX
JMP READOK
READ_FILE_ERROR:
LEA DX,MSG_READ_ERROR ;读取文件错误处理
MOV AH,09H
INT 21H
CALL RETURN
READOK:
RET
READ_FILE ENDP
;******************************************************
SCAN_FILE PROC NEAR ;在文件中查找此单词的位置,地址在DI中
LEA DI,DICT_DATA_BUFFER
NEXT:
MOV LEN_EQUAL,0
LEA SI,INSERT_WORD
CALL DICT_NEXT_WORD
CALL SET_SMALL_TO_CX ;用最小的长度作为计数器
PUSH DI
REPE CMPSB ;相等时继续比较
POP DI
JE FIND_WORD
JS TOINSERT_WORD
GOON:
ADD DI,DICT_WORD_LEN
INC DI
INC DI
JMP NEXT
FIND_WORD:
CMP LEN_EQUAL,0 ;长度相等才开能为同一单词
JE GOON
CALL FIND_WORD_DICT ;调用找到单词处理子程序
TOINSERT_WORD:
CALL INSERT_WORD_DICT ;调用插入单词处理子程序
RET
SCAN_FILE ENDP
;******************************************************
SET_SMALL_TO_CX PROC NEAR
MOV AX,DICT_WORD_LEN ;设置较短的到CX,作为比较次数
MOV BX,INSERT_WORD_LEN
CMP AX,BX
JE WORD_LEN_EQUAL
JB SHORTER
MOV CX,BX
JMP SETOK
WORD_LEN_EQUAL:
MOV LEN_EQUAL,1 ;保存两个单词长度是否相等
SHORTER:
MOV CX,AX
SETOK:
RET
SET_SMALL_TO_CX ENDP
;*************************;从词典中跳到下个单词并取得其长度******************************
DICT_NEXT_WORD PROC NEAR ;传过来DI的值
PUSH DI
INC LINE_NUM
;-----------
MOV BX,OFFSET DICT_DATA_BUFFER
ADD BX,DICT_DATA_LEN
CMP DI,BX
JAE REACH_END
;-------------
MOV AL,0AH
MOV BX,DI
MOV CX,64H
REPNZ SCASB ;查找到下个单词的开始
SUB DI,BX
SUB DI,2
MOV DICT_WORD_LEN,DI
;------------
JMP DICTOK
REACH_END:
;POP DI
MOV AX,0A0DH ;末端处理
MOV [DI-2],AX
LEA SI,INSERT_WORD
MOV CX,INSERT_WORD_LEN
REP MOVSB
POP DI
LEA DX,MSG_INSERT_OK
MOV AH,09H
INT 21H
MOV AX,LINE_NUM
CALL DEAL_NUM
;-------------------------
MOV AX,INSERT_WORD_LEN
ADD DICT_DATA_LEN,AX
ADD DICT_DATA_LEN,2
CALL SAVE_FILE ;将缓冲区的内容保存到文件中
CALL DISP_SOME_WORD
CALL MAIN
DICTOK:
;------------
POP DI
RET
DICT_NEXT_WORD ENDP
;************************插入此单词*****************
INSERT_WORD_DICT PROC NEAR
PUSH DI
;----------------------------
LEA SI,DICT_DATA_BUFFER
ADD SI,DICT_DATA_LEN
MOV CX,SI
SUB CX,DI
INC CX
MOV DI,SI
ADD DI,INSERT_WORD_LEN
ADD DI,2 ;0DH,0AH
STD
REP MOVSB
;-------------------------
POP DI
CLD
LEA SI,INSERT_WORD
MOV CX,INSERT_WORD_LEN
REP MOVSB
MOV AX,0A0DH
MOV [DI],AX
;-------------------------
SUB DI,INSERT_WORD_LEN
MOV BX,OFFSET DICT_DATA_BUFFER ;判断DI是否到了最左端
CMP DI,BX
JE INSERTOK
SUB DI,2
INSERTOK:
LEA DX,MSG_INSERT_OK
MOV AH,09H
INT 21H
MOV AX,LINE_NUM
CALL DEAL_NUM
;-------------------------
MOV AX,INSERT_WORD_LEN
ADD AX,2
ADD DICT_DATA_LEN,AX
CALL SAVE_FILE ;将缓冲区的内容保存到文件中
CALL DISP_SOME_WORD
CALL MAIN
RET
INSERT_WORD_DICT ENDP
;******************************************************
FIND_WORD_DICT PROC NEAR ;找到单词处理程序
LEA DX,MSG_FIND_WORD
MOV AH,09H
INT 21H
MOV AX,LINE_NUM
CALL DEAL_NUM
CALL DISP_SOME_WORD
CALL MAIN
RET
FIND_WORD_DICT ENDP
;******************************关闭文件****************
CLOSE_FILE PROC NEAR
MOV AH,3EH
MOV BX,DICT_FILE_HANDLE
INT 21H
RET
CLOSE_FILE ENDP
;******************************保存文件******************
SAVE_FILE PROC NEAR
CALL OPEN_FILE
MOV DX,OFFSET MSG_SAVE_OK
MOV AH,09H
INT 21H
MOV AH,40H
LEA DX,DICT_DATA_BUFFER
MOV CX,DICT_DATA_LEN
MOV BX,DICT_FILE_HANDLE
INT 21H
CALL CLOSE_FILE
RET
SAVE_FILE ENDP
;*******************************显示找到的单词位置之后的N个单词****************
DISP_SOME_WORD PROC NEAR
LEA DX,MSG_DISP_WORD
MOV AH,09H
INT 21H
MOV CX,100H
NEXT:
MOV DL,[DI]
MOV AH,02H
INT 21H
INC DI
LOOP NEXT
DISPOK:
RET
DISP_SOME_WORD ENDP
;********************************将16进制转化为10进制并输出**********
DEAL_NUM PROC NEAR
PUSH DI
MOV CX,5
MOV BX,10
MOV DI,OFFSET LINE_BUFFER+4 ;从后往前保存
LP4: XOR DX,DX ;将DX清零
DIV BX
OR DL,30H ;也可用ADD DL,30H
MOV BYTE PTR [DI],DL ;将16进制的数转换到ASCII中对应的数,0的ASCII码为 30H (48D)
CMP AX,0
JZ PRINT ;当商为0时,直接去打印,可不打印高位的0.
DEC DI
LOOP LP4
PRINT:
MOV DX,DI ;从DI开始打印,因为RESULT不一定够5位
MOV AH,9
INT 21H ;调用DOS的21号中断的9号功能,将DB输出
POP DI
RET
DEAL_NUM ENDP
;***************************************返回DOS*********
RETURN PROC NEAR
MOV AX,4C00H
INT 21H
RET
RETURN ENDP
;********************************************************
CODE ENDS
END MAIN
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -