现有一组字符串为data,name,time,file,code,path,user,exit,quit,text,请编写程序从键盘输入4个字符的字符串,若存在将其删除, 并在显示器上显示。
编译环境:MASM 2012.5
整体思路:主要利用循环与字符串操作(movsb/cmpsb),若查找到字符串相同,标志位ZF=1,若查找到字符串不同,标志位ZF=0,跳转到字符串搬移程序段中将字符串搬到输出缓冲区,最后进行输出。
需要注意:
1.16位汇编语言资源有限,需要借助栈操作(PUSH/POP)保存循环中的计数器
2.字符串操作(movsb/cmpsb)也需要计数器CX声明比较和搬移次数,串操作时指针si会自动变化,cmpsb中一旦字符不同,比较立刻停止,而不是比较到CX声明的次数。
代码:
DATAS SEGMENT
buf db 5
db ?
db 5 dup(?)
output db 50 dup(?)
data_str db 'data';003C
name_str db 'name'
time_str db 'time'
file_str db 'file'
code_str db 'code'
path_str db 'path'
user_str db 'user'
exit_str db 'exit'
quit_str db 'quit'
text_str db 'text'
DATAS ENDS
STACKS SEGMENT
;此处输入堆栈段代码
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX
MOV ES,AX
lea dx,buf ;输入字符串
mov ah,0AH
int 21H
mov cx,10 ;计数器
mov ch,0
lea si,data_str ;bx取第一个单词首地址
lea ax,output ;ax取输出缓冲区output首地址
waixunhuan:
push cx ;循环CX入栈
mov cx,4 ;设置内循环CX
mov ch,0
mov dx,si ;用dx保存当次单词首地址
lea di,buf+2 ;di始终指向被查单词首地址
repz cmpsb ;长度为4进行串查找
jnz copy_letter ;不相等就将字符串搬到output中
pop cx ;循环CX出栈
cmp cx,1
jbe end_loop
loop waixunhuan
copy_letter:
mov si,dx ;由于执行cmpsb,si已不再指向单词首地址,用之前存的dx使si重新指向首地址
pop cx ;由于跳转,使第50行未执行,补上一遍
push cx ;存上外循环次数
mov cx,4
mov ch,0
mov di,ax
rep movsb ;字符串移动,si自动加4
add ax,4 ;只需要改output地址
pop cx ;即将loop,让cx出来
cmp cx,1
jbe end_loop
loop waixunhuan
end_loop:
mov al,'$'
lea si,output
cmp cx,1
je add2 ;如果cx=1,说明没有相同单词,所以output中存了10个单词(40个字母)
jne add1 ;如果cx>1,说明有相同单词,所以output中存了9个单词(36个字母)
add1:
add si,36
jmp end3
add2:
add si,40
jmp end3
end3:
mov [si],al ;将$存进单词末尾
lea si,output ;取output首地址
mov dx,si
mov ah,09H ;输出单词
int 21H
MOV AH,4CH
INT 21H
CODES ENDS
END START
运行结果:
输入第一个单词data:
输出:第一个单词data被删掉
输入中间一个单词code:
输出:中间一个单词code被删掉
输入最后一个单词text:
输出:最后一个单词text被删掉
输入非重复单词abcd:
输出:没有单词被删掉
目标达成