2011-01-04 21 views
17

Sono un adolescente che è diventato molto interessato al linguaggio assembly. Sto provando a scrivere un piccolo sistema operativo nell'assemblatore Intel x86 e mi chiedevo come scrivere direttamente sullo schermo, come in, senza fare affidamento sul BIOS o su qualsiasi altro sistema operativo. Stavo cercando tra le fonti di coreboot, Linux e Kolibri, tra gli altri, nella speranza di trovare e capire un pezzo di codice che faccia questo. Non ho ancora avuto successo in questo senso, anche se credo che darò un'altra occhiata al codice sorgente di Linux, essendo il più comprensibile per me delle fonti che ho cercato.Come posso scrivere direttamente sullo schermo?

Se qualcuno lo sa, o sa dove in qualche parte del codice sorgente che potrei guardare, lo apprezzerei se me lo dicessero.

O meglio ancora, se qualcuno sa come identificare quale porta I/O su una CPU Intel x86 si connette a quale componente hardware, sarebbe apprezzato anche questo. Il motivo per cui ho bisogno di chiedere questo, non è né il capitolo per l'input/output nel Manuale dello sviluppatore del software per architetture Intel 64 e IA-32 Volume 1: Architettura di base, né nelle sezioni per l'istruzione IN o OUT nel Volume 3, potrei trovare nessuna di queste informazioni. E perché è stato troppo arduo per cercare le istruzioni pertinenti nelle fonti che ho.

+0

Wow, grazie per le grandi risposte, tutti. Tutte le risposte fornite sembrano essere probabilmente utili. – user336462

+3

Hai considerato uno Sharpie? Scivolano abbastanza facilmente sulla maggior parte dei display CRT e LED. –

risposta

1

Un po 'oltre il mio scopo ma si potrebbe voler esaminare VESA.

+0

Grazie, quel posto sembra che potrebbe essere più utile della maggior parte dei posti che stavo cercando. – user336462

+0

@ user336462 Nessun problema. Facci sapere come funziona e con cosa finisci. –

+0

Non sono sicuro del perché sia ​​stato votato, ma sarebbe stato bello lasciare un messaggio sul perché. –

1

Per le porte I/O generali, è necessario passare attraverso il BIOS, il che significa interruzioni. Molte lune blu fa, ho usato i riferimenti da Don Stoner per aiutare a scrivere alcuni assembly in modalità reale, ma li ho bruciati dopo alcuni mesi e ho dimenticato la maggior parte di ciò che sapevo.

16

PARTE 1

Per le modalità VGA vecchi, c'è un indirizzo fisso di scrivere l'area di memoria (legacy) del display. Per le modalità di testo questa area inizia da 0x000B8000. Per le modalità grafiche inizia a 0x000A0000.

Per le modalità video ad alta risoluzione (ad esempio quelle impostate dall'interfaccia VESA/VBE) ciò non funziona perché la dimensione dell'area di memoria di visualizzazione legacy è limitata a 64 KiB e la maggior parte delle modalità video ad alta risoluzione richiede molto di più spazio (ad es. 1024 * 768 * 32-bpp = 2,25 MiB). Per evitare che ci siano 2 metodi diversi supportati da VBE.

Il primo metodo è denominato "commutazione banca", in cui solo una parte della memoria di visualizzazione della scheda video viene mappata nell'area legacy in qualsiasi momento (ed è possibile modificare quale parte viene mappata). Questo può essere piuttosto disordinato - ad esempio, per disegnare un pixel potrebbe essere necessario calcolare su quale banco si trova il pixel, quindi passare a quel banco, quindi calcolare quale scostamento nel banco. Per peggiorare le cose, per alcune modalità video (es. Modalità video 24-bpp dove ci sono 3 byte per pixel) solo la prima parte dei dati di un pixel potrebbe essere in un banco e la seconda parte dei dati dello stesso pixel è in una banca diversa . Il vantaggio principale di questo è che funziona con l'indirizzamento della modalità reale, poiché l'area della memoria di visualizzazione precedente è inferiore a 0x00100000.

Il secondo metodo è denominato "FrameBuffer lineare" (o semplicemente "LFB"), in cui è possibile accedere all'intera area di memoria del display della scheda video senza alcuna commutazione disordinata. Devi chiedere all'interfaccia VESA/VBE dove si trova questa area (ed è tipicamente nel "buco PCI" da qualche parte tra 0xC0000000 e 0xFFF00000). Ciò significa che non puoi accedervi in ​​modalità reale e devi utilizzare la modalità protetta o la modalità lunga o "modalità irreale".

Per trovare l'indirizzo di un pixel quando si utilizza una modalità LFB, si dovrebbe fare qualcosa come "pixel_address = display_memory_address + y * bytes_per_line + x * bytes_per_pixel". "Bytes_per_line" deriva dall'interfaccia VESA/VBE (e potrebbe non essere uguale a "horizontal_resolution * bytes_per_line" perché può esserci un padding tra le linee orizzontali).

Per "banca acceso" modi VBE/VESA, diventa qualcosa di più simile:

pixel_offset = y * bytes_per_line + x * bytes_per_pixel; 
bank_number = pixel_offset/bank_size; 
pixel_starting_address_within_bank = pixel_offset % bank_size; 

Per alcune modalità VGA vecchi (ad esempio il 256 colori "modalità 0x13") è molto simile a LFB, ad eccezione non c'è padding tra le righe e puoi fare "pixel_address = display_memory_address + (y * horizontal_resolution + x) * bytes_per_pixel". Per le modalità di testo è praticamente la stessa cosa, tranne che 2 byte determinano ciascun carattere e il suo attributo, ad es. "char_address = display_memory_address + (y * horizontal_resolution + x) * 2". Per le altre vecchie modalità VGA (modalità monocromatica/2 colori, 4 colori e 16 colori) la memoria della scheda video è organizzata in modo completamente diverso. È diviso in "piani" in cui ogni piano contiene un bit del pixel e (ad esempio) per aggiornare un pixel in una modalità a 16 colori è necessario scrivere su 4 piani separati. Per motivi di prestazioni, l'hardware VGA supporta diverse modalità di scrittura e diverse modalità di lettura e può essere complicato (troppo complicato da descrivere adeguatamente qui).

PARTE 2

Per le porte di I/O (il 80x86, "PC compatibili"), c'è 3 categorie generali. Il primo è costituito da dispositivi legacy "di fatto standard" che utilizzano porte I/O fisse. Questo include cose come chip PIC, controller DMA ISA, controller PS/2, chip PIT, porte seriali/parallele, ecc. Quasi tutto ciò che descrive come programmare ognuno di questi dispositivi ti dirà quali porte I/O utilizza il dispositivo.

La categoria successiva è dispositivi legacy/ISA, in cui le porte I/O utilizzate dai dispositivi sono determinate dai jumper sulla scheda stessa e non esiste un modo corretto per determinare quali porte I/O utilizzano dal software. Per evitare questo, l'utente finale deve dire al sistema operativo quali porte I/O utilizzano ogni dispositivo. Per fortuna questa roba croccante è diventata obsoleta (anche se questo non significa necessariamente che nessuno la stia usando).

La terza categoria è "plug & play", dove esiste un metodo per chiedere al dispositivo quali porte I/O utilizza (e nella maggior parte dei casi, cambiare le porte I/O utilizzate dal dispositivo). Un esempio di questo è PCI, dove c'è uno "spazio di configurazione PCI" che ti dice molte informazioni su ogni dispositivo PCI. Per queste categorie, non c'è modo in cui nessuno possa determinare quali dispositivi useranno le porte I/O senza eseguirle in fase di runtime, e la modifica di alcune impostazioni del BIOS può causare a tutti/tutti questi dispositivi la modifica delle porte I/O.

Si noti inoltre che una CPU Intel è solo una CPU. Nulla impedisce a quelle CPU di essere utilizzate in qualcosa che è radicalmente diverso da un computer "compatibile con PC". I manuali della CPU Intel non ti diranno mai nulla sull'hardware che esiste al di fuori della CPU stessa (incluso il chipset oi dispositivi).

Parte 3

Probabilmente il miglior posto dove andare per ulteriori informazioni (che è destinato per OS sviluppatori/hobbisti) è http://osdev.org/ (la loro wiki e forum di loro).

+3

Vorrei aggiungere che, a meno che non costruisci una GUI per il tuo sistema operativo con il BIOS, risparmierai tempo che puoi dedicare a fare cose "intrise" come il cambio di attività e la gestione della memoria. Post scriptum Penso che ogni programmatore adolescente dovrebbe scrivere un sistema operativo;) anche se si tratta solo di un boot loader. impari tantissimo –

0

Ho trovato un posto che fornisce alcune buone informazioni sull'argomento: http://www.osdever.net/FreeVGA/home.htm Si parla di alcuni dettagli importanti per scrivere il codice che scrive direttamente sullo schermo. L'ho trovato dal link al sito di Don Stoner (Grazie per il link, SilverbackNet!). Sto ancora cercando ulteriori informazioni, quindi se qualcuno ha altre idee, apprezzerei molto l'aiuto.

1

Per scrivere direttamente sullo schermo, è consigliabile scrivere nell'area Modalità testo VGA. Questo è un blocco di memoria che è un buffer per la modalità testo.

La schermata in modalità testo è composta da 80x25 caratteri; ogni personaggio ha una larghezza di 16 bit. Se il primo bit è impostato, il carattere lampeggerà sullo schermo. I 3 bit successivi descrivono quindi il colore di sfondo; i 4 bit finali del primo byte sono il colore in primo piano (o il carattere del testo). Gli 8 bit successivi sono il valore del personaggio. Questo di solito è code page 737 o 437, ma potrebbe variare da sistema a sistema.

Here è una pagina di Wikipedia in dettaglio questo buffer, e here è un collegamento a tabella codici 437

Il BIOS di solito si mette in modalità testo, ma se non è necessario impostare da soli con int10h (modalità 0x03)

+0

Il bit di lampeggio non si applica a tutti gli hardware/emulatori. Alcuni hardware/emulatori lampeggiano mentre altri lo considerano un bit di intensità (1 = alta intensità, 0 = bassa intensità). Quando dici per la prima volta ti stai veramente riferendo al Bit più significativo (MSB). Di solito i bit sono numerati da 0 a n-1 (dove N in questo caso è 16) –

+0

Sì, se ricordo correttamente QEMU non simula questo bit ma VirtualBox lo fa. –

Problemi correlati