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

BIOS VESA扩展:视频模式缓冲区指向空数组问题排查

VESA模式列表读取异常问题排查与解决

问题背景

通过INT 10h / AX=4F00h获取VESA基本信息块后,读取视频模式列表时出现异常:在QEMU和DOSBox中运行时,打印大量空值,首个非零值出现后内核崩溃,不符合VESA规范中模式列表以FFFFH结尾的预期。

相关代码

获取VESA基本信息块代码

PUSH cs                             ;
    POP es                              ;
    ;- perform VESA check               ;
    PUSH es                             ; some BIOSes destroy ES with this call
    MOV di, OFFSET DRV_VESA_infoBlock   ; ES:DI buffer for at least 256 bytes (512 for VBE v2.0+)
    MOV ax, 04F00H                      ;
    INT 10H                             ;
    POP es                              ;
                                        ;
    ;- check for errors                 ;
    CALL DRV_VESA_bioscallErrorCheck    ;
                                        ;
    ;-- check buffer signature          ;
    PUSH CS                             ;
    POP ES                              ;
    MOV di, OFFSET DRV_VESA_infoBlock   ; ES:DI = buffer
    MOV cx, 4                           ;
    MAC_IMMSTRING "VESA"                ; DS:SI = "VESA" signature needs to match!
    REPZ CMPSB                          ;
    JZ @@noErrors                       ;
    MAC_DPT_PRINTIMM "VESA buffer: signature does not match!"
    DRV_VESA_panic                      ;
                                        ;
    ;-- check vesa version              ;
    MOV ax, CS:[DRV_VESA_infoBlock].version
    CMP ax, 00102H                      ;
    JGE @@noErrors                      ;
    MAC_DPT_PRINTIMM "VESA: version too low"
    DRV_VESA_panic                      ;
@@noErrors:                             ;
...
...
...
                                        ;
    ALIGN DWORD                         ; some bioses might require the structs to be aligned
    DRV_VESA_infoBlock DRV_VESA_VBE_INFO_STRUCT  {}
    ALIGN DWORD                         ;
    DRV_VESA_modeInfo DRV_VESA_VBE_MODE_INFO_STRUCT {}

获取视频模式缓冲区指针代码

;-- get vesa modes buffer address   ;
    MOV ax, WORD PTR [bx].DRV_VESA_VBE_INFO_STRUCT.modesOff
    MOV si, ax
    MOV ax, WORD PTR [bx].DRV_VESA_VBE_INFO_STRUCT.modesSeg
    PUSH ax                             ;
    POP fs                              ;
                                        ;   

打印视频模式初步操作代码

@@displayModeLoop:                      ;
    MOV cx, WORD PTR fs:[si]            ;
    CMP cx, 0FFFFH                      ;
    JE @@displayModeEndLoop             ;
    MOV ax, cx                          ;
    CALL DPT_printNum                   ;
    ;--- get mode information           ;
    MOV ax, 04F01H                      ;
    INT 10H                             ;
    CALL DRV_VESA_bioscallErrorCheck    ;

    ADD si, 2                           ;
    JMP @@displayModeLoop               ;
@@displayModeEndLoop:                   ;   

已知信息

  • DPT_printNum功能正常,无故障
  • 移除BIOS函数调用后问题仍存在
  • 当前运行在实模式(RMODE)
  • 使用自定义引导加载程序

问题现象

在QEMU和DOSBox中运行时,打印大量空值(0),首个非零模式值出现后内核立即崩溃,模式列表未按VESA规范以FFFFH结尾。

问题原因分析

  1. bx寄存器未初始化:获取模式缓冲区指针时,直接使用[bx].DRV_VESA_VBE_INFO_STRUCT.modesOff,但未设置bx指向DRV_VESA_infoBlock的偏移地址,导致读取到错误的段/偏移值。
  2. 结构体定义不匹配:若DRV_VESA_VBE_INFO_STRUCT的定义与VESA规范不符(比如modesOff和modesSeg的偏移位置错误),会读取到无效的模式列表地址。
  3. 段寻址错误:模式列表的远指针(段:偏移)加载错误,导致访问非法内存区域,出现大量空值。
  4. 内存覆盖:自定义引导加载程序或内核代码可能覆盖了VESA信息块或模式列表所在的内存区域,导致数据损坏。
  5. BIOS调用参数缺失:执行INT 10h/AX=4F01h时未正确设置es:di指向模式信息结构体,且未保留当前模式号在cx中,触发非法操作。

解决方法

  1. 初始化bx寄存器:在获取模式缓冲区指针前,将bx设置为DRV_VESA_infoBlock的偏移地址:
    ; 添加到获取模式缓冲区指针的代码前
    MOV bx, OFFSET DRV_VESA_infoBlock
    
  2. 验证结构体定义:检查DRV_VESA_VBE_INFO_STRUCT是否严格符合VESA规范,确保modesOff(偏移0x14)和modesSeg(偏移0x16)的位置正确,结构体对齐符合要求。
  3. 修正BIOS调用参数:执行INT 10h/AX=4F01h时,设置es:di指向模式信息结构体,并保留当前模式号在cx中:
    @@displayModeLoop:                      ;
        MOV cx, WORD PTR fs:[si]            ;
        CMP cx, 0FFFFH                      ;
        JE @@displayModeEndLoop             ;
        MOV ax, cx                          ;
        CALL DPT_printNum                   ;
        ;--- get mode information           ;
        PUSH cs
        POP es                              ; ES指向模式信息结构所在段
        MOV di, OFFSET DRV_VESA_modeInfo    ; ES:DI指向模式信息缓冲区
        MOV ax, 04F01H                      ;
        INT 10H                             ; CX仍为当前模式号
        CALL DRV_VESA_bioscallErrorCheck    ;
    
        ADD si, 2                           ;
        JMP @@displayModeLoop               ;
    @@displayModeEndLoop:                   ;   
    
  4. 排查内存覆盖问题:确保引导加载程序和内核代码未占用VESA信息块或模式列表的内存区域,可通过BIOS内存映射确认可用区域,或调整结构体的存储位置。
  5. 调试段地址:添加代码打印modesSeg和modesOff的值,验证是否为有效内存地址,确认fs段寄存器设置正确。

内容的提问来源于stack exchange,提问作者Maximilian Wittmer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 01:21:06