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

Emu8086汇编修改文件内容并保存新文件报错问题排查

问题:DOS中断21h 3Ch功能创建文件时总是触发错误处理(路径已确认无误)

需求:实现将文件中用户从键盘输入的指定字符替换为本人名字,并保存为新文件。

问题现象:代码中write_to_new_file段调用DOS中断21h的3Ch功能创建新文件时,总是跳转至file_error错误处理分支,且已确认目标文件路径c:\emu8086\vdrive\C\created_folder\file_corrected.txt是正确的。

相关代码片段

write_to_new_file:
    mov ah, 3Ch
    lea dx, new_file
    mov al, 0
    int 21h
    jc file_error
    mov bx, ax

完整代码

org 100h

jmp start

; File paths
file1 db "c:\emu8086\vdrive\C\file1.txt", 0 ; and files 2 and 3 almost same paths
new_file db "c:\emu8086\vdrive\C\created_folder\file_corrected.txt", 0
handle dw ?

...

; General messages
...

; Replace functionality messages
...
start:
mov ax, cs
;mov dx, ax
mov es, ax
...
;********** REPLACEMENT ********************* 
    ; Create new file
    lea dx, new_file
    mov ah, 3Ch ; Create file function
    mov cx, 0   ; Normal attributes
    int 21h
    mov bx, ax ; Save handle of new file in BX
    
choose_file_for_replacement:
mov dx, offset replace_message ; Load address of footer
mov ah, 09h          ; DOS service to display string
int 21h              ; Call DOS interrupt

; Wait for user input
mov ah, 01h          ; DOS service to read character
int 21h              ; Call DOS interrupt
 
; Compare input directly with ASCII values for '1', '2', '3'
cmp al, '1'          ; Compare with '1'
je replace_file1
cmp al, '2'          ; Compare with '2'
je replace_file2
cmp al, '3'          ; Compare with '3'      
je replace_file3

replace_file1:
; Initialize data segment
    mov ax, @data
    mov ds, ax

    ; Open the file
    mov ah, 3Dh                ; Open file function
    mov al, 0                  ; Open for reading
    lea dx, file1              ; Load address of file name
    int 21h
    jc file_error              ; If error, jump to error handling
    mov bx, ax                 ; Store file handle in BX
    jmp read_into_buffer
    
replace_file2:
...
replace_file3:
...

read_into_buffer:
    mov ah, 3Fh                ; Read file function
    lea dx, buf                ; Load address of buffer
    mov cx, 255                ; Number of bytes to read
    int 21h
    jc file_error              ; If error, jump to error handling
    mov si, offset buf         ; SI points to the buffer

    ; Prompt user to enter the character to replace
    mov ah, 02h          ; DOS service to write character
    mov dx, offset prompt
    mov ah, 9
    int 21h

    ; Read the character from the user
    mov ah, 01h
    int 21h
    mov bl, al ; Store user input in BL
    mov ah, 02h          ; DOS service to write character

    ; Process the buffer
process_message:
    mov al, [si]
    cmp al, 0
    je write_to_new_file
    cmp al, bl
    jne skip_replacement

    ; Replace character with name
    mov di, offset replacement
output_replacement:
    mov al, [di]
    cmp al, 0
    je continue_processing
    mov dl, al
    mov ah, 2
    int 21h
    inc di
    jmp output_replacement

skip_replacement:
    mov dl, al
    mov ah, 2
    int 21h

continue_processing:
    inc si
    jmp process_message

write_to_new_file:
    mov ah, 3Ch
    lea dx, new_file
    mov al, 0
    int 21h
    jc file_error
    mov bx, ax

    ; Calculate the length of the modified buffer
    mov cx, si ; SI points to the end of the modified part

    ; Write the modified content to the new file
    mov ah, 40h
    lea dx, buf
    int 21h
    jc file_error

    ; Close the new file
    mov ah, 3Eh
    int 21h

    ; Display success message
    lea dx, success_message
    mov ah, 9
    int 21h
    jmp end_program

file_error:
    ; Display error message
    lea dx, message_error
    mov ah, 9
    int 21h
    jmp end_program
...

问题分析

  1. DS寄存器指向错误:在replace_file1中执行了mov ax, @data和mov ds, ax,但new_file定义在CS段(COM程序默认代码、数据同属CS段),此时DS指向@data段,导致lea dx, new_file加载的路径地址错误,DOS无法定位正确路径。
  2. 3Ch功能参数问题:
    • 未显式设置cx寄存器(文件属性),虽默认可为0,但显式设置更规范;
    • al=0表示仅创建新文件,若目标文件已存在则创建失败,触发CF标志跳转至错误处理。
  3. 重复创建文件:start段提前调用3Ch创建new_file,后续write_to_new_file再次调用时,若文件已存在且al=0,必然触发错误。
  4. 缓冲区处理逻辑错误:当前代码仅将替换内容输出到屏幕,未修改buf数据,导致写入新文件的仍是原始内容;同时缓冲区长度计算mov cx, si错误,正确长度应为si - offset buf。

解决方案

1. 修正DS寄存器指向

在write_to_new_file开头将DS重置为CS,确保正确访问CS段中的new_file路径:

write_to_new_file:
    mov ax, cs
    mov ds, ax          ; 让DS指向CS,正确读取new_file路径
    mov ah, 3Ch
    lea dx, new_file
    mov cx, 0           ; 显式设置文件属性为普通
    mov al, 1           ; al=1表示文件存在则截断(覆盖),避免已存在时出错
    int 21h
    jc file_error
    mov bx, ax

2. 移除重复的文件创建代码

删除start段中提前创建new_file的代码,避免重复创建导致的错误:

;********** REPLACEMENT ********************* 
    ; 以下代码删除
    ; Create new file
    ; lea dx, new_file
    ; mov ah, 3Ch ; Create file function
    ; mov cx, 0   ; Normal attributes
    ; int 21h
    ; mov bx, ax ; Save handle of new file in BX

3. 修正缓冲区长度计算

将错误的长度计算改为实际处理的字节数:

; Calculate the length of the modified buffer
mov cx, si
sub cx, offset buf  ; 得到缓冲区中实际处理的字节数

4. 修正缓冲区修改逻辑

修改process_message段,将替换后的名字写入缓冲区,而不是仅输出到屏幕:

; Process the buffer
process_message:
    mov al, [si]
    cmp al, 0
    je write_to_new_file
    cmp al, bl
    jne skip_replacement

    ; Replace character with name: 将名字写入缓冲区
    mov di, offset replacement
output_replacement:
    mov al, [di]
    cmp al, 0
    je continue_processing
    mov [si], al  ; 把名字字符写入缓冲区当前位置
    inc si
    inc di
    jmp output_replacement

skip_replacement:
    ; 字符不替换,直接移动到下一个位置
    inc si
    jmp process_message

注意:需确保buf的大小足够容纳替换后的内容(单个字符替换为多字符名字会增加总长度),可适当增大缓冲区定义(如改为buf db 512 dup(0))。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 01:58:11