实模式下的x86汇编语言:基础是如何完成的?

9

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

我懂得C语言和汇编语言,但后者比前者要少得多。即便如此,我似乎能够理解并基本掌握源文件中的代码。

然而,这个文件让我感到困惑。我现在意识到这是实模式,而不是保护模式。毋庸置疑,在我出生之前,受支持的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
请访问此网址:http://www.brokenthorn.com/Resources/OSDev20.html,然后搜索“he processors i/o address space at port 0x3f2,"。关于实模式与保护模式,个人电脑在进入保护模式之前会启动实模式。这与在旧处理器上运行有关。 - Carl Winder
啊,所以0x3f2是指第一个软盘驱动器的数字输出寄存器,并将0写入其中,这样就会执行“电机使能0”,我猜这会将其禁用。明白了。我在哪里可以找到有关我可以从BIOS控制的/所有/硬件的全面信息? - Louis
1
一些文章在这里:http://www.osdever.net/papers/ - Carl Winder
1
@Louis:小修正,那些地址和数据是通过硬件发送的,而BIOS是软件。 BIOS提供了API,因此如果您想控制硬件,就无需直接写入端口。 - user707582
我想,如果我只编写足够的代码来启动一个自定义保护模式操作系统,那么BIOS API就足够了,这意味着我不必过于深入地涉及其中? - Louis
可能是是否有x86 I / O端口分配的规范? 的重复问题 || https://dev59.com/5nA75IYBdhLWcg3wlqET - Ciro Santilli OurBigBook.com
2个回答

7

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

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


6
首先,欢迎来到实模式汇编的世界!您可能已经意识到,在实模式和保护模式之间,实际的汇编器几乎相同——主要区别在于操作数大小和内存布局/管理。
互联网上有一些关于实模式的资源,您只需要找到它们!一个非常重要的资源是Ralf Brown的中断列表(称为RBIL)(链接)——它提供了关于实模式编程中使用的各种中断的大量信息。另一个是BiosCentral的CMOS内存映射(链接),它描述了BIOS存储(或应该存储)在各种内存位置中的信息。
回答您发布的Linux代码中的一些问题: outb是将字节写入al并发送到dx端口的指令——0x3f2是软驱控制器端口。维基百科可以帮助您查找x86端口号的基本列表,但是您需要深入挖掘有关al位的实际格式的详细信息。
“哪些内存地址范围可用于在实模式下进行写入?”您应该研究INT 15h,AX=E820h——它返回描述哪些内存区域可用以及哪些是保留的内存映射。请注意:在查看中断时,重要的是要看它们有多“新”,因为旧的BIOS可能不支持它们。
许多硬件设备具有可编程中断(用于在需要关注硬件时服务硬件)。通常,在启动例程期间,BIOS将对初始分配进行排序,但是操作系统重新调整硬件中断以符合自己的目的或防止已知的不兼容性是很常见的。
最后一个提示:“似乎从空气中拉出像#0x3f2这样的数字。”答案是肯定的。许多Linux引导源代码都很可怕(是的,这只是我的意见),并且似乎会在没有任何有意义的解释的情况下添加看似随机的地址、端口号和其他位。坚持下去,查找其他实模式资源,最终它将变得清晰明了。哦,如果您遇到了一份全面的参考资料,请告诉每个人(因为目前还不存在)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接