好的,这就是我的意思:
假设您想编写自己的可启动代码。
此外,您的代码将非常简单。
事实上,它是如此简单,以至于它只包含一个指令。
您的可启动代码将写入一个字节或字或双字或任何内容到外围设备上的寄存器或 RAM 位置,而不是主 RAM 或 CPU 寄存器。
您如何找出 BIOS/UEFI 分配给该外围内存位置的地址?
下面是一个更具体的例子:
我的可启动代码的第一个也是唯一的指令会将数字 11H 写入位于声卡上的寄存器。
如果 BIOS/UEFI 初始化代码正常工作,则该声卡寄存器应映射到 CPU 的内存空间和/或 IO 空间。
我需要找到该地址才能完成该写入。
我如何找到它?
这是真正的操作系统在某些时候必须做的事情。
当您在Windows中打开控制面板/设备管理器时,您会看到那里列出的外围设备的所有内存范围。
在某些时候,Windows必须查询BIOS/UEFI才能找到此数据。
再说一遍,这是怎么做到的?
编辑:
这是我编写这个可启动汇编程序的尝试:
BITS 16
ORG 100h
start:
;I want to write a byte into a register on the sound card or NIC or
;whatever. So, I'm using a move instruction to accomplish that where X
;is the register's memory mapped or IO mapped address.
mov X,11h
times 510 - ($ - $$) db 0
dw 0xaa55
我应该为 X 输入什么数字?如何找到此外设寄存器的地址?
如果要使用一条指令执行此操作,只需从Windows设备管理器获取设备的地址即可。但是,如果您想以"正确"的方式执行此操作,则需要扫描PCI总线以找到要编程的设备,然后读取设备的基址寄存器(BAR(以查找其MMIO范围。这就是Windows所做的;它不查询 BIOS。
要查找要访问的设备,请扫描 PCI 总线以查找该设备。设备在PCI总线上通过其"BDF"(总线/设备/功能的缩写(寻址。设备由供应商 ID 和供应商分配的设备 ID 标识。
读取每个 BDF 的偏移量 0 和 2 以获取供应商 ID 和设备 ID。找到要编程的设备后,读取正确的 32 位 BAR 值,偏移量在 10h 和 24h 之间。您需要知道哪个 BAR 包含您要编程的寄存器,该寄存器特定于您正在使用的设备。
本文介绍如何访问 PCI 配置空间,并提供 C 语言的示例代码,演示如何扫描 PCI 总线。 http://wiki.osdev.org/PCI