在VESA图形模式下绘制像素

时间:2018-05-26 07:27:11

标签: assembly x86 nasm x86-16 vesa

如何在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

1 个答案:

答案 0 :(得分:6)

即使使用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检索视频模式信息,包括模式属性字段的第2位( 2 BIOS输出支持)到检查BIOS功能是否有效。

使用BIOS功能写入高分辨率图像可能太慢,可能值得投资直接写入线性或窗口帧缓冲区。
写入线性帧缓冲区可能需要使用the unreal mode,可以通过使用窗口帧缓冲来避免这种情况。
除了速度较慢之外,这也更麻烦。

这是一个非常简单的程序,填充了30行,带有可怕的灰色阴影 注意我为了紧凑和清晰而剥离了所有检查,我做了很多的假设,以避免做一些数学。
这是一种不好的做法,我只将其用于原型设计 我强烈建议您阅读Int 10h/AX=4F01h返回的完整信息,并使用该信息选择正确的窗口,进行正确的填充和计算。

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语法中,我通常使用TASM(出于感情)用于DOS程序,但这次我很着急。
结果是

A grey band in the, more or less, middle of a black screen

请记住,通常可以填充每条扫描线(在视频模式信息中返回扫描线的大小)。
对于1024像素宽的扫描线,使用3x8bpp,我们有3072字节/扫描线,因为它可以被4整除,所以可能不会发生填充。
窗口起始地址以粒度单位给出(也可在视频模式信息中找到),总帧缓冲区为1024x768x3字节= 2.25 MiB,假设没有填充。
窗口大小也可在视频模式信息中找到。

这一切足以写入帧缓冲区 一旦设置了虚幻模式,线性帧缓冲区就更容易处理(填充仍然是一个需要考虑的方面)。