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

基于8086+DOSBox的驻留计时程序运行异常问题咨询

DOS驻留时钟程序运行其他EXE时失效的问题排查

背景

基于8086微处理器+DOSBox环境开发驻留时钟程序,编译链接命令为:

  • TASM.exe program.asm
  • TLINK.exe /t program.obj

程序目标是在屏幕显示分秒,依赖INT 1Ch每秒触发18次的特性实现约1秒更新一次,但运行其他.exe程序时功能失效,程序代码如下:

.MODEL SMALL
.CODE
    ORG 100H

PROGRAMA:
    JMP RESIDE
    MINUTOS DB 0d
    SEGUNDOS DB 0d
    FONDO DB 00001111b
    CONTADOR DB 18d

RUTINA PROC
    CLI

    PUSH AX
    PUSH BX
    PUSH CX
    PUSH SI
    PUSH ES

    MOV AX, SEG @DATA
    MOV DS, AX

    CMP CONTADOR, 0b
    JNE FIN
 
    CMP SEGUNDOS, 60d
    JNE CONTINUE

SISEG60:
    MOV SEGUNDOS, 0d
    INC MINUTOS

CONTINUE:
    MOV AX, 0B800h
    MOV ES, AX

    XOR AX, AX

    ;APLICAMOS ATRIBUTO A LAS 4 CASILLAS
    MOV AH, FONDO

    MOV SI, 3001d

    MOV ES:[SI], AH

    ADD SI, 2d
    MOV ES:[SI], AH

    ADD SI, 4d
    MOV ES:[SI], AH

    ADD SI, 2d
    MOV ES:[SI], AH

    XOR AX,AX
    MOV SI, 3000d

    ;ESCRIBIMOS LOS MINUTOS
    XOR AX,AX
    MOV AL, MINUTOS
    MOV BL, 10d
    DIV BL
    ADD AL, 30h
    MOV ES:[SI], AL

    ADD SI, 2d
    ADD AH, 30h
    MOV ES:[SI], AH


    ;ESCRIBIMOS LOS SEGUNDOS
    XOR AX, AX
    ADD SI, 4d
    MOV AL, SEGUNDOS
    MOV BL, 10d
    DIV BL
    ADD AL, 30h
    MOV ES:[SI], AL

    ADD SI, 2d
    ADD AH, 30h
    MOV ES:[SI], AH

    INC SEGUNDOS
    MOV CONTADOR, 18d

FIN:
    DEC CONTADOR

    POP ES
    POP SI
    POP CX
    POP BX
    POP AX

    STI
    IRET

ENDP

RESIDE:
    MOV DX, offset RUTINA
    MOV AX, 0
    MOV ES, AX
    MOV SI, 1Ch
    CLI
    MOV ES:[SI], DX
    MOV ES:[SI+2], CS
    STI
    MOV DX, offset RESIDE
    INT 27h

END PROGRAMA

核心问题原因分析

1. 未保存并链式调用原INT 1Ch中断处理程序

INT 1Ch是DOS系统的时钟滴答中断,大量程序依赖该中断实现定时逻辑。当前程序直接覆盖中断向量表中的INT 1Ch入口,既未保存原处理程序地址,也未在自身中断处理末尾调用原程序:

  • 其他程序运行时可能重新修改INT 1Ch向量,直接覆盖你的程序入口
  • 系统依赖INT 1Ch的基础功能被破坏,连锁导致驻留时钟程序失效

2. DS寄存器设置错误

当前编译的是COM格式程序(ORG 100H+TLINK /t),这类程序的代码段、数据段、堆栈段共用同一个段寄存器。但在RUTINA中断处理中,使用MOV AX, SEG @DATA设置DS,驻留后会导致DS指向错误的段地址——其他程序运行时会修改DS上下文,你的中断程序无法正确访问自身的MINUTOS、SEGUNDOS等变量,直接造成时钟更新失效。

3. 驻留内存范围计算错误

使用INT 27h驻留程序时,DX需要指向驻留部分最后一个字节的下一个偏移地址。当前设置MOV DX, offset RESIDE,会导致程序仅驻留到RESIDE标签位置,而中断处理程序RUTINA及变量区的部分内容可能未被正确驻留,其他程序运行时会覆盖这部分未被保护的内存。

4. 视频内存操作未考虑模式切换(次要)

程序直接写入0B800h文本模式视频内存,但部分程序运行时会切换视频模式,此时直接写入0B800h会失效。

修复方向

  1. 保存并链式调用原INT 1Ch中断:

    • 在变量区添加OLD_INT1C_OFF DW ?和OLD_INT1C_SEG DW ?
    • 在RESIDE段先读取原中断向量:MOV AX, 0; MOV ES, AX; MOV SI, 1Ch; MOV AX, ES:[SI]; MOV OLD_INT1C_OFF, AX; MOV AX, ES:[SI+2]; MOV OLD_INT1C_SEG, AX
    • 在RUTINA的FIN标签前调用原中断:PUSH CS; POP DS; CALL DWORD PTR [OLD_INT1C_OFF]
  2. 修正DS寄存器设置:

    • 将RUTINA中的MOV AX, SEG @DATA; MOV DS, AX替换为MOV AX, CS; MOV DS, AX,适配COM程序的段结构
  3. 修正驻留内存范围:

    • 在程序末尾添加END_RESIDE:标签,设置MOV DX, OFFSET END_RESIDE后再调用INT 27h,确保所有代码和变量都被驻留保护

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 23:44:58