汇编实现文本文件两行交换功能故障排查求助
汇编代码修复:文本文件任意行交换
问题根源
你的代码存在四个致命问题,导致交换逻辑完全失效:
- ReadLine未按行读取:原函数只是批量读取128字节,不识别换行符,行边界完全混乱
- WriteLine固定写入缓冲区:不管调用时传入的是哪个缓冲区,始终写入
buf的内容 - 行号解析计算错误:数字累加逻辑写错,解析出的行号与输入完全不符
- 交换逻辑仅支持相邻行:假设两行相邻,未处理任意行的定位与内容存储
修复后的完整代码
.model small .stack 100h .data handle dw ? handle2 dw ? filename db 26 db ? db 26 dup(0) outFile db "out.txt", 0 prompt1 db 13,10,"Provide filename and two line numbers, which will be swapped, E.g.: input.txt 2 3: $" line1 dw ? line2 dw ? tempLine1 db 128 dup(0) ; 存储line1的内容 tempLine2 db 128 dup(0) ; 存储line2的内容 len1 dw 0 ; line1的长度 len2 dw 0 ; line2的长度 buf db 128 dup(0) bufLen dw ? currentLine dw 1 .code main: mov ax, @data mov ds, ax ; 显示提示信息 lea dx, prompt1 mov ah, 9 int 21h ; 读取用户输入 mov ah, 0Ah lea dx, filename int 21h ; 给输入字符串末尾加0 mov si, offset filename + 1 mov cl, [si] mov ch, 0 inc cx add si, cx mov byte ptr [si], 0 ; 解析文件名和行号 lea si, filename + 2 call ParseInput jc failed ; --------------------------- ; 第一步:读取并保存line1和line2的内容 ; --------------------------- mov ah, 3Dh mov al, 0 lea dx, filename + 2 int 21h jc failed mov handle, ax mov currentLine, 1 read_lines: lea si, buf call ReadLine jc save_done cmp currentLine, line1 je save_line1 cmp currentLine, line2 je save_line2 jmp next_line save_line1: ; 复制buf到tempLine1 mov cx, bufLen lea di, tempLine1 lea si, buf rep movsb mov len1, cx jmp next_line save_line2: ; 复制buf到tempLine2 mov cx, bufLen lea di, tempLine2 lea si, buf rep movsb mov len2, cx jmp next_line next_line: inc currentLine jmp read_lines save_done: ; 关闭原文件 mov ah, 3Eh mov bx, handle int 21h ; --------------------------- ; 第二步:重新读取原文件,写入交换后的内容到out.txt ; --------------------------- ; 重新打开原文件 mov ah, 3Dh mov al, 0 lea dx, filename + 2 int 21h jc failed mov handle, ax ; 创建输出文件 mov ah, 3Ch xor cx, cx lea dx, outFile int 21h jc failed mov handle2, ax mov currentLine, 1 write_lines: lea si, buf call ReadLine jc write_done cmp currentLine, line1 je write_line2_content cmp currentLine, line2 je write_line1_content ; 正常写入当前行 lea si, buf mov cx, bufLen call WriteLine jmp next_write_line write_line2_content: ; 写入line2的内容 lea si, tempLine2 mov cx, len2 call WriteLine jmp next_write_line write_line1_content: ; 写入line1的内容 lea si, tempLine1 mov cx, len1 call WriteLine jmp next_write_line next_write_line: inc currentLine jmp write_lines write_done: ; 关闭文件 mov ah, 3Eh mov bx, handle int 21h mov ah, 3Eh mov bx, handle2 int 21h failed: mov ah, 4Ch int 21h ; --------------------------- ; ReadLine:按行读取,直到遇到换行符0Ah ; 输入:si = 缓冲区地址 ; 输出:bufLen = 行长度(包含0Dh+0Ah),CF=1表示EOF ; --------------------------- ReadLine proc xor cx, cx read_char: mov ah, 3Fh mov bx, handle lea dx, [si+cx] mov cx, 1 int 21h jc @exit cmp ax, 0 je @exit inc cx cmp byte ptr [si+cx-1], 0Ah ; 检查是否是换行符 jne read_char mov bufLen, cx clc ret @exit: stc ret ReadLine endp ; --------------------------- ; WriteLine:写入指定缓冲区的内容 ; 输入:si = 缓冲区地址,cx = 内容长度 ; --------------------------- WriteLine proc mov ah, 40h mov bx, handle2 mov dx, si int 21h ret WriteLine endp ; --------------------------- ; ParseInput:解析文件名后的两个行号 ; 输入:si = 输入字符串起始地址(文件名之后) ; 输出:line1, line2被赋值,CF=1表示解析失败 ; --------------------------- ParseInput proc ; 跳过文件名后的空格 skip_spaces1: lodsb cmp al, ' ' je skip_spaces1 dec si ; 解析line1 xor cx, cx parse_line1: lodsb cmp al, ' ' je store_line1 cmp al, 0 je parse_error sub al, '0' mov bx, cx mov ax, 10 mul bx mov cx, ax add cx, al jmp parse_line1 store_line1: mov line1, cx xor cx, cx ; 跳过line1后的空格 skip_spaces2: lodsb cmp al, ' ' je skip_spaces2 dec si ; 解析line2 parse_line2: lodsb cmp al, 0 je store_line2 sub al, '0' mov bx, cx mov ax, 10 mul bx mov cx, ax add cx, al jmp parse_line2 store_line2: mov line2, cx ; 确保line1 <= line2,方便处理 mov ax, line1 cmp ax, line2 jle @exit xchg ax, line2 mov line1, ax clc ret parse_error: stc ret @exit: ret ParseInput endp end main
关键修复说明
- ReadLine重构:改为逐字节读取,直到遇到
0Ah(换行符),确保每次读取完整一行,包含0Dh+0Ah的换行标记。 - WriteLine修复:使用传入的
si指向缓冲区,cx传递长度,不再固定写入buf。 - ParseInput修复:修正数字计算逻辑(
add cx, al替代错误的add cx, ax),同时跳过空格,确保正确解析两个行号,还自动将line1设为较小值,简化后续逻辑。 - 交换逻辑重构:分为两步,先读取并保存目标两行的内容,再重新遍历文件,遇到目标行时交换写入内容,支持任意行号的交换,无论是否相邻。
内容的提问来源于stack exchange,提问作者dodanija
相关产品推荐
相关产品推荐

