15

我正在创建一个小引导加载程序+内核,直到现在我设法读取磁盘、加载第二个扇区、加载 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 代码和属性,但是您需要定义一个像素(如果它的工作方式与文本模式相同)?

4

3 回答 3

21

不幸的是,它有点远。

写入显存的规则取决于图形模式。在传统的视频模式中,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 添加了平面帧缓冲区,在保护模式下(也在虚幻模式下)在某个高地址处可用。因此,进入视频模式需要调用 VBE BIOS,而不是绘制像素。

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

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

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

这取决于使用的图形模式,并且有很多差异。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
于 2013-01-19T21:39:12.323 回答
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
于 2015-09-15T17:04:04.013 回答