使用 DOS 或 BIOS 显示字符



查看Ralph Brown的中断列表, 我发现有许多不同的方法可以将文本字符输出到屏幕。

ROM BIOS API 提供以下功能:

  • AH=09h – 在光标位置写入字符和属性
  • AH=0Ah – 仅在光标位置写入字符
  • AH=0Eh – 电传打字输出
  • AH=13h – 写入字符串

DOS API提供以下功能:

  • AH=02h – 将字符写入标准输出
  • AH=06h – 直接控制台输出
  • AH=09h – 将字符串写入标准输出

这些功能有什么作用?我该如何称呼他们?我该如何在它们之间进行选择?

上述所有功能在完成的任务上都是独一无二的,但是 起初,丰富似乎有些夸张。

  • 国际 21h AH=02h 将字符写入标准输出
    此函数解释字符代码 7(蜂鸣声)、8(退格键)、9(制表符)、 10(换行)和 13(回车)。所有其他字符代码均为 显示。
    退格键是非破坏性的,这意味着光标将一个位置移动到 离开而不抹去下面的东西。后间距在左边缘停止 的屏幕。
    选项卡通过此功能展开。选项卡扩展是替换的过程 ASCII 9 由一系列一个或多个空格 (ASCII 32) 组成,直到光标到达 列位置是 8 的倍数。
    换行将光标向下移动一行,并在需要时滚动屏幕。
    回车会将光标移动到屏幕的最左侧。

  • Int 21h AH=06h 直接控制台输出
    与函数 02h 非常相似,但不太适合一般用途,因为它是 无法输出字符 255。仅供参考,FAT文件名中的法律字符。
    它的存在似乎只是为了避免ctrlC/ctrl中断检查。

  • Int 21h AH=09h 将字符串写入标准输出
    函数 02h 的字符串版本,但无法输出字符 36,因为那个用作字符串终止符。这是一个主要缺点 由于字符 36 ($) 不仅是众所周知的货币符号,而且 FAT 文件名中的合法字符。

  • Int 21h AH=40h 写入文件或设备
    当与预定义句柄 1 一起使用时,此函数输出到 STDOUT, 默认为屏幕。所以这里有另一种显示的可能性 字符。但请注意,它不依赖于字符串终止 性格,但更像是一个长度。当然是最完整的输出功能。 它解释需要解释的内容,它不排除某些 字符,它允许捕获重定向错误,尽管后者涉及使用 Int 24h 处理程序。

  • Int 10h AH=09h 在光标位置写入字符和属性
    没有字符代码被解释,它们都显示在屏幕上。 在文本模式下,提供的属性字节同时生成前台和 背景色,但在图形模式下,您只能获得前景色。 光标位置不会更改。可惜!1

  • int 10h AH=0Ah 仅在光标位置写入字符
    类似于文本模式下的函数 09h,但省略了属性字节。 在图形模式下,此功能与函数 09h 相同。

  • Int 10h AH=0Eh 电传打字输出
    此函数解释字符代码 7(蜂鸣声)、8(退格键)、 10(换行)和 13(回车)。所有其他字符代码均为 显示。太糟糕了,这个功能不会展开选项卡!

  • Int 10h AH=13h 写入字符串
    在某种程度上,这是函数 0Eh 的字符串版本。然而对于 一般用途 缺少选项卡扩展当然是一个限制。
    为什么有这么多参数?阿拉伯数字


选择哪个功能完全取决于您是哪种程序 写作。基本上,可以在控制台应用程序和完整应用程序之间进行选择 屏幕应用程序。CHKDSK.EXE 或 TREE.COM 等工具是控制台应用程序。 像QBASIC.EXE或 NE.COM 这样的程序是全屏应用程序。

控制台应用程序:

  • 不在乎使用颜色
  • 以线性方式将其输出写入屏幕上
  • 不会妨碍操作系统的输出重定向能力
  • 通常执行单个任务
  • 通常在眨眼间终止

面向屏幕的应用程序:

  • 使用适量的颜色受益匪浅
  • 在屏幕上徘徊,在它想要的地方写下它想要的东西
  • 无需担心输出重定向,因为上述内容很快就会足够 使此类输出不可读
  • 经常执行(太多)许多任务
  • 继续下去,直到你决定是时候退出了

控制台应用程序

只有 DOS 输出功能提供必需/推荐的重定向 能力。输出功能02h是完美的。即使它没有自己的错误 报告何时应发生错误(非常不可能),而输出 重定向,默认严重错误消息"中止、重试、失败? 看起来并没有太不合适。(如果这是一个全屏应用程序, 同样的信息会极大地扰乱屏幕。

; IN (ds:si) OUT ()
WriteStringDOS:
pusha
jmps    .b
.a:   mov     dl,al
mov     ah,02h
int     21h             ;DOS.DisplayCharacter -> AL
.b:   lodsb
test    al,al
jnz     .a
popa
ret

但是,有时您需要显示临时项目,例如:

  • 某种提示("-- 更多 --"、"准备好时按键..."等)
  • 一个运行计数器/百分比
  • 进度条

为了避免弄乱任何重定向的输出,最好不要使用DOS 这些临时项的输出函数。最好使用接下来的WriteStringBIOS代码。

全屏应用

现在输出重定向是你的敌人,所以不要使用任何 DOS 输出函数。 如果你不需要颜色,那么下一个代码片段适合你。它基本上 将选项卡扩展添加到 BIOS 电传打字功能。

; IN (ds:si) OUT ()
WriteStringBIOS:
pusha
mov     bx,0007h        ;Display page 0, Color if graphics mode
jmps    .b
.a:   cmp     al,9
je      .Tab
mov     ah,0Eh
int     10h             ;BIOS.Teletype
.b:   lodsb
test    al,al
jnz     .a
popa
ret
.Tab: mov     ax,0E20h        ;Start displaying space(s)
int     10h             ;BIOS.Teletype
mov     ah,03h
int     10h             ;BIOS.GetCursor -> CX DX
test    dl,7
jnz     .Tab            ;Column not yet multiple of 8
jmps    .b

大多数时候,一点颜色会创造奇迹。以下代码片段使用 BIOS 功能 09h 用于输出彩色字符和 BIOS 功能 0Eh 到 前进光标。一个很好的组合,让事情变得简单。

在文本视频模式下使用第一个:

; IN (bl,ds:si) OUT ()
WriteStringWithAttributeTVM:
pusha
mov     bh,0            ;Display page 0
jmps    .d
.a:   cmp     al,9
je      .Tab
cmp     al,13
ja      .b
mov     cx,1101_1010_0111_1111b
bt      cx,ax
jnc     .c              ;7,8,10,13 don't need the color
.b:   mov     cx,1
mov     ah,09h
int     10h             ;BIOS.WriteCharacterAndAttribute
.c:   mov     ah,0Eh
int     10h             ;BIOS.Teletype
.d:   lodsb
test    al,al
jnz     .a
popa
ret
.Tab: mov     cx,1            ;Start displaying colored space(s)
mov     ax,0920h        ;ASCII 20h is space character
int     10h             ;BIOS.WriteCharacterAndAttribute
mov     ah,0Eh
int     10h             ;BIOS.Teletype
mov     ah,03h
int     10h             ;BIOS.GetCursor -> CX DX
test    dl,7
jnz     .Tab            ;Column not yet multiple of 8
jmps    .d

在16彩色图形视频模式下使用第二个。它涉及更多 因为 BIOS 拒绝绘制背景颜色。

; IN (bl,ds:si) OUT ()
WriteStringWithAttributeGVM:
pusha
mov     bh,0            ;Display page 0
mov     bp,bx
jmps    .d
.a:   cmp     al,9
je      .Tab
cmp     al,13
ja      .b
mov     cx,1101_1010_0111_1111b
bt      cx,ax
jnc     .c              ;7,8,10,13 don't need the color
.b:   push    ax
mov     cx,1
mov     bx,bp
shr     bl,4            ;Get background color (high nibble)
mov     ax,09DBh        ;ASCII DBh is full block character
int     10h             ;BIOS.WriteCharacterAndAttribute
xor     bx,bp           ;Anticipate upcoming 'xor'
and     bl,15           ;Get foreground color (low nibble)
or      bl,128          ;Have BIOS 'xor' it
pop     ax
.c:   mov     ah,0Eh
int     10h             ;BIOS.Teletype
.d:   lodsb
test    al,al
jnz     .a
popa
ret
.Tab: mov     cx,1            ;Start displaying colored space(s)
mov     bx,bp
shr     bl,4            ;Get background color
mov     ax,0EDBh        ;ASCII DBh is full block character
int     10h             ;BIOS.Teletype
mov     ah,03h
int     10h             ;BIOS.GetCursor -> CX DX
test    dl,7
jnz     .Tab            ;Column not yet multiple of 8
jmps    .d

总结

  • 对于控制台应用程序,WriteStringDOSWriteStringBIOS过程绰绰有余3.
  • 对于全屏应用程序,WriteStringWithAttributeTVMWriteStringWithAttributeGVM过程平均提供34
  • DOS和BIOS都不足以处理图形视频 模式。要么编写自己的图形例程(不是微不足道的任务!),要么使用 第三方图形库。

1长时间延迟的功能请求:使光标前进 接收的复制计数为零。
2反转,不是实际问题。
3除非您选择的 BIOS 没有 TTY 的视频模式 支持。例如。许多 BIOS 在 VESA 视频模式下无法滚动。我什至来了 在无法在传统图形视频模式 12h 上写入具有功能 09h 的字符的 BIOS 上!
4可以直接在显存中写入是可能的,但需要更多 努力。

最新更新