[英]How to draw a pixel on the screen in protected mode in x86 assembly?
我正在创建一个小的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代码和属性,但是您需要定义一个像素(如果它的工作方式与文本模式相同)?
不幸的是,它稍微远一点。
写入视频内存的规则取决于图形模式。 在传统的视频模式中,VGA模式320x200(8bpp)是唯一一个视频存储器像普通存储器一样工作的模式:从0xA000:0000(或0xA0000线性)开始,您将对应于您想要的像素的字节写入视频缓冲区, 就这样。
对于其他VGA(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增加了平面帧缓冲,可在保护模式下的某个高地址处使用(也可以在虚幻模式下 )。 因此,进入视频模式需要VBE BIOS调用,但不能用于绘制像素。
VESA VBE 3.0可能还不够便携,它提供了一种在保护模式下调用VBE功能的方法。 (我没有机会尝试它,在我的“装配操作系统”时代不存在)。
无论如何,你必须先切换到图形模式。 这样做有几种变体:
这取决于使用的图形模式,并且存在很多差异。 BIOS VGA视频模式13h
(320x200,8位/像素)可能是最容易上手的(它是唯一具有256色的BIOS VGA视频模式,但您可以通过直接写入视频端口来创建自己的模式卡片):在BIOS视频模式下13h,映射到屏幕的视频内存从0x0A0000
开始,每个像素连续运行1个字节,只有1个位平面,因此每个坐标的内存地址为0x0A000 + 320*y + x
:
在实模式下更改为BIOS视频模式13h(320 x 200,8位/像素):
mov ax,0x13
int 0x10
在保护模式下,在左上角(视频模式13h)绘制像素:
mov edi,0x0A0000
mov al,0x0F ; the color of the pixel
mov [edi],al
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.