9

我目前正在阅读boot.s第一个 Linux 内核的源文件(假设 0.01 确实是第一个公开版本)。

我知道 C 和 ASM,后者比前者少得多。即便如此,我似乎能够理解并基本上掌握源文件中的代码。

这个文件让我很困惑。我现在意识到这是因为它处于实模式,而不是保护模式。不用说,我以前从未见过以实模式编写的 ASM 代码。保护模式是 x86 操作系统在我出生之前运行的事实上的模式,所以这是意料之中的。

这是我想更好地理解的例程:

/*
 * This procedure turns off the floppy drive motor, so
 * that we enter the kernel in a known state, and
 * don't have to worry about it later.
 */
kill_motor:
    push dx
    mov dx,#0x3f2
    mov al,#0
    outb
    pop dx
    ret

查找outb,我发现它用于将字节传递到计算机上的端口。我将根据 C 文档大胆猜测,这种情况将“停止电机”字节作为第一个参数传递,并将软盘驱动器端口号作为第二个参数传递。

这个接口是BIOS提供的吗?还是直接通过软驱?我假设 BIOS 具有节俭的“驱动程序”,用于所有基本设备的非常基本的操作。

这就是我被难住的地方:似乎像这样的数字#0x3f2是凭空捏造的。它们显然是硬件端口号或其他东西。这个文件到处都是这样的数字,没有解释他们指的是什么。我在哪里可以找到一个全面的参考资料,其中显示了他们可以从实模式接收的所有硬件端口和控制号?此外,该文件似乎在整个引导过程中使用硬编码的内存地址在内存中移动内核。我在哪里可以找到关于在实模式下可以写入哪些内存地址范围的指南?

我还阅读了 Linus 关于重新编程中断以避免 BIOS 和内部硬件中断之间的冲突的评论。我不会撒谎,那是在我头上。

帮助会很大;如果您想知道的话,谷歌似乎对这个话题很少。

4

2 回答 2

7

这些地址是 30 年前 IBM 发布第一台 IBM PC 时一成不变的。0x3f0 是主软盘控制器寄存器的第一个地址。此处提供了地址列表。

IBM 设计团队的一个不同寻常的举动是,他们用标准的现成零件将机器组装在一起。大多数芯片来自英特尔,软盘控制器是 NEC 设计的。无意中确保每个人都可以构建克隆。这些克隆使用相同的地址来确保软件兼容性,将 IBM 的选择变成可以硬编码的行业标准。

于 2012-01-17T12:22:09.140 回答
6

首先,欢迎来到实模式汇编器的世界!您可能已经意识到,实模式和保护模式之间的实际汇编程序大致相同——主要区别在于操作数大小和内存布局/管理。

互联网上有一些实模式资源——你只需要找到它们!一个非常重要的资源是Ralf Brown 的中断列表(称为 RBIL)——它提供了大量关于实模式编程中使用的各种中断的信息。另一个是 BiosCentral 的CMOS 内存映射,它描述了 BIOS 在各个内存位置存储(或应该存储)的信息。

要回答有关您发布的 Linux 代码的一些问题: outb是将字节写入al端口的指令dx- 0x3f2 是软盘控制器端口。Wikipedia可以帮助您了解 x86 端口号的基本列表,但您必须四处寻找有关al位的实际格式的详细信息。

在实模式下可以写入哪些内存地址范围?

您应该对 INT 15h, AX=E820h 进行一些研究 - 它返回一个内存映射,描述可以使用哪些内存区域以及保留哪些内存区域。但请注意:在查看中断时,重要的是要了解它们的“新”程度,因为旧的 BIOS 可能不支持它们。

...重新编程中断以避免 BIOS 和内部硬件中断之间的冲突

许多硬件设备都有可编程中断(用于在需要注意时为硬件提供服务)。通常,BIOS 会在其启动例程期间整理出初始分配,但操作系统为了自己的目的或防止已知的不兼容而重新调整硬件中断并不罕见。

最后一点:it seems that numbers like #0x3f2 are being pulled out of thin air。答案是肯定的。很多 Linux 引导源代码都非常糟糕(是的,这只是我的看法),并且似乎在没有任何有意义的解释的情况下散布看似随机的地址、端口号和其他位。坚持下去,查找其他实模式资源,最终它会变得有意义。哦,如果您遇到全面的参考- 告诉每个人(因为它目前不存在)。

于 2012-01-17T12:42:05.293 回答