了解用于在电传模式下输出字符的 nasm 程序集

use*_*234 6 bios nasm osdev bootloader x86-16

我正在阅读这篇关于操作系统编程的精彩剧本

http://www.cs.bham.ac.uk/~exr/lectures/opsys/10_11/lectures/os-dev.pdf

在第 12 页上有一个简单的引导加载程序。

如果我理解正确,显示的代码是您必须在 NASM 中编写的代码才能让 BIOS 打印出字符。

我不明白的是:

它说

we need interrupt 0x10 and to set ah to 0x0e (to indicate tele-type mode)
and al to the ASCII code of the character we wish to print.
Run Code Online (Sandbox Code Playgroud)

但第一条指令是:

mov ah , 0x0e ;int 10/ ah = 0eh -> scrolling teletype BIOS routine
Run Code Online (Sandbox Code Playgroud)

我不明白该行的评论。为什么第一行代码没有说:

mov ah, 0xeh
int 0x10
Run Code Online (Sandbox Code Playgroud)

如果那是你需要做的?

感谢帮助!

Mic*_*tch 8

虽然 Chrono 给了你一个答案,但我不太确定它是否能回答你的问题。您似乎在问为什么评论说的是一件事而代码似乎做的是另一件事。

基本前缀和后缀

几十年前,许多参考资料和一些反汇编程序使用与您今天可能看到的略有不同的默认符号来表示十进制、十六进制、八进制和二进制基数。他们将基数指定为值的最后一个字符(后缀)。常见的后缀有:

b = binary    10101010b      (decimal 170)    base 2
d = decimal   170d           (decimal 170) \  both d and t mean base 10 
t = decimal   170t           (decimal 170) /
h = hex       0AAh           (decimal 170)    base 16
o = octal     252o           (decimal 170)    base 8
Run Code Online (Sandbox Code Playgroud)

如果一个数字不包含字母字符,那么它被假定为以 10 为底的十进制数。所以这也适用:

no alphabetic character      170             decimal   170
Run Code Online (Sandbox Code Playgroud)

大多数汇编器会接受这些后缀中的大部分,但它们也会支持将基定义为前缀。如果一个值不是以字母字符结尾而是以 0 开头,后跟一个字母,则该字母表示基数。常见的前缀基是:

b = binary    0b10101010     (decimal 170)    base 2
d = decimal   0d170          (decimal 170) \  both d and t mean base 10 
t = decimal   0t170          (decimal 170) /
h = hex       0xAA           (decimal 170)    base 16
o = octal     0o252          (decimal 170)    base 8
Run Code Online (Sandbox Code Playgroud)

大多数现代汇编程序将支持指定为前缀或后缀的形式。某些汇编器可能不支持某些前缀和后缀,例如t.

如果您指定带有前缀基数的数字,则在整个文件中都使用前缀。如果您指定带有后缀基础的数字,则在整个文件中坚持使用后缀。您可以混合使用它们,但最好在文件中保持一致。

解释 int 10/ ah = 0eh

这是什么意思:

int 10/ ah = 0eh -> scrolling teletype BIOS routine
Run Code Online (Sandbox Code Playgroud)
  • int 10不包含字母,所以它是十进制 10(或十六进制 a)。
  • 0eh以字母结尾,不以 0 和字母开头,所以 h 是后缀。h表示十六进制。所以0eh十六进制 0e(或十进制 14)。

如果您要将其放入 BIOS 的汇编程序代码中,它将如下所示(使用十六进制后缀):

mov ah, 0eh      ; Decimal 14
int 0ah          ; Decimal 10. The 0 in front makes sure the assembler knows we don't mean register ah! 
Run Code Online (Sandbox Code Playgroud)

使用前缀(本例中为十六进制):

mov ah, 0xe      ; Decimal 14
int 0xa          ; Decimal 10 
Run Code Online (Sandbox Code Playgroud)

或者,如果您想使用十进制(无前缀或后缀):

mov ah, 14       ; Decimal 14
int 10           ; Decimal 10
Run Code Online (Sandbox Code Playgroud)

但是你现在可能会说嘿等等!这是错误的,因为 BIOS 视频中断是0x10(或16十进制)你是对的!我们刚刚了解到该评论是错误的,或者充其量是非常模棱两可的。评论应该说:

int 10h / ah = 0eh -> scrolling teletype BIOS routine
Run Code Online (Sandbox Code Playgroud)

您可能希望联系评论/代码的作者,让他们知道他们的评论不准确。他们写的代码是正确的。

如果汇编程序支持他们,我喜欢像前缀0x0b0o而不是后缀hbo因为它是可能的一些后缀,形成注册名称或其它标识符和符号。使用后缀时,如果您的值必须以字母开头(即:十六进制的 A 到 F),请在开头添加 0 以让汇编程序知道您表示的是一个值。例如AAh,必须写为0AAh,并且Bh必须写为0Bh

  • 啊,非常感谢!现在我突然觉得我凌驾于作者之上 ;D 感谢您的详尽解释!! (2认同)