DOS 相关 FAQ
- 来源: https://www.freebasic.net/wiki/wikka.php?wakka=FaqDOS
- 最后更新: 2019-02-26
DOS
FreeBASIC 的 DOS 移植版本基于 GNU 工具链的 DJGPP 32 位保护模式 DOS 移植版本。
该移植版本的当前维护者是 DrV。
待编写:平台特定信息、与 Win32/Linux 的区别、与 QB 的区别、教程等。
诚征测试人员
FreeBASIC 的 DOS 版本/目标需要更多测试人员。如果你有兴趣在 DOS 上使用 FreeBASIC,请不要等待未来的版本,现在就来试试吧。欢迎在新旧 PC 上运行 DOS 的测试结果(图形、文件 I/O、串口……)。如果某些功能不正常,请在论坛或 Bug 追踪器中提交详细的 Bug 报告。如果一切正常,你也可以分享你的成功经验。请确保测试较新版本的 FB(0.90 以前的 FB 报告可能被认为已过时且无用),并在抱怨任何问题前先查阅本文档。
限制
DOS 目标在 FreeBASIC 中运行相当良好且受到支持,是最新的。但与其他平台相比,存在一些差异。缺失的功能主要是操作系统、DOS 扩展器或 C 运行时不支持的那些:
- 交叉编译到其他目标
- 多线程(见 FAQ 23)
- 窗口模式图形或使用 OpenGL
- 将
Screenres设置为显卡不支持的任何分辨率 - DOS 不支持 Unicode,
Wstring将与Zstring相同,不支持拉丁字符以外的字符集(需要自行实现) - 无法创建/使用共享库(DLL)(至少不能"轻松"实现),可用于 DOS 的静态外部库数量有限
FreeBASIC DOS 相关问题:
- 1. FB 是 32 位编译器——我需要 32 位 DOS 吗?
- 2. FreeDOS-32 怎么样?FB 能/将能运行,是否有/将有对应版本?
- 3. 在 DOS 中运行 FreeBASIC 时,我收到"Error: No DPMI"消息!
- 4. 有没有办法摆脱 CWSDPMI.EXE 和 CWSDPMI.SWP?
- 5. 我可以使用其他 DOS 扩展器,如 DOS/4GW、Causeway、DOS/32A 吗?
- 6. 那个漂亮的蓝色界面在哪里 / IDE 在哪里?
- 7. 如何在 DOS 中查看 CHM 或 PDF 格式的文档?
- 8. 我如何编写/编辑源代码?
- 9. 如何在 DOS 中播放声音?
- 10. 如何在 DOS 中使用 USB?
- 11. 如何在 DOS 中使用图形?
- 12. FB 中缺少 DEF SEG!如何在代码中变通?
- 13. 如何重写 QB 的 CALL INTERRUPT / 访问 DOS 和 BIOS 中断?
- 14. 如何重写 QB 的 XMS/EMS 处理?
- 15. FBC 报错"cannot find lsupcxx"!
- 16. 如何使用串口或并口?
- 17. 如何使用打印机?
- 18. 如何对在 DOS 中运行的 FreeBASIC 程序截图?
- 19. 图形模式不工作(死机 / 黑屏 / 输出乱码)!
- 20. 鼠标问题!在 DOS 中鼠标完全不工作 / 光标"跳跃" / 等……
- 21. 64 KiB 和 640 KiB 问题是怎么回事 / FB 在 DOS 中支持多少内存?
- 22. 当我尝试使用超过约 1 MiB 内存时,程序崩溃!这是 FreeBASIC 的 Bug 吗?
- 23. DOS 中不允许使用线程函数?求助!
- 24. 用 FB DOS 生成的可执行文件体积很大!
- 25. FB 的编译速度非常慢!
- 26. SLEEP 不工作!如何产生延迟?
- 27. DOS 中性能非常差!
- 28. 我可以用 FB 访问磁盘扇区吗?
- 29. 我可以在 DOS 中使用带有 SSE 等高级指令的内联 ASM 吗?
返回目录
FreeBASIC DOS 相关问题
1. FB 是 32 位编译器——我需要 32 位 DOS 吗?
不需要,FreeBASIC 的 DOS 版本使用了 DOS 扩展器,允许你在 16 位 DOS 内核之上执行 32 位代码。你可以使用 FreeDOS(16 位)、Enhanced-Dr-DOS、旧版封闭式 Dr-DOS,甚至低至约 4 版本的 MS-DOS。你至少需要 80386 CPU,另请参见系统要求。
2. FreeDOS-32 怎么样?FB 能/将能运行,是否有/将有对应版本?
FreeDOS-32 在撰写本文时仍处于实验阶段,但它应该能够无修改地执行 FreeBASIC 及其生成的应用程序。虽然 FB DOS 支持已在 FreeDOS(16 位)上运行,但它也应该为 FreeDOS-32 做好准备。
3. 在 DOS 中运行 FreeBASIC 时,我收到"Error: No DPMI"消息!
你需要一个 DPMI 宿主(DPMI 内核、DPMI 服务器),即文件"CWSDPMI.EXE"(约 20 KiB)或 HDPMI32.EXE(约 34 KiB)。请参阅系统要求和 FAQ 4 了解更多详情。
4. 有没有办法摆脱 CWSDPMI.EXE 和 CWSDPMI.SWP?
有,有 2 种方法。要摆脱 CWSDPMI.EXE 并创建嵌入 CWSDPMI 的独立 DOS 可执行文件,你需要 CWSDPMI 软件包和"EXE2COFF.EXE"文件。使用 EXE2COFF,你可以移除 CWSDPMI.EXE 加载程序(文件减小 2 KiB,生成一个没有扩展名的"COFF"文件),然后将文件"CWSDSTUB.EXE"粘贴到这个 COFF 文件之前。新的可执行文件比原始文件大约大 21 KiB,但它是独立的,不需要额外文件。要摆脱 CWSDPMI.SWP,你可以用 CWSPARAM.EXE 编辑你的可执行文件,并禁用交换(有时也被错误地称为分页)。但请注意,这将把可分配内存限制为系统中安装的物理内存量。此操作可以同时用于 FBC.EXE 文件和 FBC 创建的所有可执行文件。该方法在 CWSDPMI 文档包中也有说明。另外,你可以使用 WDOSX 或 D3X 扩展器。它们不进行交换,并创建独立的可执行文件。由于它们在 Ring 0 中运行你的可执行文件,在发生 Bug 时的崩溃处理不太好,可能导致死机或重启,而其他宿主会以"正常"方式退出并显示寄存器转储。此外,使用 WDOSX 或 D3X 时,派生(spawning)可能工作不正常甚至完全无法工作。最后,你可以使用 HDPMI。下载"HXRT.ZIP"文件(这里:japheth.de/HX.html 备用链接),解压出"HDPMI32.EXE"(约 34 KiB)和"HDPMI.TXT"(代码不需要,只供参考),并将其加入 DOS 启动项("HDPMI32 -r")。这将使 HDPMI 常驻内存,并防止所有 FreeBASIC(以及 FreePASCAL 和 DJGPP)程序因缺少 DPMI 而报错或进行交换。HDPMI 目前无法(轻易/尚未)嵌入到你的可执行文件中。在 HDPMI 或其他外部宿主下运行包含 D3X、CWSDPMI 或某个 DPMI 宿主的可执行文件是没问题的——内置宿主将被简单地跳过。对于 FreeBASIC 来说,使用 DPMI 是绝对必要的,因为它不能生成 16 位实模式代码,而在 DOS 中执行 32 位代码没有其他好方法。
5. 我可以使用其他 DOS 扩展器,如 DOS/4GW、Causeway、DOS/32A 吗?
不是所有扩展器都可以。所谓的 WATCOM 类扩展器因为在内存管理和可执行文件结构上存在重要差异而无法使用。WDOSX 和 D3X 可以工作,因为它们是多标准扩展器,不仅限于 WATCOM 风格。你也可以使用 PMODE/DJ(不是 Tran 的"原版" PMODE,也不是 PMODE/W (!),比 CWSDPMI 节省约 5 KiB,可以嵌入 EXE,但可能影响稳定性或性能),或者如前所述,使用 HDPMI。
6. 那个漂亮的蓝色界面在哪里 / IDE 在哪里?
FreeBASIC 项目专注于编译器,即从你的 BAS 源代码生成可执行文件。它看起来不起眼,但对于你开发的软件质量最为重要。该项目不包含 IDE。目前有几个 FreeBASIC 的外部 IDE,但可能没有一个有 DOS 版本。如果你真的需要,可以尝试 Rhide,但请注意它很复杂且有 Bug,使用风险自负。另请参阅 FAQ 7 和 FAQ 8。
7. 如何在 DOS 中查看 CHM 或 PDF 格式的文档?
目前在 DOS 中没有好的方式查看 CHM 或 PDF 文件。但你仍然可以查看 FreeBASIC 文档。FreeBASIC 开发者之一 coderJeff 提供了一个 FreeBASIC 文档查看器,文档以特殊格式包含其中,并有 DOS 版本。它看起来类似 QB 的内置帮助查看器,但不含编辑器或 IDE。在此下载:http://www.execulink.com/~coder/FreeBASIC/docs.html
8. 我如何编写/编辑源代码?
DOS 有很多编辑器,但只有少数比较好用——一些选项有:FreeDOS EDIT(使用 0.7d (!!) 或 0.9 版本,有 64 KiB 限制,稳定性欠佳(请定期保存你的工作)),SETEDIT,INFOPAD(随 CC386 编译器一同发布,也可编辑大文本,有 C 和 ASM 的语法高亮,但没有 BASIC 的语法高亮)。
9. 如何在 DOS 中播放声音?
在 DOS 中播放声音有 2 种方式:一种是("古老的")PC 扬声器,以出错时发出哔声而著名;另一种是声卡。扬声器易于控制,比想象中能做更多事情,甚至可以播放音频文件(WAV,加上解压代码还可播放 OGG Vorbis、MP3 等),你可以轻松复用大多数现有的 QB 代码(示例:o-bizz.de/qb...speaker.zip)或通过内联 ASM 使用 ASM 代码,但只有一个声道和 6 位,当然质量远不如声卡,而且在一些最新的 P4 电脑上扬声器质量非常差,或者根本没有扬声器。对于旧的 ISA 声卡,有很多示例代码可用;较新的 PCI 声卡(在这种情况下假设是纯 DOS 环境)可以通过("仿真" SB16 兼容)驱动程序来访问(如果你的声卡有 DOS 驱动程序的话,遗憾的是这正变得越来越成问题,DOS 驱动程序很差甚至不存在),或直接访问声卡(这是底层编程,与硬件相关,也需要汇编语言,你还需要关于声卡的技术文档)。有一些灵感来源,如 DOS 音频播放器 MPXPLAY(用 C 加少量 ASM 编写),支持两种方法(原生 + "仿真"驱动),参见最新列表:drdos.org/...wiki...SoundCardChip。DOS 中的声音支持并非 FB DOS 移植的业务范围,事实上 FB 在 Win32 和 Linux 上也不"支持"声音——游戏是"连接到 API",而不是使用 FreeBASIC 命令或库。要播放压缩文件(MP3、OGG Vorbis、FLAC……),你还需要解压代码,现有的 DJGPP 移植库应该可以用于此目的。
10. 如何在 DOS 中使用 USB?
同样,这不是 FB 的业务范围,你需要一个驱动程序,FB 在 Win32 或 Linux 上也不"支持" USB,请参阅其他 Wiki:drdos.org/...wiki...USB 了解在 DOS 中使用 USB 的可能性。
11. 如何在 DOS 中使用图形?
在 DOS 中实现 GUI 或图形绝对是可能的,有几种方法:
- 使用 FB 图形库。它使用 VESA(首选线性方式,但也支持分块方式)访问显卡,支持声卡 VESA VBE 驱动程序报告的任何分辨率,以及标准 VGA 模式。
- VGA 模式 320x200x8bpp:非常简单,最高可靠性和兼容性,但分辨率低且只有 256 种颜色,见示例。
- VGA "ModeX" 320x240x8bpp:与上类似,不那么容易,可靠性和兼容性良好,但分辨率低且只有 256 种颜色,见示例。
- VGA "平面"模式 640x480x4bpp:设置像素较困难,最高可靠性和兼容性,但分辨率低且只有 16 种颜色,暂无公开示例(?)。
- 其他一些"奇特"的 VGA "ModeX" 模式(如 360x240x8bpp):可能可以,但只适合极客 😉
- 编写你自己的 VESA 代码:更困难,兼容性良好,高分辨率和真彩色可行,如果实现不谨慎可能存在可靠性问题。
- 使用外部库(DUGL、Allegro、MGL、WxWidgets):可以创建"精致"的图形和 GUI,增大 EXE 体积,需要遵守库的许可证,潜在的可靠性损失。
请注意,某些显卡通过 VESA 报告的功能有限,最典型的是内存更少(例如 8 MiB 而非 64 MiB)或模式更少(例如只有 24bpp 模式可见而 32bpp 隐藏,只有较低分辨率可见(最高约 1280x1024)而更高分辨率隐藏,只有"4:3"模式可见而"宽屏"模式隐藏)。这是显卡本身的问题,而非 DOS 或 FreeBASIC 的问题。你会在 DOS 以外的系统中看到额外的功能,或者只在 DOS 中使用绕过 VESA 进入最底层的硬件检测工具时才能看到。
12. FB 中缺少 DEF SEG!如何在代码中变通?
DEF SEG 与 16 位实模式寻址有关,因此被移除。"直接"访问 VGA 或其他低内存区域是不可能的,因为 FreeBASIC 的内存模型(与 DJGPP 相同)不是基于零地址的。要访问低 DOS 内存,请使用 DOSMEMGET 和 DOSMEMPUT,参见"vga13h.bas"示例,或在内联 ASM 中使用"_dos_ds"选择器,见示例:
start GeSHi
'' DOS only example of inline ASM accessing low memory
'' Run in text mode 80x25 only
'' Including dos/go32.bi will define "_dos_ds"
'' "pointing" into GO32 block
#include "dos/go32.bi"
Dim As UInteger DDS
DDS=_dos_ds
? : ? "Hello world !"
? "_dos_ds=$";Hex$(DDS)
? "This is just a tEst - abcd ABCD XYZ xyz @[`{ - press any key ..."
Do
Sleep 1000
If Inkey$<>"" Then Exit Do
Asm
mov eax,[DDS] '' Directly using "_dos_ds" won't work here !!!
push eax
pop gs '' Just to get sure, it is usually set anyway
Xor ebx,ebx
aa3:
mov al,[gs:0xB8000+2*ebx]
cmp al,65 '' "a"
jb aa1
cmp al,122 '' "z"
ja aa1
cmp al,90 '' "Z"
jbe aa2
cmp al,97 '' "a"
jb aa1
aa2:
Xor al,32 '' Swap case
aa1:
mov [gs:0xB8000+2*ebx],al
inc ebx
cmp ebx,2000
jne aa3
End Asm
Loop
? : ? "Bye"
Endend GeSHi
13. 如何重写 QB 的 CALL INTERRUPT / 访问 DOS 和 BIOS 中断?
这些中断只能使用 DOS 版本/目标的 FB 来访问。
访问中断的速度比 QB 慢:使用 FB 时,DPMI 宿主需要进行 2 次上下文切换,进入实模式再返回。所有这些在纯 DOS 中会消耗数百个时钟周期,如果加载了 emm386 或在 Windows 的 DOS 窗口中则会消耗数千个时钟周期。速度降低可能可以忽略不计,也可能很显著,这取决于具体情况。你应该尽量减少这类调用的次数,每次调用处理更多数据——至少几 KiB,而不是仅一个或几个字节。
使用 DJGPP 的 DPMI 包装器:
start GeSHi
#include "dos/dpmi.bi"
Type RegTypeX As __dpmi_regs
#define INTERRUPTX(v,r) __dpmi_int( v, @r )end GeSHi
或者,你可以通过内联 ASM 调用 INT,有 2 件重要的事情需要注意:FB 的内存模型不是基于零地址的(另见 FAQ 12,"DEF SEG"问题),此外,将地址"直接"传递给 INT(如 DS:[E]DX)将不起作用,除非你的 DPMI 宿主支持"DOS API 翻译"。
14. 如何重写 QB 的 XMS/EMS 处理?
这取决于原始代码使用它的原因。如果只是为了绕过低内存限制,只需删除它,改用"普通"的 FB 数据类型/内存处理功能即可。如果它用于(声音)DMA,那你就需要完全重新设计代码,关于声音请参见 FAQ 9。对于 DMA,最好使用低内存(应该问题不大,因为应用程序代码和大多数缓冲区都在 DPMI 内存中),在 DPMI 内存中使用 DMA 是可能的,但更困难。
15. FBC 报错"cannot find lsupcxx"!
此问题的根源是 LIB\DOS\ 目录中的 libsupcxx.a 文件,文件名有 9 个字符。你的错误是在 Windows 中启用了长文件名(LFN)支持后解压了 ZIP,然后在 DOS 中没有 LFN 支持的情况下使用 FB,导致该文件显示为 LIBSUP~1.A 而无法找到。将文件重命名为 LIBSUPCX.A(只有一个 X)或在 DOS 中重新解压 ZIP。注意:FB 0.18 的变更,需要重新测试。
16. 如何使用串口或并口?
DOS INT14 不是很有用/高效,因为它每次调用只发送/读取一个字符。因此最好使用外部的 DOS32 通信库。FB 0.18.2 及以前版本不支持 DOS 目标的 OPEN COM,coderJeff 有一个实验性库/驱动程序可用,自 0.18.3 起已包含在 FB 中。
17. 如何使用打印机?
DOS 内核在这方面帮不上忙,所以你必须自己准备文本(简单)或像素数据(对于与"ESC/P"标准兼容的打印机来说还算容易),并通过并口或 USB(使用附加驱动程序,见 FAQ 10)将其发送到打印机。所谓的"GDI"或"Windows"打印机在 DOS 中无法以合理的努力使其工作。
18. 如何对在 DOS 中运行的 FreeBASIC 程序截图?
最好在自己的代码中加入此功能。基于 DOS TSR 的截图工具(如 SNARF)大多适用于文本屏幕,但可能没有一个适用于 FreeBASIC 的 GFX 库。这不是一方或另一方的 Bug,这是"设计上"的问题。
19. 图形模式不工作(死机 / 黑屏 / 输出乱码)!
请在论坛中提交 Bug 报告。为使其尽可能有用和富有成效,请注意以下事项,按照给定步骤操作并提供所有相关信息:
- 检查 GfxLib 页面上列出的限制
- 图形在非常旧的 PC 上可能无法正常工作。如果你的 CPU 频率低于约 500 MHz,请提供详细信息;如果不确定,请使用 RayeR 的 CPUID 或类似程序进行测试。
- 需要关于你的显卡的确切信息。在 DOS 中使用 DrV 的 VBEDIAG(仅报告信息)和 RayeR 的 VESATEST(也尝试设置模式,允许直观检查结果)进行测试。找出哪些"有用"模式(640x480、800x600)受支持及其色深(8、16、24、32 bpp),以及是否可以正确设置和显示。
- 找出并精确描述问题所在("模式用 VESATEST 可以工作但用 FB 不行"、"没有图形也没有错误"、"黑屏和死机"、"图形不完整/混乱"……)。
- 如果某个复杂程序不工作,也尝试一个简单的测试,如在屏幕中央画一个圆。
- 在没有鼠标驱动程序的情况下尝试(这可以减少 CPU 开销)。
- 找出哪些模式受影响。如果某个模式不工作,降低分辨率或色深,确保测试最"低成本"/最安全的模式:640x480(32/24/16/8 bpp)、640x480(4 bpp)和 320x200(8bpp)。
- 对于一些旧显卡,有 VESA 驱动程序可用(S3VBE/UVIVBE)。同时测试有驱动程序和没有驱动程序的情况,并在报告中包含此信息。
- 从 DOS 启动文件中删除可能有问题的内容(内存管理器、驱动程序)。FB 不需要这些,只需要一个 DPMI 宿主(另见 FAQ 4)。
- 在报告中提供你的显卡、CPU(如果较旧)、DOS 类型和版本、Bug 症状以及简单示例代码的信息。
RayeR 的 VESATEST 和 CPUID 可在此处下载:rayer.ic.cz/programm/programe.htm,VBEDIAG 在此处:drv.nu/vbediag/。
20. 鼠标问题!在 DOS 中鼠标完全不工作 / 光标"跳跃" / 等……
要在 DOS 中使用鼠标,你需要一个兼容的驱动程序,能识别你的鼠标,并被 FreeBASIC 库识别。为获得最佳效果,你需要一个好的驱动程序和合适的鼠标。
鼠标:最佳选择(如今也相当常见)是 PS/2 鼠标。旧式串口鼠标也应该可以工作。最新的是 USB 鼠标——但不太适合在 DOS 中使用,因为它需要一个兼容的(INT33)高质量原生 USB 鼠标驱动程序(目前没有可用的,只有一些实验性的),或者依赖 BIOS 仿真(并非总是可用,或"不精确")。
驱动程序:首选是来自 FreeDOS 项目的 CTMOUSE。有 2008 年 7 月的 1.9a1、2.0a4 和 2.1b4 版本可用。它包含在 FreeDOS 中(但不限于此),或从这里下载某个版本:ibiblio.org/pub/...mouse。没有一个版本是完美的,但它们仍然非常可用,比大多数竞争产品更好。1.9xx 和 2.1xx 将与 BIOS 协作,允许 USB 仿真;2.0xx 绕过 BIOS,因此 USB 仿真将不工作。Logitech 鼠标驱动程序通常也表现良好,从这里下载:uwe-sieber.de/util_e.html——6.50 版本是个好的开始。DRMOUSE 和某些(旧?)版本的 MSMOUSE 以存在问题而著称。
如果鼠标完全不工作,最可能的原因是驱动程序未加载、无法识别鼠标(查看驱动程序消息),或与 INT33"标准"不兼容。对于 USB 鼠标,在 BIOS 设置中激活"USB 鼠标仿真"可能有帮助。
如果鼠标控制"不精确"、光标"跳跃",那么你要么有一个不好的驱动程序——换一个更好的,要么 BIOS 仿真很差——解决方法是购买一个 PS/2 鼠标。
21. 64 KiB 和 640 KiB 问题是怎么回事 / FB 在 DOS 中支持多少内存?
内存管理是 DPMI 宿主的业务,而非编译器的。FreeBASIC 及其生成的可执行文件不受此问题影响,因为它们使用 32 位 DPMI 代码,而非实模式代码。你几乎可以使用 PC 的全部内存,但有一些限制,不过这些限制远高于 64 或 640 KiB。CWSDPMI r5 已验证只能在 512 MiB 以内正常工作,额外内存不会导致崩溃(与一些旧版本不同),但会被静默忽略。HDPMI 应该支持更多:最高 4 GiB(32 位寻址的限制),但在如此大内存的机器上测试不多——已验证到约 1.5 GiB。FreeBASIC 及其生成的代码不需要经典的基于 DOS 的内存管理器(HIMEM/XMS 和 EMM386/EMS),但如果它们存在,应该可以共存。当然,这一切只适用于真实 DOS,像"Dos Box"这样的东西会自己控制内存管理,只向你的 DOS 代码提供少量内存(视情况而定,最多约 64 MiB)。
22. 当我尝试使用超过约 1 MiB 内存时,程序崩溃!这是 FreeBASIC 的 Bug 吗?
不,这不是 FreeBASIC 的 Bug,也不是 DOS 特有的问题,另见编译器 FAQ。对于初学者,简单的解决方案是对数组使用 Shared。更有经验的用户可以考虑使用内存管理函数,如 Allocate。这在 DOS 中更为重要,因为它允许应用程序在内存较少的(旧)PC 上运行(例如仍能至少编辑小文本),以及在有大量内存时使用所有内存(例如编辑大文本)。
23. DOS 中不允许使用线程函数?求助!
线程支持函数不支持 DOS 目标,而且很可能短期/永远都不会支持。原因很简单:DOS 内核、DPMI 宿主/标准以及"GO32" DOS 扩展器都不支持线程,不像 Win32 或 Linux 内核。但在 DOS 中没有什么是不可能的:你可以在 DPMI 之上建立自己的线程机制。有多种可能性,其中两种是:
- 设置一个 ISR,参见"ISR_TIMER.BAS"示例。这不是"完整的"替代品,但在某些情况下已经足够。
- 有一个用于 DJGPP 的 pthreads 库,可以在一定程度上"模拟"类 Linux 的线程。它对 [P]7-ZIP DJGPP 移植版(用 C++ 编写)效果还不错,尚未用 FB 测试。
- 参见论坛 t=21274
24. 用 FB DOS 生成的可执行文件体积很大!
这是事实,但目前没有简单/快速的修复方法。FB 是一个 32 位高级语言编译器,大部分体积来自 DJGPP。!writeme!(见论坛:t=11757)
25. FB 的编译速度非常慢!
问题:"FBC 编译一个"Hello world"程序需要 10 秒!TurboBASIC / QBASIC / VBDOS / PowerBASIC 执行同样的任务不到 1 秒……"
这是事实,但这是"设计上"的结果:FB 分 3 个步骤编译你的源代码,保存中间文件,如 CompilerCmdLine 所述,而许多旧编译器只在内存中进行 1 次扫描。这主要与文件 I/O 性能有关,参见下面的 FAQ 27 了解改进的可能性;此外,让 DPMI 宿主常驻内存(HDPMI32 -r 或 CWSDPMI -p,见上面的 FAQ 4)可以获得小幅改善。请注意,延迟主要是"加法"的,所以对于较大的项目影响不会太大。
26. SLEEP 不工作!如何产生延迟?
Sleep 可以工作……但分辨率只有约 55ms = 1/18s,因此"SLEEP 500"是可以的,但例如使用"SLEEP 2"来延迟 2 毫秒将不起作用。!writeme! / !fixme!
- PIT / BIOS 定时器(默认运行在 18.2 Hz),读取 BIOS 定时器或设置自己的定时器,参见"ISR_TIMER.BAS"示例,提高 PIT 频率(谨慎使用)
- 轮询 BIOS 定时器 + PIT 计数器,来自 DKRNL32 的 TIMERHLP.ASM 中的方法,可在不提高 PIT 频率的情况下提高上述精度
- RDTSC 指令(Pentium 及更新型号)
- RTC 时钟
- 延迟循环
27. DOS 中性能非常差!
问题:"DOS 中的性能与从完全相同源代码编译的 Win32 / Linux 二进制文件相比非常差!"或"更糟糕的是,完全相同的 DOS 二进制文件在 NTVDM 中运行比在 DOS 中快得多!"
这两种情况确实可能发生,但 DOS 绝不是注定要慢的,低效之处是可以修复的。首先你必须找出代码在哪里损失了性能。
文件 I/O:DOS 默认为其缓冲区使用很少的内存,而其他系统使用更多内存并"积极"进行文件缓存。当处理许多小文件时,这会导致严重的性能下降。解决方法是安装文件缓存,例如 LBACache,或者你可以安装 RAMDISK(一个好的选择:SRDISK),将"有问题的"文件(例如 FreeBASIC 安装)复制到其中并在那里工作(确保定期将你的工作备份到更持久的介质)。两者都需要一个 XMS 宿主(使用 HIMEMX)。此外,DOS 默认使用 BIOS 访问硬盘,而其他系统则尽力找到并使用 DMA。测试工具:Japheth 的 IDECHECK(下载:japheth.de/Download/IDECheck.zip)——在"I13"和"DMA"模式下运行并比较结果。如果"DMA"快得多(可能快 1 到 10 倍,取决于 PC 型号),那么安装 DOS DMA 驱动程序(例如可以尝试 XDMA 3.1)可以在大文件上带来很大的速度提升。还要确保以大块读写数据(至少 16 KiB),而不是单个字节。其他操作系统在这里更宽容,但在 DOS 上每个单独的文件 I/O 调用都会造成小的"加法"延迟,因此具有良好缓冲的高效代码设计至关重要。
图形:Pentium 2 及更新 CPU 有一个名为"MTRR"的与缓存相关的功能,可以加速写入视频 RAM。其他操作系统的驱动程序通常会启用它。DOS 不启用(因为它根本不处理图形),FB GFX 也不启用。使用 Japheth 的"VESAMTRR"工具(包含在"HXGUI.ZIP"包中),它将启用该加速功能,在模式切换和大多数"非致命"应用程序崩溃之后仍然有效,直到重启。可能的加速倍数因 PC 型号而异,最高约 20 倍。此外,鼠标处理在 DOS 中消耗了一些(太多)CPU 性能,这是一个已知的弱点(DOS FB GFX 的设计并不"很差",只是通用的"标准"——并不是很好),理论上可以修复,但不容易,你只能尝试几种不同的鼠标驱动程序(见 FAQ 20)。
28. 我可以用 FB 访问磁盘扇区吗?
可以……但 FreeBASIC 在这里帮不了你太多:没有"可移植"的解决方案,使用特定于操作系统的底层方式。DOS 有 3 种方法:
- 使用 DOS 的逻辑磁盘访问功能进行绕过文件系统的扇区访问,见论坛示例:freebasic.net/forum/viewtopic.php?t=11830
- 使用物理磁盘 BIOS INT 13,绕过 DOS
- 使用 CPU 端口,最底层,同时绕过 DOS 和 BIOS,见论坛 freebasic.net/forum/viewtopic.php?t=16196,FAQ 27 上方 IDECHECK 的源代码,FASM 论坛或某些操作系统开发资源
请注意,此类实验有些"危险"——如果出现问题,你很容易丢失数据或使 PC 无法启动。
29. 我可以在 DOS 中使用带有 SSE 等高级指令的内联 ASM 吗?
可以……但 SSE2 及以上指令需要先启用。这通常被认为是 DPMI 宿主的业务,HDPMI32 和 CWSDPMI 7 会这样做,但大多数其他宿主不会。使用这些指令之前,请确保正确进行 CPUID 检测。最好在支持最新指令的同时,也提供一个与旧 CPU(早期 Pentium、80386)兼容的代码分支,并在那些分支中也避免 CMOV 指令。
参见
返回目录