如何在x86程序集中以受保护模式在屏幕上绘制像素?

时间:2013-01-19 21:28:44

标签: memory video assembly x86 pixel

我正在创建一个小的bootloader +内核,直到现在我设法读取磁盘,加载第二个扇区,加载GDT,打开A20并启用pmode。

我跳转到32位功能,在屏幕上显示一个字符,使用视频内存作为文本内容(0x000B0000 - 0x000B7777)

pusha
mov edi, 0xB8000
mov bl, '.'
mov dl, bl
mov dh, 63
mov word [edi], dx
popa

现在,我想再进一步在屏幕上绘制一个像素。正如我在某些网站上看到的那样,如果我想使用VGA的图形模式,我必须在0x000A0000位置写入像素。是吗?

现在,单个像素的格式是什么?对于单个字符,您需要ASCII代码和属性,但是您需要定义一个像素(如果它的工作方式与文本模式相同)?

3 个答案:

答案 0 :(得分:19)

不幸的是,它稍微远一点。

写入视频内存的规则取决于图形模式。在传统的视频模式中,VGA模式320x200(8bpp)是唯一一个视频存储器像普通存储器一样工作的模式:从0xA000:0000(或0xA0000线性)开始,您将对应于您想要的像素的字节写入视频缓冲区,就是这样。

对于其他VGA(pre-SVGA)模式,规则更复杂:当你向视频存储器写一个字节时,你会寻址一组像素,而一些我忘记的VGA寄存器指定哪个更新这些像素的平面以及如何使用它们的旧值。它不仅仅是内存

有SVGA模式(从800x600x8bpp开始);您可以使用VESA Video Bios Extensions以与硬件无关的方式切换到它们。在这些模式下,视频内存的行为类似于内存,每个像素有1,2,3或4个字节,没有类似VGA的8像素组,您可以通过一个字节访问进行触摸。问题是实模式视频缓冲区不再足以解决整个屏幕的问题。

VESA VBE 1.2通过提供修改内存窗口基础的功能解决了这个问题:在任何特定时刻,线性0xA0000的段都在寻址视频内存的64Kb区域,但是你可以控制这个地址有整个帧缓冲的64Kb(基址调整的最小单位,又名窗口粒度,取决于硬件,但你可以依赖于在0xA0000处映射N * 64Kb偏移的能力。缺点是每次开始使用不同的64Kb块时都需要VBE BIOS调用。

VESA VBE 2.0添加了平面帧缓冲,可在保护模式下的某个高地址处使用(也在unreal mode中)。因此,进入视频模式需要VBE BIOS调用,但不能用于绘制像素。

VESA VBE 3.0,可能还不够便携,提供了一种在保护模式下调用VBE功能的方法。 (我没有机会尝试它,在我的“装配操作系统”时代不存在)。

无论如何,您必须先切换到图形模式。这样做有几种变体:

  • 最简单的方法是在进入保护模式之前使用BIOS调用。使用VBE 2.0,您不需要视频内存窗口调整调用。
  • 另一种方法是创建一个适合BIOS的V8086模式环境。最难的部分是将中断转发给实模式中断处理程序。这并不容易,但是当它完成后,你将能够在PM中切换视频模式并使用其他一些BIOS功能(例如,用于磁盘I / O)。
  • 另一种方法是使用VESA VBE 3.0保护模式接口。不知道它有多简单或复杂。
  • 真正的绝地方式是挖掘特定视频卡上的信息,通过设置寄存器来切换模式。去过那里,过去为一些Cirrus卡做过 - 在PM中获得大型平板帧缓冲并不太复杂。它是不可移植的,但如果目的是了解机器的内部结构,那么它可能就是您所需要的。

答案 1 :(得分:4)

这取决于使用的图形模式,并且存在很多差异。 BIOS VGA视频模式13h(320x200,8位/像素)可能是最容易上手的(它是唯一具有256色的BIOS VGA视频模式,但是您可以通过直接写入到自己的模式来创建自己的模式视频卡的端口):在BIOS视频模式下13h,映射到屏幕的视频内存从0x0A0000开始,每个像素连续运行1个字节,并且只有1个位平面,因此每个坐标的内存地址为{{1 }}:

在实模式下更改为BIOS视频模式13h(320 x 200,8位/像素):

0x0A000 + 320*y + x

在保护模式下,在左上角(视频模式13h)绘制像素:

mov ax,0x13
int 0x10

答案 2 :(得分:1)

org 100h
bits 16
cpu 386

section.text:
START:
mov ax,12h
int 10h
mov al,02h
mov ah,0ch 

pixel.asm
c:\>nasm pixel.asm -f bin -o pixel.com
int 10h