You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

汇编实现文本文件两行交换功能故障排查求助

汇编代码修复:文本文件任意行交换

问题根源

你的代码存在四个致命问题,导致交换逻辑完全失效:

  • 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

关键修复说明

  1. ReadLine重构:改为逐字节读取,直到遇到0Ah(换行符),确保每次读取完整一行,包含0Dh+0Ah的换行标记。
  2. WriteLine修复:使用传入的si指向缓冲区,cx传递长度,不再固定写入buf。
  3. ParseInput修复:修正数字计算逻辑(add cx, al替代错误的add cx, ax),同时跳过空格,确保正确解析两个行号,还自动将line1设为较小值,简化后续逻辑。
  4. 交换逻辑重构:分为两步,先读取并保存目标两行的内容,再重新遍历文件,遇到目标行时交换写入内容,支持任意行号的交换,无论是否相邻。

内容的提问来源于stack exchange,提问作者dodanija

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 21:54:53