【问题标题】:How can early BIOS use CALL?早期的 BIOS 如何使用 CALL?
【发布时间】:2019-09-17 18:12:36
【问题描述】:

我纯粹是出于爱好,试图理解 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 结尾。这怎么可能,call的返回地址存放在哪里?

还是我误解了从端口0x71 返回的值?我参考了这两个文件:

写0x8f到0x70的意义:https://wiki.osdev.org/CMOS#CMOS_Registers

随后从0x71读取的值的含义:http://www.bioscentral.com/misc/cmosmap.htm

【问题讨论】:

  • 下载并阅读 Intel CPU 文档,尤其是关于 CPU 在开机时的状态。
  • @Someprogrammerdude 有什么特别的吗?它确认 CR0 的最后一位应为零(CR0 = 60000010H)和 SS:SP = 0000:0000(第 3A 卷表 9-1)。我认为更多的是关于端口(即其他芯片)而不是 CPU 状态。
  • 版权持续 50 年或更长时间,因此您实际上侵犯了某人的知识产权。
  • 您使用了哪个 BIOS 二进制文件?链接中的两个给了我不同的反汇编。
  • @MargaretBloom 我参加了 F1。

标签: assembly x86 reverse-engineering bios


【解决方案1】:

有两种情况:

a) “冷启动”(例如,当计算机未运行而您将其打开时)。在这种情况下;不会初始化内存控制器,不会设置关机状态,jne 0xf488 会导致代码跳转到其他地方,call 不会被执行。

b) “热启动”(例如,当您在计算机已经运行后重置计算机时)。在这种情况下;内存控制器仍在初始化(从之前发生“冷启动”时开始),将设置关机状态,jne 0xf488 不会做任何事情,call 将被执行(但这很好,因为内存控制器已初始化)。

假设计算机开机时 CMOS 关机状态为零...

没有。关闭状态字节值是(根据 Ralph Brown 的中断列表):

  • 0x00 = 软件复位或意外复位
  • 0x01 = 在虚拟模式下检查内存大小后重置
  • 0x02 = 在实/虚拟模式下成功进行内存测试后重置
  • 0x03 = 在实/虚拟模式下内存测试失败后重置
  • 0x04 = INT 0x19 重启
  • 0x05 = 刷新键盘并跳转。 0x0040:0x0067
  • 0x06 = 重置(在虚拟模式下成功测试后)
  • 0x07 = 重置(在虚拟模式下测试失败后)
  • 0x08 = 在 protected=mode RAM 测试期间由 POST 使用
  • 0x09 = 用于 INT 0x15/0x87(块移动)支持
  • 0x0A = 通过 JMP via 恢复执行。 0x0040:0x0067
  • 0x0B = 通过 IRET 恢复执行。 0x0040:0x0067
  • 0x0C = RETF 通过恢复执行。 0x0040:0x0067
  • 0x0D 到 0xFF = 执行上电复位(“冷启动”)

注意:拉尔夫布朗的中断列表已经很久没有维护了。我希望其中一些是旧的和/或仅适用于一些非常旧的计算机(例如 80286,除了重置之外没有任何方法可以离开保护模式)。

【讨论】:

  • 我也是这么想的。 (尽管我可能对 (b) 案例有一个后续问题。)让我感到困惑的是关机状态。在冷启动中,它的“未设置”值是多少?如果它为零,那么在or al, al 和jne 之后的E 标志应该是1,按照我在问题中突出显示的代码路径,或者我错了吗?
  • 非常感谢!事实证明我的来源(见问题)不如这个列表,并且可能具有误导性(它说:“00h = 开机或软复位”,我将其解释为开机由 0x00 发出信号)。
猜你喜欢
  • 2017-08-15
  • 2014-12-28
  • 1970-01-01
  • 2010-12-25
  • 2010-11-18
  • 1970-01-01
  • 1970-01-01
  • 2019-05-24
  • 1970-01-01
相关资源
最近更新 更多