在 VESA 图形模式下绘制像素
Drawing pixels in VESA graphic mode
如何在 VESA 图形模式下绘制像素?
我正在尝试中断 10h
功能 0ch
,但它不起作用。怎么了?
(注意:我用NASM语法写了这段代码,并用qemu测试过)
; Code:
Mov ax, 4F02h
Mov bx, 0105h ; 1024x768 pixels
Int 10h
Mov ah, 0ch ; Draw pixel function
Mov cx, 2 ; column
Mov dx, 3 ; row
Mov bh, 0
Mov bl, 00000101b ; colour
Int 10h
Jmp $ ; jump forever
Times 510-($-$$) db 0
Dw 0xaa55
即使使用 VESA VBE 模式,函数 Int 10h/AH=0Ch 也应该可以工作。
确保正确使用它,像素的颜色进入al
。
;Set video mode
mov ax, 4f02h
mov bx, 105h
int 10h
;Draw pixel
mov ax, 0c09h ;09h = Blue
mov cx, 2
mov dx, 3
xor bx, bx
int 10h
从技术上讲,您应该使用 Int 10h/AX=4F01h 来检索视频模式信息,包括 mode 属性的第 2 位(2 BIOS 输出支持) 字段,检查 BIOS 功能是否正常工作。
使用 BIOS 功能写入高分辨率图像可能太慢,直接写入线性或 windowed 帧缓冲区可能值得投资。
写入线性帧缓冲区可能需要使用 the unreal mode,可以通过使用 windowed 帧缓冲区来避免这种情况。
这除了更慢之外,也更麻烦。
这是一个非常简单的程序,用可怕的灰色阴影填充 30 行。
注意为了简洁明了,我去掉了所有的检查,我做了很多的假设以避免做一些数学运算。
这是一个不好的做法,我只将它用于原型设计。
我强烈建议您阅读 Int 10h/AX=4F01h
返回的完整信息,并使用该信息 select 正确的 window,进行正确的填充和计算。
BITS 16
ORG 100h
mov ax, ds
mov es, ax
;Set video mode
mov ax, 4f02h
mov bx, 105h
int 10h
;Get video mode info
mov ax, 4f01h
mov cx, 105h
mov di, modeInfo
int 10h
;Assume first window is valid
mov ax, WORD [es:modeInfo + 08h]
mov es, ax
;Example of how to change the window
mov ax, 4f05h
xor bx, bx
mov dx, 5 ;This is granularity units
int 10h
xor di, di
mov al, 0f1h
mov cx, 3*1024*20
rep stosb
;Wait for key
xor ax, ax
int 16h
;Restore DOS text mode
mov ax, 0003h
int 10h
;Exit
mov ax, 4c00h
int 21h
modeInfo TIMES 256 db 0
这是在NASM语法中,我通常对DOS程序使用TASM(出于感情)但是这次我很着急。
结果是
请记住,通常可以填充每个扫描线(视频模式信息中返回扫描线的大小)。
对于 1024 像素宽的扫描线,对于 3x8bpp,我们有 3072 bytes/scanline,因为它可以被 4 整除,所以 不可能 发生填充。
window 起始地址在粒度单元中给出(也可在视频模式信息中找到),总帧缓冲区为 1024x768x3 字节 = 2.25 MiB,假设没有填充。
window 大小也可以在视频模式信息中找到。
所有这些足以写入帧缓冲区。
一旦设置了虚幻模式,线性帧缓冲区就更容易处理(填充仍然是一个需要考虑的方面)。
如何在 VESA 图形模式下绘制像素?
我正在尝试中断 10h
功能 0ch
,但它不起作用。怎么了?
(注意:我用NASM语法写了这段代码,并用qemu测试过)
; Code:
Mov ax, 4F02h
Mov bx, 0105h ; 1024x768 pixels
Int 10h
Mov ah, 0ch ; Draw pixel function
Mov cx, 2 ; column
Mov dx, 3 ; row
Mov bh, 0
Mov bl, 00000101b ; colour
Int 10h
Jmp $ ; jump forever
Times 510-($-$$) db 0
Dw 0xaa55
即使使用 VESA VBE 模式,函数 Int 10h/AH=0Ch 也应该可以工作。
确保正确使用它,像素的颜色进入al
。
;Set video mode
mov ax, 4f02h
mov bx, 105h
int 10h
;Draw pixel
mov ax, 0c09h ;09h = Blue
mov cx, 2
mov dx, 3
xor bx, bx
int 10h
从技术上讲,您应该使用 Int 10h/AX=4F01h 来检索视频模式信息,包括 mode 属性的第 2 位(2 BIOS 输出支持) 字段,检查 BIOS 功能是否正常工作。
使用 BIOS 功能写入高分辨率图像可能太慢,直接写入线性或 windowed 帧缓冲区可能值得投资。
写入线性帧缓冲区可能需要使用 the unreal mode,可以通过使用 windowed 帧缓冲区来避免这种情况。
这除了更慢之外,也更麻烦。
这是一个非常简单的程序,用可怕的灰色阴影填充 30 行。
注意为了简洁明了,我去掉了所有的检查,我做了很多的假设以避免做一些数学运算。
这是一个不好的做法,我只将它用于原型设计。
我强烈建议您阅读 Int 10h/AX=4F01h
返回的完整信息,并使用该信息 select 正确的 window,进行正确的填充和计算。
BITS 16
ORG 100h
mov ax, ds
mov es, ax
;Set video mode
mov ax, 4f02h
mov bx, 105h
int 10h
;Get video mode info
mov ax, 4f01h
mov cx, 105h
mov di, modeInfo
int 10h
;Assume first window is valid
mov ax, WORD [es:modeInfo + 08h]
mov es, ax
;Example of how to change the window
mov ax, 4f05h
xor bx, bx
mov dx, 5 ;This is granularity units
int 10h
xor di, di
mov al, 0f1h
mov cx, 3*1024*20
rep stosb
;Wait for key
xor ax, ax
int 16h
;Restore DOS text mode
mov ax, 0003h
int 10h
;Exit
mov ax, 4c00h
int 21h
modeInfo TIMES 256 db 0
这是在NASM语法中,我通常对DOS程序使用TASM(出于感情)但是这次我很着急。
结果是
请记住,通常可以填充每个扫描线(视频模式信息中返回扫描线的大小)。
对于 1024 像素宽的扫描线,对于 3x8bpp,我们有 3072 bytes/scanline,因为它可以被 4 整除,所以 不可能 发生填充。
window 起始地址在粒度单元中给出(也可在视频模式信息中找到),总帧缓冲区为 1024x768x3 字节 = 2.25 MiB,假设没有填充。
window 大小也可以在视频模式信息中找到。
所有这些足以写入帧缓冲区。
一旦设置了虚幻模式,线性帧缓冲区就更容易处理(填充仍然是一个需要考虑的方面)。