早期的BIOS怎么能使用CALL呢?

2024-04-21

我纯粹是出于爱好原因,试图理解 PC 中的一些低级代码。我为随机的旧千兆字节 MB 下载了一个过时的 BIOS ROM 映像(https://www.gigabyte.com/Motherboard/GA-8I845GE775-G-rev-10/support#support-dl-bios https://www.gigabyte.com/Motherboard/GA-8I845GE775-G-rev-10/support#support-dl-bios),它已经快 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 to 0x70: https://wiki.osdev.org/CMOS#CMOS_Registers https://wiki.osdev.org/CMOS#CMOS_Registers

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


有2种情况:

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

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

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

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

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

早期的BIOS怎么能使用CALL呢? 的相关文章

  • elf .rel.text 部分中 R_386_32/R_386_PC32 的含义

    为了理解重定位的概念 我编写了一个简单的 chk c 程序 如下所示 1 include
  • 推送 64 位 intel osx

    我想将 64 位地址压入堆栈 如下所示 asm pushq 0x1122334455667788 但我得到编译错误 我只能按以下方式推送 asm pushq 0x11223344 有人可以帮助我理解我的错误吗 我是装配新手 所以如果我的问题
  • 无法拦截Android应用程序的流量

    最近 我正在尝试测试和拦截来自开发的应用程序的流量罗莫比尔 我设置了一个代理burp 当然 我已经在我的设备上安装了 burp 证书 因此我可以拦截设备上的其他应用程序 但我无法在 burp suite 上看到相关应用程序的流量 相反 该应
  • 如何调试 iOS 应用程序在启动时崩溃,仅在程序集文件中设置断点

    我遇到了当前正在开发的应用程序的问题 问题是应用程序在启动时在后台运行一段时间后崩溃 并且仅在这种情况下 在应用程序被杀死时启动应用程序不会导致调试器或手机崩溃 无论是否进行调试 在后台启动应用程序大约 5 10 分钟都不会导致崩溃 在后台
  • x86 平台中的 KVM 影子页表处理

    据我了解 在没有硬件支持来宾虚拟到主机物理地址转换的处理器上 KVM 使用影子页表 当来宾操作系统修改其页表时 会构建和更新影子页表 硬件中有没有专门的指令 以x86为参考 来修改页表 除非有特殊说明 否则不会对VMM 造成陷阱 Linux
  • ARM 调用约定是否允许函数不将 LR 存储到堆栈中?

    正如标题所示 我在理解 ARM 架构的调用约定时遇到问题 特别是 我仍然很难知道当你调用子程序时 LR 寄存器会发生什么 我认为 当您进入子程序时 处理 LR 寄存器的最明显 最安全的方法是将其存储到堆栈中 但该行为没有出现在文档中 因此我
  • 为什么这个 C++ 包装类没有被内联掉?

    EDIT 我的构建系统出了问题 我还在弄清楚到底是什么 但是gcc产生了奇怪的结果 尽管它是 cpp文件 但是一旦我使用了g 然后它按预期工作 对于我一直遇到麻烦的事情来说 这是一个非常精简的测试用例 其中使用数字包装类 我认为会内联 使我
  • 生成唯一硬件 ID 的可靠方法

    问题 我必须为每个联网客户端提供唯一的 ID 例如 一旦客户端软件安装在目标计算机上 它 ID 应该持续存在 并且如果在同一台计算机和相同的操作系统安装上重新安装软件 它应该继续存在 如果以大多数方式修改硬件配置 除了更改主板 它不应该改变
  • 为什么我可以使用 ret 退出 main?

    我即将弄清楚程序堆栈到底是如何设置的 我了解到用以下方式调用该函数 call pointer 实际上等同于 mov register pc programcounter add register 1 where 1 is one instr
  • 为 Visual Studio 应用程序设置平台目标的目的是什么?

    对于任何 VS 项目 都可以在该项目的构建属性中设置平台目标 您可以将其设置为任何 CPU x86 x64 或 Itanium 我的问题是 如果我将此值设置为 x86 是否意味着我无法在 x64 计算机上运行该项目 如果是这样 为什么还要使
  • Clang 使用 -nostdlib 生成崩溃代码

    我正在尝试为可执行文件设置自己的运行时环境 但无法使用 clang v3 4 1ubuntu1 目标 x86 64 pc linux gnu 来生成没有段错误的可执行文件 我已将问题简化为以下内容 如果我有一个文件 crt1 c 除了满足
  • 如何让c代码执行hex机器代码?

    我想要一个简单的 C 方法能够在 Linux 64 位机器上运行十六进制字节码 这是我的 C 程序 char code x48 x31 xc0 include
  • orpd等SSE2指令有什么意义?

    The orpd指令是 压缩双精度浮点值的按位逻辑或 这不是做完 全相同的事情吗por 按位逻辑或 如果是这样 拥有它还有什么意义呢 请记住 SSE1orps https www felixcloutier com x86 orps首先 实
  • 汇编-符号标志和奇偶校验标志

    我不明白什么时候设置标志标志 什么时候设置奇偶校验 据我所知 符号标志表示运算结果的符号 0表示正数 1表示负数 那么为什么在下一个代码中 mov al 5 sub al 124 SF为零 结果是负数 关于PF 为什么a和b中设置了PF a
  • 为什么不能执行 mov [eax], [ebx] [重复]

    这个问题在这里已经有答案了 我可以做这个 mov eax ebx 和这个 mov eax ebx 甚至这个 mov eax ebx 但不是这个 错误C2415 mov eax ebx 只是wtf 为什么 它与 ptr1 ptr2 相同 为什
  • 在 x86 Intel VT-X 非根模式下,是否可以在每个指令边界传递中断?

    除了不将中断传送到虚拟处理器的某些正常指定条件 cli if 0 等 之外 客户机中的所有指令实际上都是可中断的吗 也就是说 当传入的硬件中断先传递给 LAPIC 然后传递给处理器时 据说会发生一些内部魔法 将其转换为虚拟中断给来宾 使用虚
  • Visual Studio 2017 上的简单装配程序

    386 model flat c stack 100h printf PROTO arg1 Ptr Byte data msg1 byte Hello World 0Ah 0 code main proc INVOKE printf ADD
  • 为什么 Visual Studio 使用 xchg ax,ax

    我正在查看程序的反汇编 因为它崩溃了 并注意到很多 xchg ax ax 我用谷歌搜索了一下 发现它本质上是一个 nop 但是为什么 Visual Studio 会执行 xchg 而不是 noop 该应用程序是一个C NET3 5 64位应
  • 减法进位标志

    我正在使用 MASM32 有了这个代码 mov eax 5 sub eax 10 CF 状态标志将被设置 但使用我的铅笔和纸 我实际上看到 MSB 没有任何进位 是的 我知道从较少的数字中减去大的数字集CF 但我想知道为什么 因为使用这段代
  • 用于预乘 ARGB 的 SSE alpha 混合

    我正在尝试编写一个支持 SSE 的 alpha 合成器 这就是我想出的 首先 混合两个 4 像素向量的代码 alpha blend two 128 bit 16 byte SSE vectors containing 4 pre multi

随机推荐