Esa es (en parte) la función del BIOS.
El sistema básico de entrada y salida de la computadora es responsable de proporcionar una interfaz común a los sistemas operativos, a pesar de las diferencias entre las computadoras reales.
Dicho esto, específicamente para gráficos, hay diferentes formas de dibujar en la pantalla. Hay comandos TTY que puede enviar al BIOS, pero eso es solo en modo real. Si desea dibujar algo en modo protegido, debe usar VGA para dibujar cosas. No puedo explicarlo mejor que OSDev, así que mire aquí para obtener más información , pero básicamente, puede escribir en la memoria (la memoria de video está asignada en la memoria) comenzando en la dirección 0xB8000
para dibujar cosas en la pantalla.
Si necesita una resolución más alta que VGA, debe usar las extensiones de BIOS VESA; No estoy familiarizado con él, pero intente mirar el código fuente de GRUB para obtener más información.
Algunas referencias útiles:
Si está familiarizado con D, escribí un pequeño gestor de arranque hace un tiempo que podía escribir en la pantalla (solo texto). Si estás interesado, aquí está el código:
align(2) struct Cell { char ch; ubyte flags = 0x07; }
@property Cell[] vram()
{ return (cast(Cell*)0xB8000)[0 .. CONSOLE_WIDTH * CONSOLE_HEIGHT]; }
void putc(char c)
{
if (isBochs) { _outp(0xE9, c); } // Output to the Bochs terminal!
bool isNewline = c == '\n';
while (cursorPos + (isNewline ? 0 : 1) > vram.length)
{
for (short column = CONSOLE_WIDTH - 1; column >= 0; column--)
{
foreach (row; 0 .. CONSOLE_HEIGHT - 1)
{
uint cell = column + cast(uint)row * CONSOLE_WIDTH;
vram[cell] = vram[cell + CONSOLE_WIDTH];
}
vram[column + (CONSOLE_HEIGHT - 1) * CONSOLE_WIDTH].ch = ' ';
}
cursorPos = cast(ushort)(cursorPos - CONSOLE_WIDTH);
}
if (isNewline)
cursorPos = cast(ushort)
((1 + cursorPos / CONSOLE_WIDTH) * CONSOLE_WIDTH);
else vram[cursorPos++].ch = c;
}
void putc(char c, ubyte attrib) { vram[cursorPos] = Cell(c, attrib); }
void memdump(void* pMem, size_t length)
{
foreach (i; 0 .. length)
putc((cast(char*)pMem)[i]);
}
void clear(char clear_to = '\0', ubyte attrib = DEFAULT_ATTRIBUTES)
{
foreach (pos; 0 .. vram.length)
vram[pos] = Cell(clear_to, attrib);
cursorPos = 0;
}
@property ushort cursorPos()
{
ushort result = 0;
_outp(0x3D4, 14);
result += _inp(0x3D5) << 8;
_outp(0x3D4, 15);
result += _inp(0x3D5);
return result;
}
@property void cursorPos(ushort position)
{
_outp(0x3D4, 14);
_outp(0x3D5, (position >> 8) & 0xFF);
_outp(0x3D4, 15);
_outp(0x3D5, position & 0xFF);
}