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

Assembly x86 TASM任务管理程序:任务删除功能实现故障排查

TASM x86汇编任务管理程序删除功能异常问题

我用TASM开发x86汇编的任务管理程序,已经实现了任务添加和查看功能,但在做指定任务删除功能时出了问题。写了delete_task子程序,想通过处理换行符(13、10)和终止符$完成文件读写,结果执行删除后文件内容重复还带乱码。比如原来的任务列表是task1到task5,删除操作后内容变成原列表重复,还加了一堆乱码字符。


原程序代码

.model small
.stack 100h
.data
sir db 80 dup('$') 
m2 db 'Introduceti sirul:$'
m4 db '1. Add task', 13, 10, '$'
m5 db '2. View tasks', 13, 10, '$'
filename db 'tasks.txt',0
handle dw ?
strLength dw ?
t_handle dw ?
newline db 13, 10, '$' ; 换行符
menuChoice db ?
buffer db 2000 dup(0)
.code
    mov ax,@data
    mov ds,ax
    
    mov ah, 9h
    mov dx, offset m4
    int 21h
    
    mov ah, 9h
    mov dx, offset m5
    int 21h
    
    mov ah, 1h
    int 21h
    mov menuChoice, al
    
    cmp menuChoice, '1'
    je add_task
    cmp menuChoice, '2'
    je view_tasks
    cmp menuChoice, '3'
    je delete_aux
    
    jmp end_program

view_tasks:
    ; 打开文件只读
    mov ah, 3Dh 
    mov al, 0 
    mov dx, offset filename 
    int 21h 
    mov handle, ax 

    ; 读取文件内容(仅读80字节)
    mov ah, 3Fh 
    mov bx, handle 
    mov dx, offset sir 
    mov cx, 80 
    int 21h 

    ; 逐字符显示内容
    mov si, offset sir

    display_loop:
        cmp byte ptr [si], '$'
        je end_display
        mov ah, 02h 
        mov dl, [si] 
        int 21h 
        inc si
        jmp display_loop

    end_display:
    ; 关闭文件
    mov ah, 3Eh 
    mov bx, handle 
    int 21h 

    jmp end_program

delete_aux:
    cmp menuChoice, '3' 
    jne view_tasks 
    jmp delete_task 

add_task:
    ; 清空缓冲区
    mov ah, 0Ah
    mov dx, offset sir
    int 21h

    ; 提示输入任务
    mov ah, 9h
    mov dx, offset m2
    int 21h
    
    mov bx,0 
    mov cx,80 
    mov ah,3fh
    mov dx,offset sir
    int 21h

    mov ah, 9h
    mov dx, offset sir
    int 21h

    ; 计算输入字符串长度
    mov si, offset sir
    add si, 2
    mov cx, 0 
    count_length:
        cmp byte ptr [si], '$' 
        je end_count
        inc cx 
        inc si
        jmp count_length 
    
    end_count:
    mov strLength, cx 

    ; 打开文件追加模式
    mov ah, 3Dh 
    mov al, 2 
    mov dx, offset filename
    int 21h 
    mov handle, ax 

    ; 定位到文件末尾
    mov ah, 42h 
    mov al, 2 
    mov bx, handle 
    mov cx, 0 
    mov dx, 0 
    int 21h 

    ; 写入任务内容
    mov ah, 40h
    mov bx, handle 
    mov dx, offset sir 
    mov cx, strLength
    int 21h

; 写入换行符
    mov ah, 40h 
    mov bx, handle
    mov dx, offset newline 
    mov cx, 2
    int 21h

    ; 关闭文件
    mov ah, 3Eh 
    mov bx, handle
    int 21h
   
    jmp view_tasks

delete_task:
    
    jmp view_tasks ; 删除后跳转到查看任务


end_program:
    mov ah,4Ch
    int 21h
end

尝试实现的delete_task子程序

delete_task:
    ; 提示输入要删除的任务编号
    mov ah, 9h
    mov dx, offset m_delete_prompt
    int 21h

    ; 读取用户输入的任务编号(转成数字)
    mov ah, 1h
    int 21h
    sub al, '0' 
    mov bl, al

    ; 打开文件读写模式
    mov ah, 3Dh 
    mov al, 2 
    mov dx, offset filename 
    int 21h
    mov handle, ax 

    ; 读取文件到缓冲区
    mov ah, 3Fh 
    mov bx, handle 
    mov dx, offset buffer 
    mov cx, 2000 
    int 21h

    mov si, offset buffer
    mov di, si

    delete_loop:
        cmp byte ptr [si], '$' 
        je end_delete
        mov al, [si]
        cmp al, 13 
        je check_next_char
        mov [di], al 
        inc di
        inc si
        jmp delete_loop

    check_next_char:
        inc si ; 移动到下一个字符(LF)
        mov al, [si]
        cmp al, 10
        je delete_task_found
        mov byte ptr [di], 13 
        inc di
        mov [di], al
        inc di 
        inc si
        jmp delete_loop

    delete_task_found:
        ; 判断是否是要删除的任务
        sub al, '0' 
        cmp al, bl  
        je skip_task   
        jmp copy_task

    skip_task:
        ; 跳过要删除的任务
        mov al, [si]
        cmp al, 13  
        jne skip_task 
        jmp delete_loop

    copy_task:
        ; 保留当前任务内容
        mov [di], al
        inc di 
        inc si 
        jmp delete_loop

    end_delete:
        ; 尝试截断文件
        mov ah, 40h
        mov bx, handle
        mov dx, offset buffer
        sub di, offset buffer
        int 21h

        ; 关闭文件
        mov ah, 3Eh 
        mov bx, handle
        int 21h

    jmp view_tasks

; 数据段新增提示语
m_delete_prompt db 'Enter the task number to delete: $'

原有任务列表

task1
task2
task3
task4
task5

执行删除后的异常输出

task1
task2
task3
task4
task5
task1Útask2Útask3Útask4Útask5Ú                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ÿÿùtâ

问题原因及修复方案

核心问题分析

  1. 文件截断逻辑错误:用ah=40h(写文件)无法截断文件,该功能仅能写入数据,截断需要先移动文件指针,再调用ah=4Ah(设置文件大小)。
  2. 任务编号判断逻辑错误:文件中仅存储任务内容和换行符,没有任务编号,你错误地将换行符LF(10)转成数字与用户输入对比,完全不匹配。
  3. 循环终止条件错误:文件内容没有$终止符,用cmp byte ptr [si], '$'判断结束会读取缓冲区垃圾数据,导致乱码。
  4. 跳过任务逻辑漏洞:skip_task仅跳过到下一个CR(13),未处理后续LF(10),且无边界判断,可能陷入死循环。

修复后的delete_task子程序

delete_task:
    ; 提示输入要删除的任务序号
    mov ah, 9h
    mov dx, offset m_delete_prompt
    int 21h

    ; 读取用户输入的任务序号(转成数字)
    mov ah, 1h
    int 21h
    sub al, '0'
    mov bl, al          ; bl = 要删除的任务序号
    mov bh, 1           ; bh = 当前任务序号计数器,从1开始

    ; 打开文件读写模式
    mov ah, 3Dh
    mov al, 2
    mov dx, offset filename
    int 21h
    mov handle, ax

    ; 读取整个文件到buffer,记录实际读取字节数
    mov ah, 3Fh
    mov bx, handle
    mov dx, offset buffer
    mov cx, 2000
    int 21h
    mov cx, ax          ; cx = 实际读取字节数,作为循环上限

    mov si, offset buffer
    mov di, si

delete_loop:
    cmp cx, 0
    je end_delete       ; 读完所有字节,退出循环

    mov al, [si]
    cmp al, 13
    je check_lf

    ; 判断是否是要删除的任务内容
    cmp bh, bl
    je skip_char        ; 是要删除的任务,跳过该字符
    mov [di], al        ; 不是,复制到目标位置
    inc di
skip_char:
    inc si
    dec cx
    jmp delete_loop

check_lf:
    ; 处理CR后面的LF
    inc si
    dec cx
    cmp cx, 0
    je end_delete

    mov al, [si]
    cmp al, 10
    jne not_lf

    ; 遇到完整的CR+LF,任务序号加1
    cmp bh, bl
    jne keep_newline    ; 不是要删除的任务,保留换行符
    ; 是要删除的任务,跳过LF
    inc si
    dec cx
    inc bh
    jmp delete_loop

keep_newline:
    ; 保留CR和LF
    mov [di], 13
    inc di
    mov [di], 10
    inc di
    inc si
    dec cx
    inc bh
    jmp delete_loop

not_lf:
    ; 不是LF,把CR和当前字符复制回去
    cmp bh, bl
    je skip_cr_char
    mov [di], 13
    inc di
    mov [di], al
    inc di
skip_cr_char:
    inc si
    dec cx
    jmp delete_loop

end_delete:
    ; 将文件指针移到开头
    mov ah, 42h
    mov al, 0
    mov bx, handle
    mov cx, 0
    mov dx, 0
    int 21h

    ; 写入处理后的内容
    mov ah, 40h
    mov bx, handle
    mov dx, offset buffer
    mov cx, di
    sub cx, offset buffer ; cx = 要写入的字节数
    int 21h

    ; 截断文件到写入后的大小
    mov ah, 4Ah
    mov bx, handle
    mov cx, 0
    mov dx, di
    sub dx, offset buffer ; dx = 文件新大小
    int 21h

    ; 关闭文件
    mov ah, 3Eh
    mov bx, handle
    int 21h

    jmp view_tasks

; 数据段新增提示语
m_delete_prompt db '请输入要删除的任务序号: $'

额外修复:view_tasks模块读取限制

原代码仅读取80字节,会导致长内容显示不全,修改为读取整个文件并自动添加任务编号:

view_tasks:
    ; 打开文件只读
    mov ah, 3Dh
    mov al, 0
    mov dx, offset filename
    int 21h
    mov handle, ax

    ; 读取整个文件到buffer
    mov ah, 3Fh
    mov bx, handle
    mov dx, offset buffer
    mov cx, 2000
    int 21h
    mov cx, ax          ; cx = 读取的字节数

    ; 显示内容并自动添加任务编号
    mov si, offset buffer
    mov dl, '1'         ; 初始任务编号
    mov ah, 02h
    int 21h
    mov dl, '.'
    int 21h
    mov dl, ' '
    int 21h

display_loop:
    cmp cx, 0
    je end_display

    mov al, [si]
    cmp al, 13
    je display_cr

    ; 显示当前字符
    mov dl, al
    mov ah, 02h
    int 21h
    inc si
    dec cx
    jmp display_loop

display_cr:
    ; 显示换行符
    mov dl, 13
    int 21h
    mov dl, 10
    int 21h
    inc si
    dec cx
    cmp cx, 0
    je end_display

    ; 任务编号加1并显示
    inc dl
    mov ah, 02h
    int 21h
    mov dl, '.'
    int 21h
    mov dl, ' '
    int 21h
    jmp display_loop

end_display:
    ; 关闭文件
    mov ah, 3Eh
    mov bx, handle
    int 21h

    jmp end_program

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 10:09:54