汇编实现文本文件字符串替换:TextManipulations段功能异常排查
汇编字符串替换程序:TextManipulations段修正方案
问题背景
编写汇编程序实现从指定文本文件中搜索目标字符串并替换为指定字符串,输出替换后的文件。现有程序的参数解析、文件打开/创建等前序功能正常,但TextManipulations子程序存在逻辑错误,导致要么替换成功但丢失部分字符,要么功能完全失效。
原程序代码
.MODEL small .STACK 256 .DATA help db "Hello,", 10, 13, "provide arguments like in the example: program.exe data.txt abcd EFG res.txt", 10, 13, "$" FileProblem db "Provided file wasn't found.", 10, 13, "Provide arguments like in the example: program.exe data.txt abcd EFG res.txt", 10, 13, "$" input db 255 dup(0) inputFD dw, ? string1 db 255 dup(0) string2 db 255 dup(0) output db 255 dup(0) outputFD dw, ? buffer db 50000 dup(?) tempBuf db 255 dup(?) .CODE Start: mov ax, @data mov ds, ax xor cx, cx xor ah, ah mov cl, [es:0080h] cmp cx, 4 jbe Helpmsg jne SkipHelp SkipHelp: xor di, di mov bx, 82h mov si, offset input call SaveArgument mov si, offset string1 call SaveArgument mov si, offset string2 call SaveArgument mov si, offset output call SaveArgument xor ax, ax mov ah, 3Dh mov al, 00 mov dx, offset input int 21h jc MissingFile mov inputFD, ax mov ah, 3Fh mov bx, inputFD mov cx, 200 mov dx, offset buffer int 21h mov ah, 3Ch mov cx, 0 mov dx, offset output int 21h mov outputFD, ax call TextManipulations mov ah, 3Eh mov bx, outputFD int 21h Final: mov ah, 4Ch int 21h Helpmsg: mov ah, 09h mov dx, offset help int 21h JMP Final MissingFile: mov ah, 09h mov dx, offset FileProblem int 21h jmp Final SaveArgument PROC Begin: mov dx, [es:bx] inc bx cmp dl, 20h je StopSpace cmp dl, 13 je StopEnter mov byte ptr [si], dl inc si jmp Begin StopSpace: inc di ret StopEnter: cmp di, 3 jb Helpme ret Helpme: mov ah, 09h mov dx, offset help int 21h mov ah, 4Ch int 21h ret SaveArgument ENDP TextManipulations PROC mov si, offset buffer mov di, offset string1 xor cx, cx push cx Read: mov ah, 3Fh mov bx, inputFD mov cx, 1 mov dx, si int 21h cmp byte ptr [si], 0 je Return mov al, byte ptr [si] mov ah, byte ptr [di] cmp al, ah je CheckForString mov al, 0 mov ah, 40h mov bx, outputFD mov dx, offset tempBuf mov cx, 1 int 21h mov cx, 1 mov dx, si int 21h inc si mov di, offset string1 pop cx xor cx, cx push cx jmp Read CheckForString: pop cx inc cx inc di cmp byte ptr [di], 0 je PrintString push di mov di, offset tempBuf mov byte ptr [di], al pop di inc si push cx jmp Read PrintString: pop cx mov ah, 40h mov bx, outputFD mov cx, 1 mov dx, offset string2 int 21h inc si xor cx, cx push cx jmp Read Return: ret TextManipulations ENDP END Start
原TextManipulations段的核心问题
- 重复读取文件:主程序已经通过
int 21h 3Fh读取了200字节到buffer,但子程序内再次调用3Fh读取,导致文件指针跳转,丢失已读入buffer的数据。 - 匹配失败时的临时字符未处理:匹配过程中暂存到
tempBuf的字符未在匹配失败时输出,直接丢弃,导致丢失字符。 - 替换字符串输出不完整:
PrintString中仅输出string2的1个字符,而非整个替换字符串。 - 文件结束判断错误:用
[si] == 0判断文件结束,但文本文件可能包含空字节,正确的方式是检查int 21h 3Fh的返回值ax是否为0。 - 匹配状态重置不完整:匹配失败后,未清空
tempBuf中暂存的部分匹配字符,影响后续逻辑。
修正后的TextManipulations段
TextManipulations PROC ; 初始化:si指向buffer起始,bp记录已匹配的字符数,di指向tempBuf暂存区 mov si, offset buffer mov bp, 0 mov di, offset tempBuf MatchLoop: ; 检查buffer是否读完,若读完则尝试读下一批数据 cmp si, offset buffer + 200 je RefillBuffer mov al, [si] mov ah, [string1 + bp] cmp ah, 0 ; 判断是否已匹配完整个目标字符串 je ReplaceString cmp al, ah je MatchContinue ; 当前字符匹配,继续匹配下一个 ; 匹配失败:输出暂存的字符,再输出当前字符,重置匹配状态 mov cx, bp jcxz SkipTempOutput ; 无暂存字符则跳过 mov ah, 40h mov bx, outputFD mov dx, offset tempBuf int 21h SkipTempOutput: mov ah, 40h mov bx, outputFD mov dx, si mov cx, 1 int 21h mov bp, 0 ; 重置匹配计数器 mov di, offset tempBuf ; 重置暂存区指针 inc si jmp MatchLoop MatchContinue: ; 暂存当前匹配的字符,更新匹配计数器和指针 mov [di], al inc di inc bp inc si jmp MatchLoop ReplaceString: ; 输出替换字符串 mov cx, 0 mov di, offset string2 CountReplaceLen: inc cx cmp [di], 0 je DoReplace inc di jmp CountReplaceLen DoReplace: mov ah, 40h mov bx, outputFD mov dx, offset string2 int 21h mov bp, 0 ; 重置匹配计数器 mov di, offset tempBuf ; 重置暂存区指针 inc si jmp MatchLoop RefillBuffer: ; 读取下一批数据到buffer mov ah, 3Fh mov bx, inputFD mov cx, 200 mov dx, offset buffer int 21h jcxz EndProcessing ; ax=0表示文件结束 mov si, offset buffer ; 重置si到buffer起始 jmp MatchLoop EndProcessing: ; 输出剩余的暂存字符 mov cx, bp jcxz Return mov ah, 40h mov bx, outputFD mov dx, offset tempBuf int 21h Return: ret TextManipulations ENDP
修正说明
- 移除重复读取:仅在
buffer数据读完时才调用3Fh读取下一批,避免文件指针混乱。 - 完善匹配逻辑:用
bp记录已匹配的字符数,tempBuf暂存匹配过程中的字符,匹配失败时先输出暂存字符再输出当前字符,避免丢数据。 - 完整输出替换字符串:先计算
string2的长度,再一次性输出整个替换字符串。 - 正确判断文件结束:通过
int 21h 3Fh的返回值ax判断是否读取到文件末尾。 - 重置匹配状态:每次匹配成功或失败后,重置匹配计数器和暂存区指针,确保后续匹配不受影响。
内容的提问来源于stack exchange,提问作者Leonardas SInkevicius
相关产品推荐
相关产品推荐

