Discussione VRAM della VGA mappata in memoria

mattstack

Utente Bronze
1 Aprile 2021
62
19
12
41
Ultima modifica:
Parto col dire che sono in totale confusione, e forse quello che dirò sarà sbagliato.
Avevo intenzione di scrivere un piccolo programma che facesse uso del chip VGA per operazioni di video Output.
Ho capito che la VGA dispone di molti registri interni, più di 300, che sono mappati tramite il Port Mapped I/O(PMIO), questo vuol dire che l'accesso ai registri interni della VGA avviene attraverso determinate istruzioni di I/O messe a disposizione dalla CPU, per esempio nella famiglia x86 abbiamo le seguenti:
Codice:
in    al/ax, Imm8/16
out   Imm8/16, al/ax
Subito dopo ho compreso che la VGA dispone di una memoria interna che viene adoperata per memorizzare i dati da visualizzare a video, quest'ultima in modalità testo si estende dall'indirizzo fisico B8000h fino a l'indirizzo BFFFFh, si suddivide in 8 pagine video delle quali solo la prima comporta modifiche a video.
La VRAM della VGA è mappata in memoria RAM tramite MMIO(Memory mapped I/O), questo vuol dire che è possibile apportare modifiche a questa memoria utilizzando le sole istruzioni di trasferimento dati messe a disposizione dalla CPU(ess. mov, stosw, etc.).
Qui inizia a confondermi la situazione, il MMIO consiste nel mappare determinati indirizzi di memorie centrali all'interno della memoria RAM, facendo si che quando un determinato indirizzo venga scritto sull'Address Bus, se quest'ultimo corrisponde a uno degli indirizzi compresi nell'area di memoria mappata in RAM, il dispositivo mappato recepisca l'indirizzo e svolge il suol compito.
Esempio:
Scrivo nella locazione di memoria avente indirizzo fisico B8000h il dato 23h, l'indirizzo B8000h verrà scritto sull'Address Bus, ma non verrà recepito dalla RAM bensì dalla VGA che riconoscendo l'indirizzo scriverà il dato nella determinata locazione della VRAM.

Adesso il problema principale è uno, lo espongo con un esempio(con questa confusione gli esempi mi escono meglio):

Supponiamo di avere un piccolo computer che dispone di 32KiB RAM, di una VGA con memoria interna di 32KiB, e di una CPU con 16 pin di indirizzo, quindi può indirizzare fino a 64KiB di memoria, i primi 32KiB dello spazio di indirizzamento è dedicato alla RAM(Memoria bassa) e nei 32KiB alti è mappata la VRAM(memoria alta), se il processore scrive sull'Address Bus un indirizzo su 15 bit, per esempio 8000h, la RAM recepirà l'indirizzo e il processore scriverà/leggerà il dato nell'ultima locazione della RAM, se il processore scriverà sull'Address Bus un indirizzo su 16bit del tipo 8001h, allora il dato verrà letto/scritto nella VRAM, in quanto supera lo spazio di indirizzamento basso e scrive i dati in quello alto nella quale e mappata la VRAM.
(già così mi puzza la situazione).

Se invece la RAM fosse di 64KiB e la VRAM di 32KiB(mappata in memoria), e il processore ha uno spazio di indirazzmento di 64KiB questo vuol dire che non potremmo mai usare le locazione dopo il 32KiB di memoria RAM, in quanto dopo quell'indirizzo è mappata la VRAM, giusto? Non è uno spreco enorme di memoria.

Sicuramente non è tutto corretto, qualcuno che mi possa spiegare ciò?
 
In realtà la VRAM è un pò più grande; si tratta di 128Kb di memoria:
  • da A000h:0000h a A000h:FFFFh (64K), è il modo grafico
  • da B000h:0000h a B000h:7FFFh (32K) è il modo monocromatico
  • da B000h:8000h a B000h:FFFFh (32k) è il modo testo
Non mi sembra ci sia qualcosa di errato in ciò che dici. E' proprio così: quando vai a scrivere in VRAM il risultato viene direttamente mostrato a video (se scrivi sulla pagina 0).

A parte ciò considera che la memoria sotto DOS era di 1MB. La CPU 8086 non poteva indirizzarne di più. Quindi i buffer video (VRAM) servivano proprio a questo scopo: accedere a della memoria alla quale non si sarebbe potuti accedere.
Considera che un programma DOS aveva a disposizione ben poca memoria, più o meno il 40% di 1MB, poichè il resto era dedicato a IVT, DOS, BIOS, VRAM... quindi diciamo che un programma aveva a disposizione 600KB circa.

Considera anche che sotto DOS con una 8086 hai già uno spreco: l'ultimo segmento disponibile, FFFFh ha come ultimo offset 000Fh. Con questa coppia hai già raggiunto i 20bit disponibili e incrementando l'offset hai un indirizzo a 21bit (FFFFh:0010h), che in 8086 non può essere gestito (tornavi all'inizio, a causa del "wrap around").
Con 286 puoi accedere a questa memoria, avendo un address bus più ampio: la zona di memoria è nota come HMA.

Diciamo che i tuoi esempi sono corretti, anche se l'indirizzo che hai riportato è già a 16bit. Comunque si è capito ciò che intendi. L'informazione scritta in uno di questi buffer viene comunque recepita dalla scheda direttamente, e viene poi gestito l'output a video.

Non so se in qualche modo ho risposto ai tuoi dubbi.
 
In realtà la VRAM è un pò più grande; si tratta di 128Kb di memoria:
  • da A000h:0000h a A000h:FFFFh (64K), è il modo grafico
  • da B000h:0000h a B000h:7FFFh (32K) è il modo monocromatico
  • da B000h:8000h a B000h:FFFFh (32k) è il modo testo
Non mi sembra ci sia qualcosa di errato in ciò che dici. E' proprio così: quando vai a scrivere in VRAM il risultato viene direttamente mostrato a video (se scrivi sulla pagina 0).

A parte ciò considera che la memoria sotto DOS era di 1MB. La CPU 8086 non poteva indirizzarne di più. Quindi i buffer video (VRAM) servivano proprio a questo scopo: accedere a della memoria alla quale non si sarebbe potuti accedere.
Considera che un programma DOS aveva a disposizione ben poca memoria, più o meno il 40% di 1MB, poichè il resto era dedicato a IVT, DOS, BIOS, VRAM... quindi diciamo che un programma aveva a disposizione 600KB circa.

Considera anche che sotto DOS con una 8086 hai già uno spreco: l'ultimo segmento disponibile, FFFFh ha come ultimo offset 000Fh. Con questa coppia hai già raggiunto i 20bit disponibili e incrementando l'offset hai un indirizzo a 21bit (FFFFh:0010h), che in 8086 non può essere gestito (tornavi all'inizio, a causa del "wrap around").
Con 286 puoi accedere a questa memoria, avendo un address bus più ampio: la zona di memoria è nota come HMA.

Diciamo che i tuoi esempi sono corretti, anche se l'indirizzo che hai riportato è già a 16bit. Comunque si è capito ciò che intendi. L'informazione scritta in uno di questi buffer viene comunque recepita dalla scheda direttamente, e viene poi gestito l'output a video.

Non so se in qualche modo ho risposto ai tuoi dubbi.
Cioè che mi fa dubitare e che in quei tempi, in cui i chip RAM erano molto costosi, per quale motivo implementare questo metodo di MMIO VRAM, sarebbe stato meglio secondo me implementare un paio di istruzioni per la scrittura in memoria secondarie, ciò avrebbe complicato uno po' la circuteria del processore.... No aspetta, adesso che ci penso bene, se vogliamo sfruttare tutto la spazio di indirizzamento della CPU per la sola memoria RAM, bisognerebbe far si che niente si intrometti nella trasmissione dell'Indirizzo sull'Address Bus, quindi dovremmo usare un secondo bus per indirizzare dati nelle memorie secondarie, ma ciò comporterebbe la presenza di extra pin di indirizzo, n per la RAM e n per le memorie principali secondarie.
Sarebbe stato molto costoso.

Non ho ancora capito una cosa però, questo comporta che certe locazioni della RAM non potranno mai essere utilizzate perché recepite dal chip VGA e non dal chip RAM.
 
Al tempo di 8086 tieni presente che avevi a che fare con dei PC che costavano già abbastanza, ma a parte ciò, considera che 1MB di RAM era sufficiente (si parla della fine degli anni '70 circa).
Devi tener presente che tante locazioni di RAM non venivano utilizzate ai tempi; prendi DOS ad esempio. La memoria convenzionale era di 640K, che in realtà era poi un pò inferiore a questo numero. Il programma aveva quindi 640k di RAM, il resto non è utilizzabile dal programma.

Non ho ancora capito una cosa però, questo comporta che certe locazioni della RAM non potranno mai essere utilizzate perché recepite dal chip VGA e non dal chip RAM.

In sostanza si. Quando scrivi in uno degli indirizzi citati sopra, è la VGA a ricevere il valore, e disegna i pixels a schermo.

Guarda anche la memory map del DOS:
MEMMAP.GIF

Puoi trovare un pò di info anche qui: https://wiki.osdev.org/Memory_Map_(x86)
 
Al tempo di 8086 tieni presente che avevi a che fare con dei PC che costavano già abbastanza, ma a parte ciò, considera che 1MB di RAM era sufficiente (si parla della fine degli anni '70 circa).
Devi tener presente che tante locazioni di RAM non venivano utilizzate ai tempi; prendi DOS ad esempio. La memoria convenzionale era di 640K, che in realtà era poi un pò inferiore a questo numero. Il programma aveva quindi 640k di RAM, il resto non è utilizzabile dal programma.



In sostanza si. Quando scrivi in uno degli indirizzi citati sopra, è la VGA a ricevere il valore, e disegna i pixels a schermo.

Guarda anche la memory map del DOS:
MEMMAP.GIF

Puoi trovare un pò di info anche qui: https://wiki.osdev.org/Memory_Map_(x86)
Ok chiaro, grazie.