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.