16

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.

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

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?

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)?

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
ali
  • 10,927
  • 20
  • 89
  • 138

3 Answers3

22

Unfortunately, it's a little more than a little further.

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.

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.

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 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 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, 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:

  • The easiest thing to do is to use a BIOS call before you enter protected mode. With VBE 2.0, you won't need video memory window adjustment calls.
  • Another way is creating a V8086-mode environment which is good enough for BIOS. The hardest part is forwarding interrupts to real-mode interrupt handlers. It's not easy, but when it's done, you'll be able to switch video modes in PM and use some other BIOS functions (for disk I/O, for example).
  • Yet another way is to use VESA VBE 3.0 protected mode interface. No idea on how easy or complicated it might be.
  • And a real Jedi way is digging out the information on your specific video card, switching modes by setting its registers. Been there, done that for some Cirrus card in the past -- getting big plain framebuffer in PM was not too complicated. It's unportable, but maybe it's just what you need if the aim is understanding the internals of your machine.
Anton Kovalenko
  • 20,999
  • 2
  • 37
  • 69
  • 2
    Some VBE 2/3 BIOSes don't support LFB. I found it out the hard way on some intel's chip that combines a memory controller and a video device back in 2001. – Alexey Frunze Jan 20 '13 at 02:28
6

It depends on the graphics mode in use, and there are a lot a differences. BIOS VGA video mode 13h (320x200 at 8 bits/pixel) is probably the easiest to get started with (and it's the only BIOS VGA video mode with 256 colors, however you can create your own modes by writing directly to the ports of the video card): in BIOS video mode 13h the video memory mapped to screen begins at 0x0A0000 and it runs continuosly 1 byte for each pixel, and only 1 bit plane, so each coordinate's memory address is 0x0A000 + 320*y + x:

To change to BIOS video mode 13h (320 x 200 at 8 bits/pixel) while in real mode:

mov ax,0x13
int 0x10

To draw a pixel in the upper left corner (in video mode 13h) while in protected mode:

mov edi,0x0A0000
mov al,0x0F      ; the color of the pixel
mov [edi],al
nrz
  • 10,435
  • 4
  • 39
  • 71
  • 3
    Yes, of course. `mov ax,13h`, `int 10h` does that (in real mode). – nrz Jan 19 '13 at 21:41
  • 1
    No, in protected mode it's a little more complicated, I think you have to define a palette, and of course, you can't use interrupts in pmode. – ali Jan 19 '13 at 21:42
  • I just wanted to know the format of the pixel. So, it's just the colour of it. Thanks – ali Jan 19 '13 at 21:43
  • 1
    If a DOS extender is used it will typically hook common interrupts (such as `10h`), which enables you to use them from protected mode. – Michael Jan 20 '13 at 15:07
  • 1
    For videomodes with 8,15,16,24,32 bits of colors the format of a pixel depends on how many bits per pixel is used with the videomode. But the horizontal scanlines are maybe longer as the horizontal resolution with a part outside of the visible view. Example für 800x600x8 the scanlines are maybe 1024 bytes with 224 Bytes outside of the visible view for each horizantal scanline. Whith the VBE function 4F01h we can get those mode information. All information about the VBE-Bios we can found in the public and costfree document "vbe3.pdf" from vesa.org(need register/login). – Dirk Wolfgang Glomp May 08 '14 at 07:18
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
1.21 gigawatts
  • 16,517
  • 32
  • 123
  • 231
  • 3
    DOS `.com` executable don't run in protected mode, they run in vm86 or actual real mode. (There is a 16-bit protected mode, but AFAIK you can't use `int 10h` BIOS calls from it.) So I think this doesn't answer the question at all. Add text to explain if I'm wrong. – Peter Cordes Apr 18 '18 at 10:41