英文:
BIOS VESA-extensions: video-modes buffer pointing to an empty array
问题
我获取了基本的VESA信息块,使用INT 10h / AX=4F00h
。
PUSH cs ;
POP es ;
;- 执行VESA检查 ;
PUSH es ; 一些BIOS在这个调用中破坏ES
MOV di, OFFSET DRV_VESA_infoBlock ; ES:DI 缓冲区至少需要256字节(VBE v2.0+需要512字节)
MOV ax, 04F00H ;
INT 10H ;
POP es ;
;
;- 检查错误 ;
CALL DRV_VESA_bioscallErrorCheck ;
;
;-- 检查缓冲区签名 ;
PUSH CS ;
POP ES ;
MOV di, OFFSET DRV_VESA_infoBlock ; ES:DI = 缓冲区
MOV cx, 4 ;
MAC_IMMSTRING "VESA" ; DS:SI = "VESA" 签名需要匹配!
REPZ CMPSB ;
JZ @@noErrors ;
MAC_DPT_PRINTIMM "VESA buffer: signature does not match!"
DRV_VESA_panic ;
;
;-- 检查VESA版本 ;
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 ; 一些BIOS可能需要对齐结构体
DRV_VESA_infoBlock DRV_VESA_VBE_INFO_STRUCT {}
ALIGN DWORD ;
DRV_VESA_modeInfo DRV_VESA_VBE_MODE_INFO_STRUCT {}
然后,我获取了视频模式缓冲区的指针。
;-- 获取VESA模式缓冲区地址 ;
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 ;
;--- 获取模式信息 ;
MOV ax, 04F01H ;
INT 10H ;
CALL DRV_VESA_bioscallErrorCheck ;
ADD si, 2 ;
JMP @@displayModeLoop ;
@@displayModeEndLoop: ;
-
DPT_printNum 在这里很可能没有问题(它在许多其他地方都有效)。
-
我已经尝试过删除BIOS函数调用,它不是导致问题的原因。
-
我仍然在RMODE中。
-
我正在使用自己的引导加载程序。
相关文件位于此处:https://github.com/Wittmaxi/maxos/tree/master/kernel/drivers/graphics
当我运行这段代码(无论是在QEMU还是在DOSBox中),会打印出许多空数组索引。一旦打印出第一个非零值,内核就会崩溃。我预期该数组应该(如在http://www.ctyme.com/intr/rb-0273.htm中指定)充满了显示模式代码,并以单词"FFFF"结束。
英文:
I get the basic VESA information block with INT 10h / AX=4F00h
.
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 {}
I then get the pointer to the video-modes buffer
;-- 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 ;
;
I then (as preliminary step) print out all the video modes I have
@@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 is most certainly not at fault here (it worked in many other places)
-
I already tried removing the BIOS-function-call, it is not what causes the issue
-
I am still in RMODE
-
I am using my own bootloader
The relevant files are here: https://github.com/Wittmaxi/maxos/tree/master/kernel/drivers/graphics
When I run this code (both in QEMU and in DOSBox), a lot of empty array indexes are printed. As soon as the first non-zero value is printed, the kernel panics.
I expect the array to be (as specified <http://www.ctyme.com/intr/rb-0273.htm>) full of display-mode-codes and ended with the word "FFFF"
答案1
得分: 2
> 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
错误地从 DS 相对于 VideoModePtr 检索 VbeInfoBlock,实际上应该相对于 CS,甚至 ES,因为你复制了 CS 到 ES。
;-- 检查缓冲区标识 ;
PUSH CS ;
POP ES ;
MOV di, OFFSET DRV_VESA_infoBlock ; ES:DI = 缓冲区
MOV cx, 4 ;
MAC_IMMSTRING "VESA" ; DS:SI = "VESA" 标识需要匹配!
REPZ CMPSB ;
JZ @@sigMatch ;
MAC_DPT_PRINTIMM "VESA 缓冲区:标识不匹配!"
DRV_VESA_panic ;
@@sigMatch: ;
;-- 检查 VESA 版本 ;
MOV ax, ES:[DRV_VESA_infoBlock].version
CMP ax, 00102H ;
JGE @@versionOk ;
MAC_DPT_PRINTIMM "VESA: 版本太低"
DRV_VESA_panic ;
@@versionOk: ;
;-- 获取 VESA 模式缓冲区地址 ;
MOV si, ES:[DRV_VESA_infoBlock].modesOff
MOV fs, ES:[DRV_VESA_infoBlock].modesSeg
我在 ModeInfoBlock 中找到了一个额外的问题。你没有包括偏移量 29 处的 NumberOfImagePages 字段。
英文:
> 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
You are erroneously retrieving the VideoModePtr relative to DS where in fact the VbeInfoBlock was placed in the code segment, so relative to CS, or even ES since you copied CS to ES.
;-- 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 @@sigMatch ;
MAC_DPT_PRINTIMM "VESA buffer: signature does not match!"
DRV_VESA_panic ;
;
@@sigMatch: ;
;-- check vesa version ;
MOV ax, ES:[DRV_VESA_infoBlock].version
CMP ax, 00102H ;
JGE @@versionOk ;
MAC_DPT_PRINTIMM "VESA: version to low"
DRV_VESA_panic ;
;
@@versionOk: ;
;-- get vesa modes buffer address ;
MOV si, ES:[DRV_VESA_infoBlock].modesOff
MOV fs, ES:[DRV_VESA_infoBlock].modesSeg
I have found an additional problem in your ModeInfoBlock. You did not include the NumberOfImagePages field at offset 29.
答案2
得分: 0
在哪里设置BX
用于 ;-- 获取VESA模式缓冲区地址
?
;--- 获取模式信息
需要 ES:DI
指向一个 DRV_VESA_VBE_MODE_INFO_STRUCT
。
英文:
Where do you set up BX for ;-- get vesa modes buffer address
?<br>
;--- get mode information
requires ES:DI pointing to a DRV_VESA_VBE_MODE_INFO_STRUCT
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论