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

DOSBox环境下汇编语言实现TXT文件单词计数功能求助

汇编程序单词计数功能修复求助

我是汇编语言编程初学者,当前需要完成以下任务:

  • 提示用户输入TXT文件名
  • 检查文件是否存在:若存在则统计文件内单词数并显示结果;若不存在则报错并重新提示输入

目前已实现文件读取部分,但单词计数逻辑存在问题,附上在DOSBox下编译运行的现有代码,请求帮助完善代码以完成任务。

现有代码

.model small
.stack 200h
.data
            prompt          db 10,13, "Enter the file name: $"
            filename        db 100,102 dup("$")
            filehandle      dw ?
            open_msg        db 10,13, "File successfully opened! $"
            open_error_msg  db 10,13,"File cannot be opened! $"
            count_msg db 10, 13, 'The number of words in the file: $'
            word1 db 1 
            
.code
start:
    ;Initiate
    mov ax,seg open_msg
    mov ds,ax

; Display Prompt message ===
retry:
    mov dx,offset prompt
    mov ah,9
    int 21h

    ; Enter Filename ===
    mov dx,offset filename
    mov ah,10
    int 21h
    mov bl,filename[1]
    cmp bl,8
    ja retry
    jmp store

store:
    mov [bx+filename+2],0

;Open the file
open:
    mov ah, 3Dh
    mov dx, offset [filename+2] 
    mov al,2
    int 21h
    jc retry

    ;if file successfully opened, save the filehandle
    mov [filehandle],ax
    mov ah,9
    mov dx,offset open_msg; display file opened succesfully
    int 21h
    
    jmp count_loop
    

error_when_open:
    mov ah,9
    mov dx,offset open_error_msg
    int 21h

; PART for Counts the number of words in the file 

; continue the PART for Counts the number of words in the file here
count_words:
    mov cx, 0
    mov si, 0

count_loop:
    mov ah, 3fh
    mov bx, filehandle
    mov cx, 1
    mov dx, offset word1
    int 21h
    cmp ax, 1
    je increment
    cmp ax, 0
    je end_count
    mov al, word1
    cmp al, ' '
    je increment
    jmp count_loop

increment:
    inc cx
    jmp count_loop

end_count:
    mov ah, 09h
    mov dx, offset count_msg
    int 21h
    mov dx, cx
    add dx, 48
    mov ah, 02h
    int 21h
    jmp close



close:
    mov ah,3eh
    mov dx,filehandle
    int 21h
    mov ah,4ch
    int 21h


end start

修复后的代码

.model small
.stack 200h
.data
    prompt          db 10,13,"Enter the file name: $"
    filename        db 100, 102 dup("$")  ; DOS输入缓冲区:[0]=最大长度, [1]=实际长度, [2..]=输入字符
    filehandle      dw ?
    open_msg        db 10,13,"File successfully opened! $"
    open_error_msg  db 10,13,"File cannot be opened! $"
    count_msg       db 10,13,"The number of words in the file: $"
    current_char    db ?
    is_in_word      db 0  ; 状态标志:0=当前在空白字符,1=当前在单词中
    count_buffer    db 5 dup('$')  ; 存储转换后的十进制数字字符串

.code
start:
    ; 初始化数据段
    mov ax, @data
    mov ds, ax

retry:
    ; 提示输入文件名
    mov dx, offset prompt
    mov ah, 9
    int 21h

    ; 读取文件名(DOS功能调用10)
    mov dx, offset filename
    mov ah, 10
    int 21h

    ; 处理输入的文件名:添加字符串终止符
    mov bl, filename[1]  ; 获取实际输入长度
    cmp bl, 0  ; 禁止空输入
    je retry
    mov byte ptr [filename + 2 + bx], 0  ; 在输入字符末尾加0

    ; 以只读方式打开文件(AL=0),原代码AL=2是读写,统计不需要写权限
    mov ah, 3Dh
    mov dx, offset filename + 2
    mov al, 0
    int 21h
    jc open_failed  ; 进位标志置位表示打开失败

    ; 打开成功,保存文件句柄并提示
    mov [filehandle], ax
    mov dx, offset open_msg
    mov ah, 9
    int 21h

    ; 初始化单词计数相关变量
    mov cx, 0  ; cx存储单词数
    mov byte ptr [is_in_word], 0  ; 初始状态:不在单词中

count_loop:
    ; 读取一个字符(DOS功能调用3F)
    mov ah, 3Fh
    mov bx, [filehandle]
    mov cx, 1
    mov dx, offset current_char
    int 21h

    cmp ax, 0  ; ax=0表示文件读取完毕
    je end_count

    cmp ax, 1  ; ax=1表示成功读取一个字符
    jne count_loop  ; 读取异常,继续循环

    ; 判断当前字符是否为空白字符(空格、制表符、换行、回车)
    mov al, current_char
    cmp al, ' '
    je handle_whitespace
    cmp al, 09h  ; Tab键
    je handle_whitespace
    cmp al, 0Ah  ; 换行
    je handle_whitespace
    cmp al, 0Dh  ; 回车
    je handle_whitespace

    ; 当前字符是非空白字符
    mov al, [is_in_word]
    cmp al, 0
    je start_new_word  ; 之前不在单词中,现在开始新单词
    jmp count_loop  ; 已经在单词中,继续读取下一个字符

handle_whitespace:
    ; 当前字符是空白字符,标记为不在单词中
    mov byte ptr [is_in_word], 0
    jmp count_loop

start_new_word:
    ; 开始新单词,计数+1,标记为在单词中
    inc cx
    mov byte ptr [is_in_word], 1
    jmp count_loop

end_count:
    ; 显示计数提示信息
    mov dx, offset count_msg
    mov ah, 9
    int 21h

    ; 将cx中的数字转换为十进制字符串并显示
    mov ax, cx
    mov si, offset count_buffer + 4  ; 从缓冲区末尾开始填充
    mov bx, 10  ; 除数为10

convert_loop:
    xor dx, dx  ; dx清零,准备除法
    div bx      ; ax = ax / 10, dx = ax % 10
    add dl, '0' ; 余数转换为ASCII字符
    mov [si], dl
    dec si
    cmp ax, 0
    jne convert_loop

    ; 显示转换后的数字字符串
    mov dx, si
    inc dx  ; 指向第一个有效数字
    mov ah, 9
    int 21h

    ; 关闭文件并退出
close_file:
    mov ah, 3Eh
    mov bx, [filehandle]
    int 21h

exit_program:
    mov ah, 4Ch
    int 21h

open_failed:
    ; 显示打开失败提示,然后重新输入
    mov dx, offset open_error_msg
    mov ah, 9
    int 21h
    jmp retry

end start

关键修改说明

  • 核心计数逻辑修复:
    • 新增is_in_word状态标志,区分当前处于空白字符还是单词中
    • 仅当从空白字符切换到非空白字符时,才递增单词计数,符合标准单词定义
    • 支持多种空白字符(空格、制表符、换行、回车)
  • 功能完善:
    • 修复文件打开失败的报错流程:先显示错误信息再重试输入
    • 实现多位数数字显示:新增数字转字符串逻辑,支持任意非负整数计数
    • 优化文件打开模式:使用只读模式(AL=0)替代原有的读写模式,更符合统计需求
  • 代码规范与bug修复:
    • 用标准的mov ax, @data初始化数据段
    • 修复文件名终止符的添加逻辑,避免地址计算错误
    • 修复关闭文件的参数错误:DOS功能调用3E需用bx传递文件句柄
    • 移除无用标签,优化代码流程

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 17:21:08