如何在 x86 程序集中以保护模式在屏幕上绘制像素? [英] How to draw a pixel on the screen in protected mode in x86 assembly?

查看:166
本文介绍了如何在 x86 程序集中以保护模式在屏幕上绘制像素?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am creating a little bootloader+kernel and till now I managed to read disk, load second sector, load GDT, open A20 and enable pmode.

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

I jumped to the 32-bits function that show me a character on the screen, using the video memory for textual content (0x000B0000 - 0x000B7777)

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

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

Now, I would like to go a little further and draw a single pixel on the screen. As I read on some website, if I want to use the graphics mode of the VGA, I have to write my pixel at location 0x000A0000. Is that right?

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

Now, what is the format of a single pixel? For a single character you need ASCII code and attribute, but what do you need to define a pixel (if it works the same way as the textual mode)?

推荐答案

不幸的是,它有点远.

写入视频内存的规则取决于图形模式.在传统的视频模式中,VGA 模式 320x200 (8bpp) 是唯一一种视频内存表现得像普通内存的模式:您将与您想要的像素对应的字节写入视频缓冲区,从 0xA000:0000(或 0xA0000 线性)开始,仅此而已.

The rules for writing to video memory depend on the graphics mode. Among traditional video modes, VGA mode 320x200 (8bpp) is the only one where video memory behaves like a normal kind of memory: you write a byte corresponding to a pixel you want to the video buffer starting from 0xA000:0000 (or 0xA0000 linear), and that's all.

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

For other VGA (pre-SVGA) modes, the rules are more complicated: when you write a byte to video memory, you address a group of pixels, and some VGA registers which I have long since forgotten specify which planes of those pixels are updated and how the old value of them is used. It's not just memory any more.

有SVGA模式(800x600x8bpp开头);您可以使用 VESA Video Bios Extensions 以独立于硬件的方式切换到它们.在这些模式下,视频内存的行为再次像内存一样,每个像素有 1、2、3 或 4 个字节,并且没有您通过 1 个字节访问接触的类似 VGA 的 8 像素组.问题是实模式视频缓冲区不够大,无法处理整个屏幕.

There are SVGA modes (starting with 800x600x8bpp); you can switch to them in a hardware-independent way using VESA Video Bios Extensions. In those modes, video memory behaves like memory again, with 1,2,3 or 4 bytes per pixel and no VGA-like 8-pixel groups which you touch with one byte access. The problem is that the real-mode video buffer is not large enough any more to address the whole screen.

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

VESA VBE 1.2 addressed this problem by providing functions to modify the memory window base: in any particular moment, the segment at linear 0xA0000 is addressing 64Kb region of video memory, but you can control which 64Kb of the whole framebuffer are available at this address (minimal unit of base address adjustment, a.k.a window granularity, depends on the hardware, but you can rely on the ability to map N*64Kb offset at 0xA0000). The downside is that it requires VBE BIOS call each time when you start working with different 64Kb chunk.

VESA VBE 2.0 添加了平面帧缓冲区,在保护模式(也在非真实模式下)的一些高地址处可用).因此,进入视频模式需要 VBE BIOS 调用,但绘制像素不需要.

VESA VBE 2.0 added flat framebuffer, available at some high address in protected mode (also in unreal mode). Thus VBE BIOS call is required for entering video mode, but not for drawing pixels.

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

VESA VBE 3.0, which might not be portable enough yet, provides a way to call VBE functions in protected mode. (I didn't have a chance to try it, it was not there during my "OS in assembly" age).

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

Anyway, you have to switch to graphics mode first. There are several variants of doing that:

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

这篇关于如何在 x86 程序集中以保护模式在屏幕上绘制像素?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆