【问题标题】:Drawing pixels in VESA graphic mode在 VESA 图形模式下绘制像素
【发布时间】:2018-11-05 12:20:53
【问题描述】:

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

【问题讨论】:

  • 请用 NASM 语法或类似 NASM(TASM、MASM 等)而不是 GAS 语法回答这个问题。因为,我无法使用 GNU Assembler 语法。
  • @Juan:您要查找的术语是 Intel 与 AT&T 语法。无论如何,您可以通过使用mov byte [bx], 123(或word 或其他任何内容,取决于您设置的像素格式)将像素存储到视频内存中来绘制像素。将dses 设置为视频RAM 基地址。
  • 2 票否决?用户提供 1. 他们试图完成的事情,2. 他们尝试过的事情,3. 代码应该做什么的描述,4. 代码不能绘制像素。看看接受的答案,似乎尝试的东西也不是很远......?说:“问题是我忘了把颜色放在 ax 的低字节中。”这样说是没有意义的。无需投票,但在我看来,问题和答案是一个有趣的问题和解决方案。
  • @user176692:删除了我的反对票。当我第一次阅读这篇文章时,我错过了尝试绘制像素以及设置视频模式的情况。 (我不知道有一个int 10h函数。看起来调用它比存储到视频内存需要更多的代码。)仍然不是minimal reproducible example,并且只需阅读文档即可解决。 (除非你知道直接存储到视频 RAM 比 int 10h 快得多。)

标签: assembly x86 nasm x86-16 vesa


【解决方案1】:

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

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

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

【讨论】:

    猜你喜欢
    • 2018-03-29
    • 2022-01-02
    • 1970-01-01
    • 2014-12-11
    • 1970-01-01
    • 1970-01-01
    • 2015-08-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多