我目前正在阅读第一个Linux内核源代码中的boot.s
文件(假设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文档猜测这个场景将'stop motor'字节作为第一个参数传递,并将软盘驱动器端口号作为第二个参数。
这个界面是否由BIOS提供?还是直接通过软驱?我假设BIOS对所有基本设备的基本操作都有节俭的“驱动程序”。
这就是我难倒的地方:似乎像#0x3f2
这样的数字正在被掏空。它们显然是硬件端口号或其他东西。这个文件上撒有这样的数字,没有解释他们所指的是什么。在哪里可以找到一个全面的参考资料,显示他们可以从实模式接收的所有硬件端口和控制编号?此外,似乎文件在整个启动过程中使用硬编码的内存地址在内存中移动内核。在哪里可以找到有关在实模式下可以写入的内存地址范围的指南?
我还阅读了Linus关于重新编程中断的评论,以避免BIOS与内部硬件中断之间的冲突。我不会撒谎,这是我的头脑。
帮助会很棒;如果你想知道,谷歌似乎很少涉及这个话题。
答案 0 :(得分:7)
30年前IBM发布了第一台IBM PC时,这些地址都是一成不变的。 0x3f0是主软盘控制器寄存器的第一个地址。地址列表为available here。
IBM设计团队的一个不寻常的举动是,他们将机器从标准的现成部件组合在一起。大多数芯片来自英特尔,软盘控制器是NEC设计。无意中确保每个人可以构建克隆。这些克隆使用相同的地址来确保软件兼容性,将IBM的选择转变为可以硬编码的行业标准。
答案 1 :(得分:6)
首先,欢迎来到realmode汇编程序的世界! 您可能已经意识到实际的汇编程序在realmode和protected模式之间大致相同 - 主要区别在于操作数大小和内存布局/管理。
互联网上有一些现实模式的资源 - 你只需要追捕它们!一个非常重要的资源是Ralf Brown's Interrupt List(称为RBIL) - 它提供了很多关于realmode编程中使用的各种中断的信息。另一个是BiosCentral的CMOS memory map,它描述了BIOS在各种存储位置存储(或应该存储)的信息。
回答您发布的Linux代码的一些问题:
outb
是将al
中的字节写入端口dx
的指令 - 0x3f2是软盘控制器端口。 Wikipedia可以帮助您了解x86端口号的基本列表,但您必须深入了解有关al
位的实际格式的详细信息。
在realmode期间可以写入哪些内存地址范围?
你应该对INT 15h,AX = E820h做一些研究 - 它会返回一个内存映射,描述可以使用哪些内存区域以及保留哪些内存区域。但需要注意的是:在查看中断时,重要的是要了解它们是多么“新”,因为较旧的BIOS可能不支持它们。
...重新编程中断以避免BIOS与内部硬件之间发生冲突 中断
许多硬件设备都有可编程中断(用于在需要注意时为硬件提供服务)。通常,BIOS会在其启动例程中对初始分配进行排序,但操作系统为了自己的目的而重新调整硬件中断或防止已知的不兼容性并不罕见。
最后一点:it seems that numbers like #0x3f2 are being pulled out of thin air
。答案是肯定的。许多Linux启动源都是可怕的(是的,这只是我的意见)并且确实看起来像是随机地址,端口号和其他位而没有任何有意义的解释。坚持下去,查找其他现实资源,最终它会有意义。哦,如果你遇到综合参考 - 告诉所有人(因为它目前不存在)。