

           Textausgabe im Grafikmodus 12h (640x480x16)
           


Whrend sich Gabriel in dieser Ausgabe mit der Ausgabe eines
Textes im Textmodus (nettes Wortspiel, oder? :-> ) beschftigt,
habe ich mir das ganze fr den Grafikmodus 12h vorgenommen.

Ich werde Euch nun die Theorie hinter meiner Ausgaberoutine er-
klren, die ich z.B. auch fr den Lister benutze.

Zu erst mten wir wohl mal erfahren, wo da, was wir ausgeben
wollen, berhaupt zu finden ist: Die Zeichensatztabelle.
Die Zeichensatztabelle fr 3 Zeichenstze (bei der VGA-Karte)
befindet sich in einem ROM-Baustein. Um die Adresse dieser
Tabelle(n) zu ermitteln, hilft ein Interruptaufruf:

Laden wir das AX-Register mit dem Wert '1130h'
und BH mit: 01h  ---> 16 Byte-Zeichensatz
            02h  ---> 14 Byte-Zeichensatz
            03h  --->  8 Byte-Zeichensatz.

Somit ist auch schon erklrt, welche drei Zeichenstze 'von Haus
aus' vorhanden sind. Es knnen natrlich auch noch eigene nachge-
laden werden, doch ist das nicht Thema von diesem Artikel...
Es sei nur noch erwhnt, da der 16 Byte-Zeichensatz derjenige
ist, der normalerweise im Textmodus benutzt wird. Im MC-Lister
wird aber zum Beispiel nur der 14'er-Satz benutzt.

Wie auch immer: Rufen wir den Interrupt 10h nun mit AX=1130h und
BH=02h auf, erhalten wir in BP:ES die Offset und Segmentadresse
des gesuchten Zeichensatzes zurck.
Von BP+00 bis BP+13 befindet sich nun die BitMaske des ersten
Zeichens, von BP+14 bis BP+27 die des zweiten Zeichens und so
weiter. Um nun zu ermitteln, wo zum Beispiel das 'A' steht, mu
der ASCII-Code des Zeichens 'A' (nmlich 65) mit 14 (bzw. 8,16 -
je nach gewhltem Zeichensatz) multipliziert werden (hier: 910).
Addieren wir das Ergebnis nun zu BP, erhalten wir die Offset-
adresse des Zeichens 'A'. Hierrauf folgen dann 14 Bytes, die,
wenn man sie als Bitmaske interpretiert, untereinander geschrie-
ben ein 'A' ergeben... Alles klar?

Ok, ein Beispiel:

Wo liegt Buchstabe 'B' im Speicher?

 Ermittlung vom 14'er-Zeichensatz:
  AX=1130, BH=02h, Aufruf: INT10h --> BP : Offset, ES : Segment.

 Position von 'B' innerhalb des Zeichensatzes:
  Pos = ASCII-Code ('B') * 14 = 66 * 14 = 924.

 Position von 'B' im Speicher:

                  7  6  5  4  3  2  1  0

 ES:BP + 924:     0  0  0  0  0  0  0  0
 ES:BP + 925:     1  1  1  1  1  1  0  0
 ES:BP + 926:     1  1  0  0  0  0  1  0
 ES:BP + 927:     1  1  0  0  0  0  0  1
 ES:BP + 928:     1  1  0  0  0  0  0  1
 ES:BP + 929:     1  1  0  0  0  0  0  1
 ES:BP + 930:     1  1  0  0  1  1  1  0
 ES:BP + 931:     1  1  0  0  0  0  0  1
 ES:BP + 932:     1  1  0  0  0  0  0  1
 ES:BP + 933:     1  1  0  0  0  0  0  1
 ES:BP + 934:     1  1  0  0  0  0  1  0
 ES:BP + 935:     1  1  1  1  1  1  0  0
 ES:BP + 936:     0  0  0  0  0  0  0  0
 ES:BP + 937:     0  0  0  0  0  0  0  0.


So, ich hoffe, da ist jetzt klar geworden.
Die allgemein 'Formel' lautet also:

ZeichenPosition = ES:BP + ASCII-Code von Zeichen * 14,
wobei ES:BP schon auf den Zeichensatz zeigen mu!

Gut, jetzt wei man immerhin schon mal, wo da, was spter mal
auf dem Schirm zu sehen sein soll, im Speicher zu finden ist.

Nun stellt sich nur noch die Frage, wie bringe ich denn diese
Bitmasken auf den Schirm?
Es gibt da verschiedene Mglichkeiten, wobei ich meine natrlich
wieder fr die beste halte ;-)... zumindest aber fr die schnell-
ste!
Es gibt zum einen die Mglichkeit, nun jedes einzelne Bit zu pr-
fen und dann mittels einer PutPixel-Routine auf den Bildschirm zu
bringen. Das hat den Vorteil, da man das vorgefundene Zeichen
auch vergrern kann, indem man nmlich fr ein gesetztes Bit
nicht nur einen Pixel setzt sondern gleich zum Beispiel ein 2x2-
Feld. Man kann auch 3x3 oder 10x10-Pixelfelder benutzen - je
nachdem, wie gro man das Zeichen haben will. Nur hat diese Va-
riante den argen Nachteil, extrem langsam zu sein. Schlielich
mu man zum einen bei jedem Bit prfen ob es auf 0 oder auf 1
steht, und zum anderen mu man jeden Pixel einzeln setzen.

Meine Lsung sieht nun aber vor, das vorgefundene Byte in einem
auszulesen und ins 'BitMask-Register' der VGA-Karte zu schreiben.
Anschlieend brauch man dann nur noch die gewnschte Farbe ber
die Latchregister in den Videospeicher zu schreiben und schon
funzt's. Eventuell mu man vorher auch noch die Latchregister
auslesen. Das war's dann aber auch schon. Man hat also sogesehen
8 Bits auf einen Schlag gesetzt bzw. eine ganze Zeile eines Zei-
chens ausgegeben.

Nochmal die Form:
Man ermittelt das erste Byte des Zeichens und ldt dieses in das
BitMask-Register des Graphics-Controller der VGA-Karte. Dann wer-
den die Latchregister ausgelesen und danach mit der gewnschten
Farbe an der Position, wo das Zeichen hin soll, wieder beschrie-
ben. Das wiederholt man nun mit den dreizehn (oder 7/15) folgen-
den Bytes auch noch, und... das Zeichen steht.

Ein Beispiel:
 Ich will ein 'B' bei 0/0 ausgeben:

  Der Graphics-Controller, der ber die Index-Portadresse 3CEh
  und ber die Daten-Portadresse 3CFh angesprochen wird, erhlt
  nun ber PORT(3CEh) den Wert 08h(setze BitMaske) und ber den
  PORT(3CFh) den Wert 00000000h (erstes Byte von 'B' (s.o.)).
  Nun werden die Latchregister ausgelesen: AH=MEM(A000h:0).
  Dann werden die Latchregister beschrieben: MEM(A000h:0)=Farbe.
  Nun geht's wieder von vorne los, wobei anstelle des ersten
  Bytes von 'B' die folgenden benutzt werden und sich die Off-
  setadresse bei den Speicherzugriffen (hier ber MEM deutlich
  gemacht) jeweils um 80 erhht, also:
  MEM(A000h:80), MEM(A000h,160), MEM(A000h,240)...

-----

Um das zu verstehen, mu man natrlich schon einiges ber den Mo-
dus 12h bescheid wissen, was aber mit den schon vorher erschie-
nenen Artikeln (was, ihr habt sie nicht? Dann bestellen!) kein
Problem sein sollte. Kennt Ihr Euch also nicht mit dem genannten
Modus aus, knnt Ihr das Weiterlesen eigentlich gleich bleiben
lassen, da Ihr, wie ich annehme, jetzt schon nichts mehr versteht
und: es wird noch schlimmer... :-((! Wie gesagt: Bestellt die
vorherigen Ausgaben mit den passenden Artikeln (am besten gleich
alle...).

-----

Nun offenbart sich aber ein Problem: Nach dieser Variante kann
man den Text leider nur wie im Textmodus darstellen, da heit,
nur an x-Koordinaten zeigen, die durch 8 teilbar sind! Da liegt
nun mal an dem (meiner Meinung nach beschi...) Speicheraufbau im
Modus 12h. Da sich die Pixel 0-7, 8-15 etc. jeweils innerhalb
eines Bytes finden, mu man ein wenig tricksen, wenn man ein
Zeichen zum Beispiel von 3-10 stehen haben will.

Und das geht so:
Es ist schon mal klar: Wenn ich ein Zeichen ausgeben will, da
(um beim Beispiel zu bleiben) von der x-Koordinate 3 bis 10
erscheinen soll, so mssen dafr zwei Bytes im Videospeicher
angesprochen werden (bei y-Koor=0 nmlich A000h:0 und A000h:1).
Um nun an die richtigen Bitmasken zu kommen, lesen wir das
erste (zweite...vierzehnte) Byte erst einmal aus und speichern
es nun im oberen Byte einer WORD-Variablen. Ich nehme hier zum
Beispiel mal das AH-Register als oberes Byte des AX-Registers.
Um nun an die beiden Bitmasken zu kommen (die sich spter in
AH (fr A000h:0) und AL (fr A000h:1) befinden werden), mssen
wir das zwischengespeicherte Byte ein wenig nach rechts shiften.
Um wieviele stellen ermittelt man, indem man die x-Koordinate
(hier 3) durch 8 teilt und davon dann den ganzzahligen Rest
nimmt (hier also auch 3, denn 3 MOD 8 = 3). Nehmen wir an
wir hatten AX=       01101011-00000000b
dann haben wir nun:  00001101 01100000b.
Daraus ergeben sich nun die beiden Bitmasken 00001101b und
01100000b, die erste wird bei A000h:0 verwendet, die zweite
bei A000h:1 bzw. bei A000h:(3 DIV 8( und bei A000h:(3 DIV 8 + 1).

So, ich glaube da ist kein weiteres Beispiel ntig, verstehen
werdet Ihr es eh' nicht ;-), oder doch? Na hoffentlich!

Jetzt geht's aber noch einen Schritt weiter:

Wir haben nun eine Textausgabe fr einen Pseudo-Textmodus und
fr einen 'echten' Grafikmodus, wo das Zeichen beliebig auf dem
Bildschirm gesetzt werden kann.
Nun ist es aber oftmals ntzlich (so zum Beispiel im Lister),
wenn die Stelle, an die das Zeichen geschrieben wird, vorher
gelscht wird. Das heit, man gibt eine Hintergrundfarbe an,
auf die man schreiben mchte. Am einfachsten geht das, indem
man einfach das Byte '11111111b' an die angegebene Stelle
setzt (man verfhrt genauso wie oben, benutzt aber die Hinter-
grundfarbe). Dann hat man die Stelle vorher mit der Hinter-
grundfarbe berschrieben, und kann dann mit der Vordergrund-
farbe das Zeichen draufsetzen.


So, ich glaube das war's von mir und schtze einfach mal, da
noch einige Fragen offen sind, oder? Wenn ja: Schreibt!
Im Assembler-Forum findet Ihr noch ein Listing dazu (schaut
mal rein!).

Bis denne,
                                Kemil.

