中国DOS联盟

-- 联合DOS 推动DOS 发展DOS --

联盟域名:www.cn-dos.net 论坛域名:www.cn-dos.net/forum
DOS,代表着自由开放与发展,我们努力起来,学习FreeDOS和Linux的自由开放与GNU精神,共同创造和发展美好的自由与GNU GPL世界吧!

中国DOS联盟论坛
现在时间是 2026-06-16 09:34
中国DOS联盟论坛 » DOS开发编程 & 发展交流 (开发室) » 自动检测汉字系统是否加载的QUICK BASIC程序 查看 2,733 回复 12
楼 主 自动检测汉字系统是否加载的QUICK BASIC程序 发表于 2004-02-27 00:00 ·  中国 广东 佛山 三水区 电信
元老会员
★★★★
积分 5,170
发帖 1,637
注册 2002-10-16 00:00
UID 8
性别 男
来自 广东佛山
状态 离线
这是在某本合订本上介绍的,原来介绍用C检测,我后来用QB实现了,现在找到程序把它贴出来,只要用一个变量保存检测结果,准备好两套显示,就可以对是否有汉字系统自动适应了。

REM 在BASIC程序中自动检测汉字系统
DEF SEG = &H40
mode = PEEK(&H49)
OUT &H3CE, &H6
result = INP(&H3CF) AND &HF
PRINT "mode="; mode, "result="; result
IF mode = 3 AND result = 5 THEN
PRINT "现在于直接写屏的汉字系统中"
PRINT "现在你看到的是汉字"
ELSE
IF mode = 3 AND result = 14 THEN
PRINT "Is not any CCDOS in the memory ,It's it ?"
PRINT "So , You only see the English"
ELSE
IF mode = 18 AND result = 1 THEN
PRINT "你现在非直接写屏的汉字系统中"
ELSE
PRINT "I Can't know which display mode ."
END IF
END IF
END IF
[已使用 Gemini 解答]
Gemini 解答

技术背景说明

在 20 世纪 80 年代至 90 年代中期的中文 DOS 环境下,由于原始的 PC 标准(如 IBM VGA/EGA 规范)并不直接支持双字节字符(DBCS)显示,中文系统(CCDOS、天汇、UCDOS、希望等)通常通过拦截中断和直接操作视频硬件寄存器来实现汉字显示。

本帖讨论的核心在于如何通过 Quick BASIC 代码识别当前的视频状态,从而判断是否加载了汉字系统。这主要涉及到 BIOS 数据区、VGA 控制器寄存器以及多路中断调用(Multiplex Interrupt)。


技术实现原理与纠正

1. 基于视频状态的检测(帖子 #1 与 #8)

原作者 mys 和用户 本是 提到的方法是利用 VGA 图形控制器的 Graphics Controller (GC) 寄存器。

  • 硬件原理: 索引为 06h 的 Misc 寄存器(通过端口 3CEh3CFh 访问)决定了显存的映射方式。
    • 在标准的 DOS 文本模式(Mode 3, 80x25)下,该寄存器的默认值通常使得结果掩码为 0Eh(或包含位 1 和位 3)。
    • 许多中文字体驱动程序(如采用图形覆盖技术或拦截写屏的中文字体)会修改 VGA 的位平面(Bit Planes)访问方式,以便在字符模式下模拟图形输出或处理汉字点阵。
  • 局限性: 这种基于硬件端口(INP / OUT)的方法依赖于具体的汉字系统实现。Wengier 在帖子 #2 中指出的修正 result = 1 or result = 5 是必要的,因为不同的环境(如 Windows 虚拟 DOS 虚拟机、不同的驱动实现)在初始化 VGA 寄存器时存在细微差异。

2. 基于软件中断的检测(帖子 #4)

Kinglion 提供的汇编代码(通过 CALL ABSOLUTE 执行)使用了更标准的方法,即探测特定的中断调用。

  • 中断 2Fh (Multiplex Interrupt): 这是 DOS 环境下各 TSR(内存驻留程序)之间通信的标准接口。
  • 功能调用 0DB00h: 这是历史上许多中文系统(如天汇、UCDOS、CCDOS)约定的探测接口。如果 AX = 0DB00h 调用后,AL 返回 0FFh,通常意味着中文内核已加载。
  • 功能调用 0DB10h / INT 10h: 另一部分中文系统通过扩展 INT 10h(视频服务)来提供中文支持。代码中检测 AL 是否返回 0FFh 来验证环境。
  • 技术细节: 帖子 #4 的代码逻辑是:
    1. 尝试 INT 2Fh / AX=0DB00h
    2. 如果失败,尝试 INT 10h / AX=0DB10h
    3. 根据返回值判断是否设置成功标志位,最后回传给 QB 的数组空间。这是当时最稳健的检测方案,因为它不依赖于特定的视频硬件状态。

关于环境变量与错误码的补充(帖子 #5, #7, #9)

在 DOS 中,由于每个进程都拥有自己的 环境变量块(Environment Block) 副本,子进程(如 QB 编写的程序)修改自己的环境变量副本后,在退出时无法直接反馈给父进程(如 COMMAND.COM)。

  • 官方局限: 正如 xugaohui 所述,QB 的 ENVIRON 语句只能修改局部环境。
  • 历史解决方案: 当年通用的做法是程序运行后通过 SYSTEM nEND n 返回一个 退出码(ERRORLEVEL)。批处理文件随后使用 IF ERRORLEVEL n 逻辑来执行后续操作(例如加载不同的驱动或显示不同的界面)。
  • 另一种方式: 如果必须修改父进程的环境变量,则需要直接定位 DOS 内核中的 Master Environment Block。这涉及到遍历 PSP(程序段前缀)链表,操作复杂且由于不同 DOS 版本(MS-DOS 5.0+, PC-DOS, FreeDOS)的内核结构差异,极具风险。

关于 Windows 环境检测(帖子 #12)

byxyk 提到的 AX = 160Ah 是 Windows 的增强模式探测调用。

  • 功能: 如果程序运行在 Windows 的 DOS 虚拟机中,该调用会返回 Windows 的主次版本号。
  • 意义: 在 Win9x 时代,DOS 窗口自带中文支持(基于 WinOldAp 的保护模式驱动),传统的 DOS 级检测(如直接探测显卡寄存器)可能会失效或产生不稳定的结果,结合此调用可以区分“纯实模式 DOS”和“Windows 下的虚拟 DOS 环境”。

总结

在 2004 年至 2010 年的讨论语境下,最推荐的方式是结合 INT 2Fh (AX=0DB00h)ERRORLEVEL 返回。通过硬件端口直接读取寄存器(如 3C5h3CFh)虽然代码简洁,但在不同显卡架构及模拟器(如 DOSBox)或现代兼容层下稳定性较低。

我的网志
http://hzmys.blog.163.com/
我的网盘
firststep.qjwm.com
fsmys.ys168.com
ssmys.ys168.com
www.brsbox.com/fsmys
www.brsbox.com/ssmys
www.brsbox.com/ccdos
2 发表于 2004-02-28 00:00 ·  美国
系统支持
★★★★★★
“新DOS时代”站长
积分 27,736
发帖 10,521
注册 2002-10-09 12:00
UID 9
状态 离线
把程序中的这一行:

IF mode = 3 AND result = 5 THEN

改成:

IF mode = 3 AND (result = 1 or result = 5) THEN

吧,否则在Win9x/ME的DOS窗口中的AW97、XZL等汉字系统下,或者在纯DOS下均无法正常判断汉字系统是否加载。

Wengier - 新DOS时代

欢迎大家来到我的“新DOS时代”网站,里面有各类DOS软件和资料,地址:
http://wendos.mycool.net/

E-Mail & MSN: wengierwu AT hotmail.com (最近比较忙,有事请联系DOSroot和雨露,谢谢!)

3 发表于 2004-03-02 00:00 ·  中国 辽宁 沈阳 联通
铂金会员
★★★★
痴迷DOS者
积分 5,798
发帖 1,924
注册 2003-06-20 00:00
UID 5583
性别 男
来自 金獅電腦軟體工作室
状态 离线
我也有一段关于判断中文系统是否启动的Quick BASIC程序。改天上传供大家分享。
熟能生巧,巧能生精,一艺不精,终生无成,精亦求精,始有所成,臻于完美,永无止境!
金狮電腦軟體工作室愿竭诚为您服务!
QQ群:8393170(定期清理不发言者)
个人网站:http://www.520269.cn
电子邮件:doujiehui@vip.qq.com
微信公众号: doujiehui
4 我的关于检测中文系统是否启动的Quick BASIC程序 发表于 2004-03-21 00:00 ·  中国 辽宁 朝阳 联通
铂金会员
★★★★
痴迷DOS者
积分 5,798
发帖 1,924
注册 2003-06-20 00:00
UID 5583
性别 男
来自 金獅電腦軟體工作室
状态 离线
CALL TestCcdos
SYSTEM

SUB TestCcdos
DIM a%(50)
DEF SEG = VARSEG(a%(0))
RESTORE
FOR I% = 0 TO 37
READ D%
IF I% = 4 THEN
D% = VARPTR(a%(49)) MOD 256
ELSEIF I% = 5 THEN
D% = VARPTR(a%(49)) / 256
END IF
POKE VARPTR(a%(0)) + I%, D%
NEXT I%

CALL ABSOLUTE(VARPTR(a%(0)))
DEF SEG
IF a%(49) = 0 THEN
PRINT
PRINT "This is a test program!"
PRINT "If you run it under Chinese System, Program will show GB Chinese char message."
PRINT
SYSTEM
ELSE
PRINT "这是一个中文测试程序!"
PRINT "版权所有:金狮计算机软件工作室 窦杰晖"
PRINT "电子邮件:kinglionsoft@idvweb.com"

END IF
END SUB

DATA &H50,&H53,&H56,&HBE,&H00,&H00,&H2E,&HC7,&H04,&H00,&H00,&HB8,&H00,&HDB,&HCD,&H2F
DATA &H3C,&HFF,&H74,&H09,&HB8,&H10,&HDB,&HCD,&H10,&H3C,&HFF,&H75,&H05,&H2E,&HC7,&H04
DATA &H01,&H00,&H5E,&H5B,&H58,&HCB




熟能生巧,巧能生精,一艺不精,终生无成,精亦求精,始有所成,臻于完美,永无止境!
金狮電腦軟體工作室愿竭诚为您服务!
QQ群:8393170(定期清理不发言者)
个人网站:http://www.520269.cn
电子邮件:doujiehui@vip.qq.com
微信公众号: doujiehui
5 发表于 2009-07-05 10:57 ·  中国 广东 揭阳 电信
高级用户
★★
积分 774
发帖 293
注册 2003-04-16 00:00
UID 1579
性别 男
来自 湖北仙桃
状态 离线
顶一下老贴。
请教大家,这样检测汉字系统是否加载后能不能新增一个DOS环境变量?
微软的方法是再调用批处理设置环境变量:http://support.microsoft.com/kb/43691/zh-cn
vbdos的Environ只能修改或删除已经存在的dos环境变量,而不能新增加环境变量。
这样很不方便,能不能直接在QB中新增一个环境变量呢?

[ Last edited by xugaohui on 2009-7-5 at 11:03 ]
下载
09年7月7日 更新
感谢网友 囧HQY 提供空间
6 不用环境变量,只要7行汇编代码就行! 发表于 2009-07-05 12:46 ·  中国 江苏 苏州 电信
银牌会员
★★★
积分 2,223
发帖 789
注册 2005-01-27 00:00
UID 35703
性别 男
状态 离线
不用环境变量,只要7行汇编代码就行!
mov dx,3C4h
mov al,02
out dx,al
mov dx,3C5h
in al,dx
cmp al,03
下一行用JZ 英语DOS或者JNZ 中文DOS即可。
我的VTmagik.com中就是如此操作的。
;jz EnDisp, jnz CcDisp
本帖最近评分记录 (共 1 条) 点击查看详情
评分人分数时间
xugaohui +1 2009-07-05 13:27
my major is english----my love is dos----my teacher is the buddha----my friends--how about U
7 发表于 2009-07-05 13:10 ·  中国 广东 揭阳 电信
高级用户
★★
积分 774
发帖 293
注册 2003-04-16 00:00
UID 1579
性别 男
来自 湖北仙桃
状态 离线
不懂汇编和C,我想是用一个程序检测是否为中文环境,然后设置环境变量cn=1,这样在dos下任何批处理都可以判断当然环境是否中文的,很方便做出中英文显示的批处理程序。在Qb也可以输入中英文提示。我看了Pascal也没有新增环境变理的命令。
微软的网站是总是这样的说明:http://support.microsoft.com/kb/69846/zh-cn
看powerbasic的帮助试试PEEK$ 和 POKE$解决问题,估计这个办法不太好。

经测试用PEEK$ 和 POKE$不行,因为内存中有多个程序段前缀PSP,这样就搜到很多环境变量,却不知那个是正确的。

[ Last edited by xugaohui on 2009-7-5 at 15:37 ]
下载
09年7月7日 更新
感谢网友 囧HQY 提供空间
8 发表于 2009-07-06 00:19 ·  中国 江苏 苏州 电信
银牌会员
★★★
积分 2,223
发帖 789
注册 2005-01-27 00:00
UID 35703
性别 男
状态 离线
6楼的汇编转BASIC如下:
REM 在BASIC程序中自动检测汉字系统
OUT &H3C4, 02
result = INP(&H3C5) AND &HF
IF result = 3 THEN
PRINT "MS/PC DOS"
ELSE
PRINT "CCDOS"
END IF
END
my major is english----my love is dos----my teacher is the buddha----my friends--how about U
9 发表于 2009-07-06 04:45 ·  中国 广东 揭阳 电信
高级用户
★★
积分 774
发帖 293
注册 2003-04-16 00:00
UID 1579
性别 男
来自 湖北仙桃
状态 离线
谢谢本是,楼上的简单有效。
vbdos本身不能设置环境变量,但system语句可以返回DOS错误号,可以在批处理很好调用,比环境变量更好使用。
下载
09年7月7日 更新
感谢网友 囧HQY 提供空间
10 发表于 2009-07-06 23:50 ·  中国 广东 揭阳 电信
高级用户
★★
积分 774
发帖 293
注册 2003-04-16 00:00
UID 1579
性别 男
来自 湖北仙桃
状态 离线
继续请教本是,wbat程序在加载ccdos后,用鼠标操作时控件时有问题。怎么QBasic写个鼠标驱动是否加载的程序呢?
网上的文章太多是调用中断的。这样生成的文件太大,而且不方便。
http://support.microsoft.com/kb/37882/zh-cn
http://support.microsoft.com/kb/28171/zh-cn
下载
09年7月7日 更新
感谢网友 囧HQY 提供空间
11 发表于 2009-07-07 04:53 ·  中国 江苏 苏州 电信
银牌会员
★★★
积分 2,223
发帖 789
注册 2005-01-27 00:00
UID 35703
性别 男
状态 离线
请参考“QBASIC对QB中断调用的移植及绝对地址调用的扩展”(http://www.cn-dos.net/forum/viewthread.php?tid=48086&sid=e1w9ca
my major is english----my love is dos----my teacher is the buddha----my friends--how about U
12 发表于 2009-07-07 06:08 ·  中国 云南 昆明 联通
初级用户
★★
积分 112
发帖 54
注册 2007-06-18 22:47
UID 91747
性别 男
状态 离线
bool InWinBox( )
{
_AX = 0x160a;
geninterrupt( 0x2f );
return !_AX;
}
13 发表于 2010-11-19 15:11 ·  中国 福建 福州 福清市 电信
初级用户
积分 134
发帖 17
注册 2004-10-25 00:00
UID 32901
性别 男
状态 离线
学习……
论坛跳转: