You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现用于视频输出的基础x86中断管理器?相关技术疑问

我原本打算逆向分析加载到内存中的BIOS模块,不过先在此咨询问题。我写了一个极简bootloader(可在屏幕输出'e'):

mov ah, 0x0e
mov al, 'e'
int 0x10
jmp $
times 510-($-$$) db 0
dw 0xaa55

用nasm编译后,在VirtualBox中创建虚拟软盘的命令:

head -c 1474560 /dev/zero > bootloader.vfd  
dd status=noxfer conv=notrunc if=test.bin of=bootloader.vfd

生成的镜像可正常运行,现在我想尝试向输出设备渲染图形,遇到几个瓶颈问题,以下是对应的解决方法:

问题解答

1. 如何覆盖BIOS已设置的IVT?

实模式下IVT(中断向量表)位于内存0x00000到0x003FF区域,每个中断向量占4字节(低2字节是偏移地址,高2字节是段地址)。覆盖步骤:

  • 执行cli指令关闭中断,避免修改过程中触发中断引发异常
  • 计算目标中断的向量地址:中断号 * 4,比如替换int 0x10的话,地址就是0x10 * 4 = 0x40
  • 将自定义中断处理程序的偏移地址写入该地址的低2字节,段地址写入高2字节
  • 执行sti指令重新开启中断
    注意:替换前建议保存原向量内容,后续可能需要恢复;自定义处理程序必须遵循x86中断调用约定,最后用iret指令返回。

2. 如何通过编程方式选择可用的显示设备?

实模式下可借助BIOS中断int 0x10完成显示设备的检测与模式设置:

  • 调用int 0x10且ah=0x0F,可获取当前显示模式:返回后al存储模式号,ah存储列数,bh存储当前页号
  • 调用int 0x10且ah=0x00,al传入目标模式号即可设置显示模式(比如0x13是320x200 256色图形模式,0x03是80x25文本模式)
  • 检测可用设备时,可枚举标准显示模式,调用int 0x10 ah=0x00尝试设置,成功则说明该模式对应的设备可用;也可调用int 0x11获取设备列表,其中位4-5表示显示适配器类型(00=CGA/EGA/VGA,01=MDA,10=CGA,11=EGA)

3. 如何确定哪些内存区域可用于存放代码/堆?

最可靠的方式是通过BIOS中断int 0x15的ah=0xE820功能获取内存映射(支持扩展内存):

  • 初始化寄存器:eax=0xE820,ebx=0,ecx=24,edx=0x534D4150(SMAP签名),es:di指向一个24字节的缓冲区
  • 调用int 0x15,成功后缓冲区会填充内存区域的基地址、长度、类型(1=可用,2=保留等)
  • 循环调用直到ebx=0,收集所有标记为“可用”的内存区域
    另外,实模式下前640KB(0x00000到0x9FFFF)是常规内存,其中0x00000-0x003FF是IVT,0x00400-0x004FF是BIOS数据区(BDOS),剩余大部分区域可用;注意bootloader加载在0x7C00,需避开该区域及周边空间。

实现用于视频输出的基础x86中断管理器

以替换int 0x10(BIOS视频中断)为例,实现步骤如下:

  1. 保存原中断向量:读取IVT中int 0x10对应的4字节地址,存储到内存安全区域,方便后续调用原BIOS功能或恢复
  2. 编写自定义中断处理程序:
    • 开头用pusha和pushf保存所有寄存器状态(避免破坏调用方环境)
    • 根据ah的值判断要处理的功能:比如ah=0x0E是电传输出,可自行实现文本输出逻辑;对于不需要自定义处理的功能,直接跳转到原BIOS中断处理程序执行
    • 处理完成后用popf和popa恢复寄存器,最后执行iret返回
  3. 更新IVT向量:按照前面覆盖IVT的方法,将自定义处理程序的段地址和偏移地址写入int 0x10对应的IVT位置
  4. 功能测试:调用int 0x10的相关功能,验证自定义处理程序是否正常工作

内容的提问来源于stack exchange,提问作者Gabriel Reyes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 06:15:29