                      ͻ
                       
                    
                     
   ͻ        ͼ
                  ۰
                  ۰
       ͼ   ۰
                                 ۰
                           ۰
                      ۰
                       ۰
                          ۰
                                        ۰ 
                                                   ۰
ͻ                              ۰
DIE WELT DES                                ۰
GESCHWINDIG-                     ۰
KEITSRAUSCHES                             
ͼ                   
   ͻ                                      
   PART VI                                     
   ͼ                                      



 Liebe Zielgruppe!

 Heute schreiben wir ein kleines Proggi (wer liest den ASM-Kurs eigentlich?),
 mit dem dezimale Zahlen in hexadezimale umgewandelt werden. 
 
 
 Tja, was mu das Proggi im einzelnen tun?

 1. den Bildschirm lschen, der Form wegen
 2. die Frage nach der dez. Zahl mu ausgegeben werden
 3. die dez. Zahl wird eingelesen
 4. sie mu dem Proggi irgendwie zugnglich gemacht werden
 5. nun wird die hex. Zahl ausgegeben
 6. die Frage, ob eine weitere Berechnung durchgefhrt werden soll, wird
    ausgegeben
 7. die Eingabe wird ausgewertet
 

 
 Den Bildschirm lschen
 ----------------------

 Es gibt viele Mglichkeiten, den Bildschirm zu lschen. Da wir uns nicht
 unntig bemhen wollen, berlassen wir die Arbeit dem Videointerrupt.
 Dazu mu man wissen, da der Bildschirm, beim einschalten eines Video-
 modus, gelscht wird.

 Wie schaltet man die Videomodi ein?

 Mit der Funktion 00h den Videointerrupts:


 
 --- INT 10H - AH: 00h - AL: Videomodus -------------------------------------

 Videomodi: 00h - 40*25 Zeichen,  16 Graustufen, Textmodus
            01h - 40*25 Zeichen,  16 Farben    , Textmodus
            02h - 80*25 Zeichen,  16 Graustufen, Textmodus
            03h - 80*25 Zeichen,  16 Farben    , Textmodus
            04h - 320*200 Pixel,   4 Graustufen, Grafikmodus
            05h - 320*200 Pixel,   4 Farben    , Grafikmodus
            06h - 640*200 Pixel,   2 GS (s/w)  , Grafikmodus
            07h - 80*25 Zeichen,   monochrom   , Textmodus  , am Mono-Monitor
            0dh - 320*200 Pixel,  16 Farben    , Grafikmodus
            0eh - 640*200 Pixel,  16 Farben    , Grafikmodus
            0fh - 640*350 Pixel,   monochrom   , Grafikmodus, am Mono-Monitor
            10h - 640*350 Pixel,   4 Farben    , Grafikmodus, bei 64KB  V-RAM
                  640*350 Pixel,  16 Farben    , Grafikmodus, bei 128KB V-RAM
            11h - 640*480 Pixel,   2 Farben    , Grafikmodus
            12h - 640*480 Pixel,  16 Farben    , Grafikmodus
            13h - 320*200 Pixle, 256 Farben   , Grafikmodus
 
 ----------------------------------------------------------------------------

 
 Da wir im Textmodus mit 80*25 Zeichen und 16 Farben arbeiten...:

 mov ax,0003h
 int 10h

 Schon ist der Bildschirm gelscht!


 Einen Text ausgeben
 -------------------

 Hier benutzen wir den DOS-Funktionsinterrupt, genauer gesagt die Funktion
 09h. Mit dieser Funktion kann ein beliebiger String ausgegeben werden, der
 mit '$' (hex: 24h) beendet werden mu. Steuercodes (also bell, line feed
 usw.) werden als solche ausgegeben. Der Cursor wird am Ende des Strings
 positioniert.

 
 --- INT 21h - AH: 09h ------------------------------------------------------

 In DS:DX mu der FAR-Zeiger auf den String gegeben werden.

 ----------------------------------------------------------------------------

 
 Um einen Text auszugeben, gengen ein paar Byte:

 mov ah,09h
 mov ds,cs
 mov dx,text
 int 21h

 text: db'Das ist der auszugebende Text.$'

 
 In der zweiten Zeile wird festgelegt, da der Text im selben Segment, wie
 der Code liegt. Sie kann u.U. weggelassen oder verndert werden.

 Um die nexte Zeile auszugeben, werden die Bytes 0Ah (line feed, setzt den
 Cursor eine Zeile tiefer) und 0Dh (Carriage Return, positioniert den Cursor
 am Anfang der Zeile) an den String gehngt. Ein Zeilenvorschub wird also
 mit ...,0a,0d erzeugt (oder ...,0d,0a ;-)).

 
 Ein Beispiel:

 db'Das ist Text Nr.1 in der ersten Zeile.',0a,0d
 db'Und das ist der Text der zweiten Zeile.$'

 Der Text wird so ausgegeben:
 
 Das ist Text Nr.1 in der ersten Zeile.
 Und das ist der Text der zweiten Zeile.

 
 Ein zweites Beispiel:

 db'"Der Affe ist tot!",',0a,0a,0d
 db' sprach der Vogel und starb.$'

 Dieser Text wird so ausgegeben:

 "Der Affe ist tot!",
  
  sprach der Vogel und starb.


 Einen Text eingeben
 -------------------
 
 Auch hier gibt es viele Mglichkeiten... Um die dezimale Zahl einzugeben,
 benutzen wir die Funktion 0Ah den DOS-Funktionsinterrupt.

 
 --- INT 21h - AH: 0Ah ------------------------------------------------------

 In DS:DX wird wieder ein FAR-Zeiger bergeben.

 Das erste Byte im Puffer enthlt die Anzahl der Zeichen (+1, s.u.), die
 maximal eingegeben werden sollen.

 Wurde die gewnschte Zeichenkette eingegeben, schreibt der DOS-F. die Anzahl 
 der eingegebenen Zeichen (+1, s.u.) in das zweite Byte des Puffers, erst
 ab Byte 3 folgt die Zeichenkette.

 Bei der max. Anzahl und der Anzahl der eingegebenen Zeichen mu beachtet
 werden, da das Return am Ende der Eingabe dazugerechnet wird! Das letzte
 Byte der Zeichenkette ist also immer 0Dh!

 ----------------------------------------------------------------------------

 
 Um einen String von max. 5 Byte (also eine 5-stellige Zahl z.B.) eingeben
 zu lassen, schreiben wir also folgendes:

 mov ah,0ah
 mov ds,cs
 mov dx,puffer
 int 21h

 puffer db 06

 Das war's.


 Auf eine Taste warten
 ---------------------

 Warten wir auf eine einzelne Taste, z.B. bei der Abfrage 'Nochmal (j/n)',
 wird der Interrupt 16h benutzt, der fr die Tastatur zustndig ist.
 Uns interessiert speziell die Funktion 00h. Bei dieser Funktion wartet der
 Interrupt, bis eine Taste gedrckt wird und liefert deren Code(s) zurck.

 
 --- INT 16h - AH: 00h ------------------------------------------------------

 Nach einem Tastendruck wird der Code der gedrckten Taste zurckgeliefert.

 Wenn AL=0 ist, befindet sich der erweiterte Tastaturcode in AH.
 Ist AL<>0, steht dort der ASCII-Code der Taste und in AH ihr Scancode, der
 uns im Augenblick aber nicht interessiert.

 ----------------------------------------------------------------------------

 
 Folgende Bytes halten das Proggi an, bis ein 'j' eingegeben wird.

 mark1:
 xor ah,ah
 int 16h
 cmp al,'j'
 jne mark1


 Eine Dezimalzahl wird dem Proggi bergeben
 ------------------------------------------

 Hier ist ein kleiner Algorithmus, der die Zahl bergibt:

 1. die erste (nexte) Ziffer wird gelesen
 2. wenn das Ende des Strings erreicht ist, wird die Berechnung beendet
 3. da die Ziffer als ASCII-Code vorliegt, wird '0', also 30h, subtrahiert
    (eine '0' wird zu 00h, eine '1' zu 01h usw.)
 4. es wird geprft, ob dieser Wert zulssig ist (also kein Buchstabe o..
    eingegeben wurde)
 5. der bisher errechnete Wert wird mit 10 multipliziert, die Einerstelle
    wird also 'frei gemacht'; so wird z.B. aus einer 12 eine 120
 6. jetzt wird die ausgelesene Ziffer zu diesem Wert addiert, die Einer-
    stelle 'besetzt'; zu der 120 wird z.B. eine 3 addiert =-> 123
 7. zu 1. springen

 
 Hier der Code:

 mov ds,cs           ; DS=CS, da DS fr LODSB bentigt wird, s.u.
 mov si,puffer+2     ; SI zeigt auf das erste Byte der dez. Zahl, s.u.
 mark1:
 lodsb               ; das Byte bei DS:SI in AL laden, s.u.
 cmp al,0dh          ; Ende des Strings erreicht?
 je mark2            ; wenn ja, ende
 sub al,30h          ; die Ziffer umrechnen
 jb mark3            ; wenn der ASCII-Code kleiner als '0' war, ist die
                       Eingabe falsch, Fehlermeldung ausgeben
 cmp al,09h          ; wenn der ASCII-Code grer als '9' war, ist die
 ja mark3            ; Eingabe falsch, Fehlermeldung ausgeben
 xor ah,ah           ; der bisherige Wert wird mit 10 multipliziert
 xchg ax,bx
 mov cx,000ah
 mul cx
 add bx,ax           ; zur gelesenen Stelle wird der neue Wert addiert
 jmp mark1           ; nexte Stelle abarbeiten

 mark2:              ; hier wird das Programm nach der Berechnung fortgesetzt
 .
 .
 .

 mark3:              ; die Fehlermeldung ausgeben
 mov ah,09h
 mov dx,fehler
 int 21h
 .                   ; und weiter (Proggi beenden, noch eine Eingabe
 .                   ; zulassen...)
 .

 fehler: db'Die Dezimalzahl ist nicht korrekt.$'
 puffer  db'xy65535'

 Die Zahl befindet sich dann im BX-Register.


 --- Neue Befehle -----------------------------------------------------------

 LODSB, ldt den Wert der Speicherzelle bei DS:SI in das AL-Register, danach
        wird SI automatisch um 1 erhht, zeigt also aus das nexte Byte.
        ( LODSB = mov al,b[ds:si], inc si )

 LODSW, ldt ein Word von DS:SI in AX, SI wird um 2 erhht.
        ( LODSW = mov ax,w[ds:si] / inc si / inc si )

 LODSD, (ab 386er) ldt ein DWord von DS:SI in EAX, SI wird um 4 erhht.
        ( LODSD = mov eax,dw[ds:si] / add si,4 )

 STOSB, schreibt das Byte aus AL nach ES:DI, erhht DI um 1.
        ( STOSB = mov b[es:di],al / inc di )

 STOSW, schreibt das Word aus AX nach ES:DI, erhht DI um 2.
        ( STOSW = mov w[es:di],ax / inc di / inc di )
 
 STOSD, (ab 386) schreibt das DWord aus EAX nach ES:DI, erhht DI um 4.
        ( STOSW = mov dw[es:di],eax / add di,4 )

 MOVSB, schreibt das Byte von DS:SI nach ES:DI, SI und DI werden um 1 erhht.
        ( MOVSB = mov al,b[ds:si] / mov b[es:di],al / inc si / inc di )

 MOVSW, schreibt das Word von DS:SI nach ES:DI, SI und DI werden um 2 erhht.
        ( MOVSW = mov ax,w[ds:si] / mov w[es:di],ax / add si,4 / add di,4 )
 
 MOVSD, (ab 386) schreibt das DWord von DS:SI nach ES:DI, SI und DI werden
        um 4 erhht. ( MOVSW = mov eax,w[ds:si] / mov dw[es:di],eax /
        add si,4 / add di,4 )

 ----------------------------------------------------------------------------
 
 
 Eine hex. Zahl ausgeben
 -----------------------

 Auch hier gibt es mehrer Mglichkeiten. 
 Wie wr's damit: Da wir in Part V etwas von Shift- und Rotationsbefehlen
 gehrt haben, benutzen wir sie doch einfach. Das Word in AX besteht aus
 zwei Byte, gell. Ein Byte besteht wiederum aus zwei Nibbles zu je vier
 Bit. Wie der Zufall so will, steht das hherwertige Nibble fr die erste
 und das niederwertige fr die zweite Ziffer einer zweistelligen hex. Zahl:

 Ein Beispiel: hex. Zahl     : E8h 
               binar        : 11101000
               erstes Nibble : 1110 = 0Eh
               zweites Nibble: 1000 = 08h

 Mit einem Word sieht es genauso aus, halt mit 16 Bit, 4 Nibbles und einer
 vierstelligen hex. Zahl. Wir lassen die Bits in AX also vier mal von links
 nach rechts rotieren (mit ROL). Nun steht das hchstwertige Nibble (z.B
 bei 83FAh die 8) im niederwertigen Nible von AL. Jetzt setzen wir das hher-
 wertige AL-Nibble auf Null und in AL steht die auszugebende hex. Zahl!
 Das wird fr jede Stelle, also vier mal, gemacht, ganz einfach.

 
 Der Code:

 Die auszugebende Zahl steht in AX.

 mov cx,0004h        ; wir wollen vier Ziffern ausgeben
 mark1:
 push cx             ; den Zhler merken 
 mov cl,04h          ; vier mal rotieren
 rol ax,cl
 push ax             ; AX merken
 and al,0001111b     ; das hherwertige Nible in AL lschen
 add al,30h          ; um einen ASCII-Code zu erhalten 30h addieren
 cmp al,39h
 jbe mark2           ; wenn ein Buchstabe ausgegeben werden soll, nochmal
 add al,07h          ; 07h addieren
 mark2:
 mov ah,0eh          ; die ermittelte Ziffer ausgeben
 int 10h
 pop ax              ; AX zurckholen
 pop cx              ; die Anzahl der noch zu berechnenden Ziffern holen
 loop mark1          ; wenn ntig, weitere Ziffern berechnen

 So, mehr brauchen wir nicht!

 
 Hier ist der vollstndige Code des Proggis (die eingefgten Zeilen erklren
 sich eigentlich von selbst, sollte es trotzdem Probleme geben: immer fragt
 mich!) :

 
 --- CODE -------------------------------------------------------------------

 ; * Zuerst den Bildschirm lschen. *
 
 begin:
 mov ax,0003h
 int 10h

 
 ; * Die Frage nach der Dezimalzahl ausgeben *
 
 mov ah,09h
 mov dx,frage1
 int 21h

 
 ; * Die Eingabe ermglichen. *
 
 mov ah,0ah
 mov dx,puffer
 int 21h

 ; * 'Hexadezimal: ' ausgeben *

 mov ah,09h
 mov dx,hexade
 int 21h
 
 ; * Die Dezimalzahl in's Proggi holen *
 
 xor bx,bx           ; BX lschen, damit bei einem Neustart nicht mit dem
                     ; alten Wert weitergerechnet wird 
 mov si,puffer+2     ; SI zeigt auf das erste Byte der dez. Zahl
 mark1:
 lodsb               ; das Byte bei DS:SI in AL laden
 cmp al,0dh          ; Ende des Strings erreicht?
 je mark3            ; wenn ja, weiter zur Ausgabe
 sub al,30h          ; die Ziffer umrechnen
 jb mark2            ; wenn der ASCII-Code kleiner als '0' war, ist die
                     ; Eingabe falsch, Fehlermeldung ausgeben
 cmp al,09h          ; wenn der ASCII-Code grer als '9' war, ist die
 ja mark2            ; Eingabe falsch, Fehlermeldung ausgeben
 xor ah,ah           ; der bisherige Wert wird mit 10 multipliziert
 xchg ax,bx
 mov cx,000ah
 mul cx
 jc mark2            ; ist die Zahl grer als 65535: Fehlermeldung
 add bx,ax           ; zur gelesenen Stelle wird dieser neue Wert addiert
 jc mark2            ; ist die Zahl grer als 65535: Fehlermeldung
 jmp mark1           ; nexte Stelle abarbeiten

 mark2:              ; Fehlermeldung ausgeben
 mov ah,09h
 mov dx,fehler
 int 21h
 jmp mark6           ; und eine neue Change geben ;-)

 mark3:              ; weiter
 mov ax,bx           ; den hex. Wert in AX schreiben
 

 ; * die hex. Zahl ausgeben *

 mov cx,0004h        ; wir wollen vier Ziffern ausgeben
 mark4:
 push cx             ; den Zhler merken 
 mov cl,04h          ; vier mal rotieren
 rol ax,cl
 push ax             ; AX merken
 and al,0001111b     ; das hherwertige Nible in AL lschen
 add al,30h          ; um einen ASCII-Code zu erhalten 30h addieren
 cmp al,39h
 jbe mark5           ; wenn ein Buchstabe ausgegeben werden soll, nochmal
 add al,07h          ; 07h addieren
 mark5:
 mov ah,0eh          ; die ermittelte Ziffer ausgeben
 int 10h
 pop ax              ; AX zurckholen
 pop cx              ; die Anzahl der noch zu berechnenden Ziffern holen
 loop mark4          ; wenn ntig, weitere Ziffern berechnen

 
 ; * Soll noch eine Zahl berechnet werden? *

 mark6:
 mov ah,09h
 mov dx,frage2
 int 21h

 mark7:
 xor ah,ah           ; auf eine Taste warten
 int 16h
 cmp al,'j'          ; wenn noch eine Zahl berechnet werden soll: zum Anfang
 je begin
 cmp al,'n'          ; wenn nicht: Ende
 jne mark7


 ; * Ende *

 ende:
 mov ah,4ch
 int 21h
 
 frage1: db 'Gib die Dezimalzahl ein ( 0 - 65535 ).',0a,0a,0d
         db 'Dezimalzahl: $'
 frage2: db 0a,0a,0d,'Noch eine Berechnung (j/n)? $'
 hexade: db 0a,0d,'Hexadezimal: $'
 fehler: db 0a,0a,0d,'Du hast eine falsche Dezimalzahl eingegeben!',0a,0d,'$'
 puffer: db 06
 
 ----------------------------------------------------------------------------


 Na Hochsprachenprogrammierer, neidisch? Dieses Proggi ist nur 276 Byte lang,
 davon sind 122 der eigentliche Code und 154 Daten (also der Text). Wieviel
 kB braucht's in eurer Sprache? Zehn, zwanzig...?

 NOTE: Es gibt natrlich elegantere, schnellere und platzsparendere Methoden,
       eine dez. in eine hex. Zahl umzuwandeln. Ich wollte hier eigentlich
       nur zeigen, was der eine (oder sind es zwei), der diesen ASM-Kurs
       verfolgt, zu diesem Zeitpunkt auf die Beine stellen kann (knnen
       sollte). Ich glaube, es ist mir gelungen, ein kleines Proggi zu
       erklren, das eine Mischung aus dem oben genannten ist. Es ist nicht
       sonderlich gro (gut, man knnte noch 15 Byte rausholen), nicht un-
       logisch aufgebaut und auch nicht langsam (wie kann man ein solches
       Proggi in ASM langsam machen ;-)).
 
 
 So, das war's fr heute.
  So long, Master YODA.
 
 
 Ŀ
  Wer mir eine (besser zwei) Disk(s) zusendet und das Stichwort 'Assembler'
  irgendwo auf/im Brief vermerkt, bekommt seine Disk(s) randvoll mit       
  SW/PD/FW-Tools (A86, D86...) zum Thema Assembler zurck. Dazu gibt's die 
  ASM-Kurs-Parts!                                                          
                                                                           
  Bei leerer Disk gilt: Rckporto und Rckumschlag nicht vergessen!        
 

 
 Master YODA (Manuel Mbes, Lahnstr.4, 06846 Dessau)
 
 
 NOTE: Ŀ
        Wer die letzten Parts des ASM-Kurses verpasst hat, sollte sich  
                                                                        
                               das nexte SKYLINE                        
                                                                        
        besorgen, da der zweite Part dort erscheint (natrlich mit dem  
         Einverstndnis von SolarDesign). Das SKYLINE-DiskMag bekommt   
             Ihr z.B. bei KILLER TAIFUN (Addy siehe ADDY, logisch)      
                        oder auch bei meiner Wenigkeit.                 
       

 NOTE2: Die einzelnen Parts gibt's natrlich auch bei mir, gegen Disk, Rck-
        umschlag und Porto.

 NOTE3: Sollte jemand Fehler in meinen Geschreibsel finden, mich loben,
        korrigieren, oder beschimpfen wollen, soll er mir seine Meinung mit-
        teilen!

       >>> Hi Master Yoda! Es gibt Leute die Dein ASM-Kurs interessiert,
           die aber dummerweise mir schreiben statt Dir!!! Ich solle doch
           mal die ASM Kurs Parts aus dem Platinum suchen  ... als htt'
           ich nichts anderes zu tun.
           Nochmal an alle wer Fragen hat oder etwas anderes zum ASM Kurs
           wissen will, mge doch bitte Master Yoda schreiben und nicht
           mir. Die 1.30 Rckporto msste Euch schon die Sache wert sein
           persnlich mit dem Kursleiter in Kontakt zu treten.
           
                                                                Fury

     

Yo, Master Yoda!

Auf Deine Frage, wie man Scrolly's mit Sinus im Textmodus macht, hier die
Antwort. Ich beziehe mich dabei auf das Intro vom PLT#13, dessen Source ihr
weiter unten findet. Ich mchte aber betonen, da der Code nicht von mir ist.
Ich will mir aber Mhe geben, ihn so gut es geht zu erltern. Aber hier
erst der Code:

Program Intro_Platinum_#13;

Uses Dos, Crt;

Const sSpeed             = 0;
      Sample             = 75;
      ScreenOffset       = 250;
      StringLength       = 255;
      VGASegment         : WORD = $B800;
      Txt                : STRING = 'PLATINUM #13 ------- brought 
                                     to you by SolarDesign!      ';
Var   StringTab          : ARRAY [0..255] Of WORD;
      fSegment,  fOffset : WORD;
      i, j               : WORD;
      ch                 : CHAR;
      Loop               : INTEGER;

Procedure CursorOn; ASSEMBLER;
ASM
  MOV  AH,1
  MOV  CH,12
  MOV  CL,13
  INT  10h
END;

Procedure CursorOff; ASSEMBLER;
ASM
  MOV  AH,1
  MOV  CH,32
  MOV  CL,32
  INT  10h
END;

Procedure GetFont; ASSEMBLER;
ASM
  mov   AX, 1130h;
  mov   BH, 1;
  int   10h;
  mov   fSegment, ES;
  mov   fOffset, BP;
END;

Procedure SetImage (ch : CHAR; Var Data);
  Var OffSet : WORD;
BEGIN
  OffSet := Ord (ch) * 32;
  InLine ($FA);
  PortW [$03C4] := $0402;
  PortW [$03C4] := $0704;
  PortW [$03CE] := $0204;
  PortW [$03CE] := $0005;
  PortW [$03CE] := $0006;
  Move (Data, Ptr ($A000, OffSet)^, 8);
  PortW [$03C4] := $0302;
  PortW [$03C4] := $0304;
  PortW [$03CE] := $0004;
  PortW [$03CE] := $1005;
  PortW [$03CE] := $0E06;
  Inline ($FB);
END;

Procedure Init;
  Var CharSet : ARRAY [0..7] Of BYTE;
      i       : BYTE;
BEGIN
  If (LastMode = 7) Then
    VGASegment := $B000;
  TextMode (Font8x8 + CO80);
  TextColor (White);
  ClrScr;
  GotoXY (1,1);
  Mem [$B800:1] := 0;
  For i := 0 To 7 Do
    BEGIN
      FillChar (CharSet, SizeOf (CharSet), 0);
      CharSet [i] := 3;
      SetImage (Chr (128 + i), CharSet);
    END;
END;

Procedure GenerateTab;
  Var i : BYTE;
BEGIN
  For i := 0 To 255 Do
    StringTab [i] := Round (Sin (2 * Pi * i / StringLength) * Sample) + 
      ScreenOffset;
END;

Procedure Scroll;
  Var PosTab                          : ARRAY [0..79, 0..7] Of WORD;
      BitMap                          : ARRAY [0..79, 0..7] Of BYTE;
      sCtr, tCtr, CurChar, l, b, x, y : BYTE;
BEGIN
  FillChar (PosTab, SizeOf (PosTab), 0);
  FillChar (BitMap, SizeOf (BitMap), 0);
  sCtr := 0;
  tCtr := 1;
  Repeat
    CurChar := Ord (Txt [tCtr]);
    tCtr := 1 + tCtr Mod Length (Txt);
    For b := 0 To 7 Do
      BEGIN
        Move (BitMap [1,0], BitMap [0,0], SizeOf (BitMap));
        For l := 0 To 7 Do
          If (((Mem [fSegment:fOffset + 8 * CurChar + l] Shl b) And 128) 
             <> 0) Then

            BitMap [79,l] := 1

          Else
            BitMap [x,y] := 0;
        While ((Port [$3DA] And 8) <> 0) Do;
        While ((Port [$3DA] And 8) = 0) Do;
        For x := 0 To 79 Do
          For y := 0 To 7 Do
            Mem [VGASegment:PosTab [x,y]] := 32;
        For x := 0 To 79 Do
          For y := 0 To 7 Do
            BEGIN
              PosTab [x,y] := (y + (StringTab [(sCtr + x) Mod StringLength] 
                Div 8)) * 160 + x + x;

              If (BitMap [x,y] = 1) Then

                Mem [VGASegment:PosTab [x,y]] := 128 + StringTab [(sCtr + x) 
                    Mod StringLength] Mod 8;

            END;
        sCtr := (sCtr + sSpeed) Mod StringLength;
      END;
  Until KeyPressed;
END;

BEGIN
  Init;
  GetFont;
  GenerateTab;
  Scroll;
  TextMode (LastMode);
END.


Also:

  Die Prozedur "Init" setzt als erstes den neuen Text-Modus (90x30).

  Die Prozedur "GetFont" tut nichts anderes als die Adresse des eingebauten
Standardzeichensatzes in ES:BP zu schreiben.

  In "GenerateTab" wird eine Sinus-Tabelle erzeugt und in "StringTab" ge-
speichert. Das erspart die ewige Rechnerei BEI der Darstellung.

  Die Prozedure "Scroll" schlielich setzt die ganze Geschichte in Marsch.

  Das einzige, wo ich nicht hinter gekommen bin: Was zum Henker machen die
ganzen PortW-Befehle in "SetImage"? Wer kann mir da helfen?

  Vielleicht hat das je einigen geholfen,

>>> J'Role

     
