我纯粹是出于爱好原因,试图理解 PC 中的一些低级代码。我为随机的旧 Gigabyte MB ( https://www.gigabyte.com/Motherboard/GA-8I845GE775-G-rev-10/support#support-dl-bios ) 下载了一个过时的 BIOS ROM 镜像,它已经有将近 15 年的历史了,所以我希望它不会损害任何人的知识产权。我将使用此文件作为引用。
我一开始就被绊倒了。这些似乎是处理器上电后看到的第一条指令:
f000:fff0 ljmp 0xf000:0xe05b
f000:e05b jmp 0xf46c
f000:f46c cli
f000:f46d cld
f000:f470 smsw ax ; read CR0
f000:f473 test al, 1 ; test Protected Mode Enable
f000:f475 je 0xf480
[assuming PE is zero – jump:]
f000:f480 jmp 0xe043
f000:e043 mov al, 0x8f
f000:e045 out 0x70, al ; CMOS controller: disable NMI, set index 0xf
f000:e047 out 0xeb, al ; this port is presumably unoccupied: just a delay mechanism
f000:e049 in al, 0x71 ; read 0xf (CMOS Shutdown Status)
f000:e04b out 0xeb, al ; more delay
f000:e04d or al, al
f000:e04f jmp 0xf483
f000:f483 jne 0xf488
[assuming status = 0 (Power on or soft reset) – pass:]
f000:f485 call 0x4dee
假设计算机开机时 CMOS 关闭状态为零,BIOS 将在 f000:f485
处发出调用。在早期,我们不会尝试检测是否存在任何 RAM。堆栈段和堆栈指针也尚未设置。 f000:f485
处的代码确实看起来像一个函数,并以 ret
结尾。这怎么可能,调用
在哪里存储返回地址?
或者我是否误解了从端口0x71
返回的值?我引用了这两个文档:
将0x8f
写入0x70
的含义:https://wiki.osdev.org/CMOS#CMOS_Registers
随后从0x71
读取的值的含义:http://www.bioscentral.com/misc/cmosmap.htm
最佳答案
有2种情况:
a)“冷启动”(例如,当计算机未运行而您将其打开时)。在这种情况下;内存 Controller 不会被初始化,关闭状态不会被设置,jne 0xf488
会导致代码跳转到其他地方,call
也不会被处决。
b) “热启动”(例如,当您在计算机已经运行后重置计算机时)。在这种情况下;内存 Controller 仍处于初始化状态(从之前发生“冷启动”时开始),将设置关闭状态,jne 0xf488
不会执行任何操作,call
将被执行(但这没关系,因为内存 Controller 已初始化)。
Assuming the CMOS shutdown status is zero upon powering the computer on...
没有。关闭状态字节值为(根据 Ralph Brown 的中断列表):
- 0x00 = 软件重置或意外重置
- 0x01 = 在虚拟模式下检查内存大小后重置
- 0x02 = 在实/虚拟模式下成功进行内存测试后重置
- 0x03 = 在实/虚拟模式下内存测试失败后重置
- 0x04 = INT 0x19 重新启动
- 0x05 = 齐平键盘并跳转。 0x0040:0x0067
- 0x06 = 重置(虚拟模式测试成功后)
- 0x07 = 重置(在虚拟模式下测试失败后)
- 0x08 = 在 protected =模式 RAM 测试期间由 POST 使用
- 0x09 = 用于 INT 0x15/0x87( block 移动)支持
- 0x0A = 通过 JMP 恢复执行。 0x0040:0x0067
- 0x0B = 通过 IRET 恢复执行。 0x0040:0x0067
- 0x0C = 通过 RETF 恢复执行。 0x0040:0x0067
- 0x0D 至 0xFF = 执行加电复位(“冷启动”)
注意:Ralph Brown 的中断列表已经很久没有维护了。我预计其中一些是旧的和/或仅适用于一些非常旧的计算机(例如 80286,除了重置之外没有任何方法可以离开保护模式)。
关于assembly - 早期BIOS如何使用CALL?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57970485/