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

MASM611编译TINY模型汇编程序遇A2118错误及运行无响应问题咨询

MASM611编译TINY模型汇编程序遇A2118错误及运行无响应问题咨询

我来帮你逐个分析和解决这两个问题:

一、编译时出现的A2118错误

当你用ml.exe /AT filename.asm编译时触发A2118: cannot have segment address references with TINY model错误,原因很直接:

  • TINY模型要求程序的代码、数据、栈段合并成一个64KB的段,最终生成.COM格式程序。这种模型下,程序启动时CS=DS=ES=SS,所有段寄存器默认指向同一个段,完全不需要手动设置DS。
  • 你的代码里写了mov ax, @data和mov ds, ax,@data是MASM用来引用独立数据段地址的符号,但TINY模型不存在独立数据段,这种段地址引用属于非法操作,所以编译器报错。

解决办法:直接删掉这两行设置DS的代码,TINY模型下系统会自动帮你把DS指向正确的段。

二、程序编译成功但运行无响应(无输出)

你的程序编译后没反应,核心是两个关键逻辑错误导致的:

1. 文件查找结果的判断逻辑完全错误

INT 21h的4Eh(查找第一个文件)功能调用,不是通过AL的值判断成败,而是通过CF标志位:

  • 查找成功时,CF会被清零;
  • 查找失败(比如目录为空、路径不存在)时,CF会被置位。

你原代码用cmp al, 0来判断,这完全不符合DOS中断的规范,导致即使找不到文件,也不会进入输出逻辑,直接跳转到程序退出,所以看不到任何内容。

正确的判断方式是调用int 21h后,用jc exit_search(如果CF置位,说明查找失败,直接跳转到退出)。

2. DTA中日期和时间的解析完全混乱

INT 21h的4Eh调用后,DTA的结构里:

  • 偏移20h是日期字段(不是年份),格式为:高9位是相对于1980的年份,中间4位是月份,低5位是日期;
  • 偏移22h是时间字段(不是月份),格式为:高5位是小时,中间6位是分钟,低5位是秒(乘以2)。

你原代码不仅把这两个字段搞反了,还直接把整个字拆成字节输出,就算找到文件,输出的也是乱码,但首先是判断错误导致根本没进入输出环节。

3. 额外的小坑

路径用C:\*.*时,要确保DOSBox里的C盘存在对应目录,换成当前目录".\*.*"可能更稳妥,避免因路径不存在导致查找失败。

修正后的代码示例

.model tiny
.stack 100h
.data
DTA db 128 dup(0)
path db ".\*.*", 0  ; 改用当前目录,兼容性更好
creation_time db "File created on: ", 0
.code
main proc
    ; TINY模型下无需设置DS,CS=DS=SS已由系统自动设置
    mov ah, 1Ah       ; 设置磁盘传输区域(DTA)
    mov dx, offset DTA
    int 21h

    mov dx, offset path
    mov ah, 4Eh       ; 查找第一个文件
    int 21h
    jc exit_search    ; CF置位说明查找失败,直接退出

search_loop:
    ; 输出提示字符串
    mov dx, offset creation_time
    mov ah, 09h       ; 字符串输出功能
    int 21h

    ; 解析日期(DTA+20h)
    mov cx, word ptr [DTA+20h]
    ; 提取年份:高9位是相对于1980的数值,加1980得到实际年份
    mov ax, cx
    shr ax, 9
    add ax, 1980
    ; 输出年份(简单的十进制转ASCII)
    call print_decimal
    mov dl, '-'       ; 输出分隔符
    mov ah, 02h
    int 21h
    ; 提取月份:中间4位
    mov al, cl
    shr al, 4
    call print_single_digit
    mov dl, '-'
    int 21h
    ; 提取日期:低5位
    mov al, cl
    and al, 0Fh
    call print_single_digit

    ; 输出时间(DTA+22h)
    mov dl, ' '
    int 21h
    mov cx, word ptr [DTA+22h]
    ; 提取小时:高5位
    mov al, ch
    shr al, 3
    call print_single_digit
    mov dl, ':'
    int 21h
    ; 提取分钟:中间6位
    mov al, ch
    and al, 07h
    shl al, 3
    or al, cl shr 5
    call print_single_digit
    mov dl, ':'
    int 21h
    ; 提取秒:低5位乘以2
    mov al, cl
    and al, 1Fh
    shl al, 1
    call print_single_digit

    ; 输出换行
    mov dl, 0Dh
    int 21h
    mov dl, 0Ah
    int 21h

    ; 查找下一个文件
    mov ah, 4Fh
    int 21h
    jnc search_loop   ; CF未置位说明找到下一个文件,继续循环

exit_search:
    mov ah, 4Ch       ; 程序退出
    int 21h

; 辅助子程序:输出AX中的十进制数(简化版,适用于1980-2099范围)
print_decimal proc
    push bx
    push cx
    mov cx, 10
    xor bx, bx
div_loop:
    xor dx, dx
    div cx
    push dx
    inc bx
    test ax, ax
    jnz div_loop
print_digits:
    pop dx
    add dl, 30h
    mov ah, 02h
    int 21h
    dec bx
    jnz print_digits
    pop cx
    pop bx
    ret
print_decimal endp

; 辅助子程序:输出AL中的单个十进制数(0-59)
print_single_digit proc
    push ax
    mov ah, 0
    mov cl, 10
    div cl
    add ah, 30h
    mov dl, ah
    mov ah, 02h
    int 21h
    mov dl, al
    add dl, 30h
    int 21h
    pop ax
    ret
print_single_digit endp
main endp
end main

修正说明

  1. 删掉了设置DS的代码,彻底解决TINY模型的A2118编译错误;
  2. 修正了文件查找结果的判断逻辑,严格遵循DOS中断的CF标志位判断规则;
  3. 正确解析DTA中的日期和时间字段,并通过辅助子程序将数值转换为ASCII字符输出;
  4. 改用当前目录路径,避免因C盘路径不存在导致的查找失败;
  5. 添加了辅助子程序处理十进制数转ASCII输出,修复原代码中直接输出字节的错误。

备注:内容来源于stack exchange,提问作者Артем Лебідь

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 12:58:00