Assembler für Einsteiger - Teil 7 ----------------------------------- von Tim-Philipp Müller Nachdem wir uns bisher schon eine Menge mit den Möglichkeiten des Computers beschäftigt haben, stellt sich nun die Frage, wie man denn mit der Außenwelt- der Peripherie- Kontakt aufnehmen kann. Dazu gibt es drei Möglichkeiten: - die s.g. CIO - Central Input/Output - die s.g. SIO - Seriell Input/Output - direkte Hardware-Programmierung Letztere ist sehr aufwendig und kompliziert, deswegen wird sie hier nicht behandelt. Die CIO ist sehr flexibel, da sie mit jedem 'Handler' (Treiber) benutzt werden kann. Dazu gehören Drucker(P:), Keyboard(K:), Editor(E:), Screen(S:), Kassettenrekorder(C:) und -wenn ein DOS installiert ist die Floppy(D:). Werden andere Treiber installiert, z.B. für eine RS-232-Schnittstelle oder eine Window-Verarbeitung, kann die CIO auch dafür benutzt werden. Mit der SIO lassen sich alle Geräte am Seriellen Bus betreiben, das wären die Floppy, der Kassettenrekorder, der Drucker (oder was haben Sie da sonst noch angeschlossen). Die Unterschiede zwischen CIO und SIO werden Sie wohl selbst beim Durchlesen erkennen..... Lassen Sie sich durch die folgenden 'geballten Informationen' nicht stören! Es ist nicht so kompliziert! Auch diesmal befinden sich auf der Rückseite der Disk wieder einige einfache, erläuterte Beispiele. Wie immer *.ASM für den BIBO-Assembler und *.SRC für Atmas. ----- CENTRAL INPUT/OUTPUT: CIO Die CIO stellt 8 Kanäle zur Verfügung (sie kennen das ja vom BASIC). Für jeden Kanal existiert ein 16 Byte langer Informationsblock, der jeweils folgendermaßen aufgebaut ist: $342 ICCOM Kommando $343 ICSTA Status,Fehlercode $344/$345 ICBADR Adresse $348/$349 ICBLEN Datenlänge $34A ICAUX1 Hilfsregister 1 $34B-$34F ICAUX2-6 Hilfsregister 2-6 $E456 CIOV Einsprungvektor Das sind alle Register, die man braucht und am Anfang eines Programms festlegen sollte (ICAUX2-6 kann man sich meist sparen). --- Kommando 3: OPEN Öffnet einen Kanal. ICBADR muß auf die Dateispezifikation zeigen. ICAUX1+2 sind vom jeweiligen Gerätetreiber abhängig (siehe später). Dateispezifikation: -Gerätekürzel (D,E,K,C...) -Gerätenummer (wenn nicht da =1) -Doppelpunkt ':' -Filename (max. 8 Zeichen, erstes keine Ziffer) -Punkt '.' -Extender (max. 3 Zeichen) -EOL ($9B,155) --- Kommando 12: CLOSE Schließt einen Kanal. --- Kommando 7: BGET (Get Characters) Liest einen Datenblock beliebiger Länge ein. ICBLEN muß die Länge enthalten, ICBADR die Adresse, an die die Daten gelesen werden sollen. Hat ICBLEN den Wert 0, wird ein Byte in den Akku gelesen. Nach Rückkehr enthält ICBLEN die Anzahl der tatsächlich übertragenen Bytes. --- Kommando 11: BPUT (Put Characters) Schreibt einen Datenblock beliebiger Länge. ICBLEN gibt die Länge an, ICBADR zeigt auf den Speicherbereich. Hat ICBLEN den Wert 0, wird das im Akku stehende Byte gesaved. Nach Rückkehr enthält ICBLEN die Anzahl der tatsächlich übetragenen Bytes. --- Kommando 5: INPUT (Get Record) Liest so lange Zeichen ab der in ICBADR angegeben Adresse ein, bis entweder die in ICBLEN angegebene Anzahl eingelesen ist, oder ein End-of-Line Zeichen (EOL $9B,155) auftritt. Im ersten Fall wird trotzdem bis zum nächsten EOL Zeichen gewartet, und dann ein Error #137 ausgegeben ('Truncated Record'). Nach Rückkehr enthält ICBLEN die Anzahl der tatsächlich gelesenen Zeichen. --- Kommando 9: PRINT (Put Record) Schreibt einen Datenblock mit der in ICBLEN angegeben Maximallänge von ICBADR an. Enthält der Buffer kein EOL, wird hinten automatisch eins angehängt. --- Kommando 13: Get STATUS Liest den Status des Geräts ein. Danach enthalten folgende Register Infos: (man braucht dieses Kommando eigentlich nicht, denn die CIO meldet nach allen Operationen ja genaue Fehlercodes zurück.) $2EA DVSTAT siehe unten bei SIO.. $2EB FSTAT siehe unten bei SIO.. $2EC Timeout-Wert des Geräts $2ED Zahl der Zeichen im Ausgabepuffer --- Kommando größer 13: SPECIAL Spezial-Kommandos für die verschiedenen Geräte. Siehe auch unten. Die Spezial-Kommandos kann man alle auch ohne voriges Öffnen des Kanals anwenden, wenn ICBADR auf die Dateispezifikation zeigt. Man benutzt folgende Programierung, um die verschiedenen Kanäle anzusteuern: LDX #Kanal*16 LDA #3 OPEN-Kommando STA ICCOM,X LDA #FN STA ICBADR,X ... ... JSR CIOV BMI ERROR negativ=Error? RTS ERROR ... ... Vor dem Einsprung in die CIO durch CIOV müssen alle Register gesetzt werden. Das X-Register muß die Kanal-Nummer mal 16 enthalten (jeder IOCB-Block für einen Kanal ist ja 16 Bytes lang). Bei der Rückkehr liefert die CIO im Y-Register einen evtl. Fehlercode. Ist kleiner 128 (also positiv), ist kein Fehler aufgetreten. Andernfalls (wenn negativ) gibt die Fehlernummer an, die auch in ICSTA enthalten ist. Fehlernummern: 128 BREAK wurde gedrückt 129 Kanal bereits geöffnet 130 Gerät nicht vorhanden (z.B. D1:*.* ohne DOS angesteuert) 131 Kanal nur für Ausgabe geöffnet 132 Ungültiger Befehl 133 Kanal ist noch nicht geöffnet 134 Kanalnummer fehlerhaft 135 Kanal nur für Eingabe geöffnet 136 Ende der Datei (End-of-File,EOF) 137 Record zu lang 138 Gerät antwortet nicht (auf OFF) 139 Gerät arbeitet fehlerhaft 140 Fehler am seriellen Bus 141 Cursorposition falsch 142 serieller Übertragungsfehler 143 Prüfsummenfehler (bei Kass. z.B.) 144 Sektor nicht schreib-/lesbar Floppyhebel offen? Schreibschutz? 145 Fehler bei Überprüfung 146 Kommando nicht anwendbar 147 zu wenig Speicherplatz (z.B. beim GRAPHICS- Befehl) 160 Falsche Laufwerksnummer 161 zu viele Dateien offen 162 Diskette voll 163 unbekannter Fehler! 164 Datei-Links zerstört (defekt!) 165 Falscher Dateiname 166 POINT-Befehl falsch 167 Datei schreibgeschützt (protected) 168 ungültiges Kommando 169 Inhaltsverzeichnis voll 170 Datei nicht gefunden 171 POINT ungültig 255 Formatierfehler Die Beschreibung der speziellen Eigenschaften der Kommandos für die einzelnen Geräte: ----- DISKETTENSTATION (D:) OPEN: AUX1 - 4: Datei lesen 8: Datei schreiben 12: Lesen+Schreiben 9: an Datei anhängen 6: Directory lesen Mit einem OPEN #x,8,0,"D:DOS.SYS" wird automatisch das DOS auf die Disk geschrieben. CLOSE: File wird in Directory gesichert SPECIAL: --- KOMMANDO 32: RENAME Benennt eine Datei um. Dateispezifikation: D1:altfile.ext,neufile.ext --- Kommando 33: DELETE --- Kommando 35: PROTECT --- Kommando 36: UNPROTECT Löscht,schützt bzw. entschützt eine Datei. Dateispez.: D1:filename.ext --- Kommando 37: POINT --- Kommando 38: NOTE Diese Befehle sollten nur von Fortgeschrittenen verwendet werden (lest Zusatz-Artikel!) POINT legt die Schreibposition des durch ICBADR adressierten Files fest, NOTE ermittelt die momentane Schreibposition des in ICBADR adressierten Files. Aux3+4: Sektornummer Aux5: Bytenummer im Sektor Anwendung dieser Kommandos: Stellen Sie sich vor,Sie haben eine Datei, in der Sie z.B.die Beschreibung aller Orte eines Adventures haben. Nun können Sie ermitteln, wo jeweils der Anfang der Texte für die einzelnen Räume sind. Das Programm kann dann auch direkt auf diese Textstellen zu- greifen, ohne vorher alle anderen Daten lesen zu müssen. --- Kommando 253 FORMAT SINGLE --- Kommando 254 FORMAT Formatiert eine Disk. Kommando 254 unterscheidet sich nur bei DOS 2.5 oder kompatiblen vom Kommando 253. Dann wird die Disk in Medium Density forma- tiert. Einige DOS orientieren sich beim Kommando 254 an Aux2, in welcher Dichte formatiert wird. Beispiel BIBO-DOS: Aux2=0: Single Density =1: Double Density =2: Medium Density =33: Quad Density (nur BIBO-Dos 6.x) =128:Clear Disk (löscht VTOC+Dir.) ----- Screen(S:) OPEN: Aux1- Bit 2: Kanal für Schreiben Bit 3: Kanal für Lesen Bit 4: Fenster wird unten eingeblendet. Bit 5: Screen nicht löschn Aux2- Grafikstufe (0-15) Der Grafikscreen wird unter RAMTOP ($6A,106) gelegt. APPMHI ($E,14) sollte auf das höchste belegte Byte zeigen.Ist zwischen den beiden Registern nicht genug Platz, gibt's einen Error 147. GET: Mit den beiden Funktionen können Daten vom Screen gelesen werden. Dabei wird immer die Farbe bzw. der Atascii-Code der Cursorpos- ition angegeben. Diese wird in $54 ROWCRS für die Zeile und $55,$56 COLCRS für die Spalte abgelegt. PUT: Durch diese Funktionen kann ein Zeichen oder ein Punkt auf dem Screen gesetzt werden.Ausgegeben werden die Farb-Nummer oder der Atascii-Wert. SPECIALS: --- Kommando 17: DRAW Zieht eine Linie von der zuletzt benutzten Cursorposition zur in $54-$56 angegeben Position. Es wird die Farbe in ATACHR ($2FB) verwendet. --- Kommando 18: FILL (Halbperfekte Füllroutine) Zuerst muß man die Umrisse der Form mit DRAW zeichnen. Für die rechte begrenzung benutzt man nun in der oben angegebenen Form dieses Kommando. Es wird dann von jeden Punkt der Linie so lange nach rechts gezeichnet,bis man auf einen Punkt der gleichen Bildschirmfarbe trifft !!! ----- KASSETTENREKORDER (C:) OPEN: Aux1= 4:Schreiben 8:Lesen CLOSE: Am Ende jedes Files benutzen. ----- EDITOR(E:) Ist quasi wie der 'S:'-Handler, nur: - verwendet bei der Eingabe (GET) die Tastatur als Eingabequelle. - ermöglicht das Editieren logischer Zeilen (3 Zeilen = 1 logische Zeile) - verwendet bei der Zeichenausgabe Spezial-Codes für Editier-Funktionen: $1B ESCape $7E Zeichen zurück $1C Cursor hoch $7F TABulator $1D Cursor runter $9B Return,EOL $1E Cursor links $9C Zeile löschen $1F Cursor rechts $9D Zeile einfügen $7D Screen löschen $9E Tabulator weg $FD Summton $9F set Tabulator $FE Zeichen löschn $FF Zeichen insert - die eingegebenen Daten werden erst nach einem EOL für das Programm ver- fügbar. Leerzeichen am Anfang einer Eingabe werden 'eliminiert'. --- KEYBOARD (K:) und DRUCKER (P:) OPEN: Aux1: Keyboard =4 für lesen Drucker =8 zum Schreiben Ansonsten Länge und Dateispezifikation wie normal setzen. Die vom Keyboard eingelesenen Daten werden nicht auf den Bildschirm angezeigt. ------- SERIELL INPUT/OUTPUT: SIO Die SIO ermöglicht Kommunikation mit externen Geräten auf einer Stufe unter der CIO. Dabei ist keine universelle Programmierung für verschiedene Geräte möglich, vielmehr muß man exact unterscheiden. Daher gibt es auch für die veschiedenen Geräte verschiedene Kommandos. Für die SIO gibt es einen Befehlsblock: $300 * DDEVIC Geräte-Kennung $301 DUNIT Geräte-Nummer $302 DCOMND Geräte-Befehl $303 * DSTATS Datenrichtung,Error $304,$305 DBUF Datenblock-Adresse $306 * DTIMLO Timeout-Wert $307 * immer auf 0 setzen $308,$309 * DBYTE Blocklänge $30A,$30B DAUX Zusatzregister $E459 SIOV SIO-Einsprungvektor ----- PRINTER DDEVIC $40 DUNIT 1 oder 2 DCOMND W ($57) Schreiben S ($53) Status DSTATS Vorher: Bei W=$80, bei S=$40 Nachher: Status, >127=Fehler DBUF Adresse des Druck-Buffers DTIMLO $1E DBYT Länge des zu druckenden Textes ----- KASSETTENREKORDER DDEVIC $60 DUNIT 0 DCOMND R ($52) Lesen W ($57) Schreiben DSTATS Vorher: Bei W=$80, bei S=$40 Nachher: Status, >127=Fehler DBUF $3FD (Adresse des Kassetten- buffers CASBUF) DTIMLO $23 DBYT $83 (Recordlänge) DAUX1 0 DAUX2 128=kurze Lücken zwischen den Records 0=lange 'Gaps' zwischen den Records ----- DISKETTENSTATION * DDEVIC $31 DUNIT 1-8 für die einzelnen Floppies DCOMND siehe unten * DSTATS Vorher: Bei Format und Schreiben: $80 Bei Status und Lesen: $40 Nachher: 1=ok, >127 Fehler DBUF Adresse des Datenblocks * DTIMLO Bei Format: $A0, sonst $7 * DBYT Sektorlänge (normal ist $80) DAUX Sektornummer Für die Floppy gibt es eine Einsprungs- Routine (DSKINV $E453), die Operationen mit normalem Format (Single,Medium) ein bischen erleichtert: Es müssen nämlich alle mit einem '*' versehenen Register nicht mehr gesetzt werden. Bei der DSKINV-Routine funktionieren nur die Kommandos $21,$52,$53,$57. Schreiben mit Verify geht nur bei XL/XE Die Kommandos: ! $21 Formatieren Single " $22 Formatieren Medium N $4E Percom-Block lesen O $4F Percom-Block schreiben P $50 Sektor mit Überprüfung schreiben W $57 Sektor ohne 'Verify' schreiben R $52 Sektor lesen S $53 Status einlesen Die DSKINV-Routine setzt beim Status- Kommando den Buffer automatisch auf $2EA DSTAT. Die ATARI 815 (und XF551) sowie alle mir bekannten Floppy-Speeder besitzen einen internen Konfigurationsblock, PERCOM-Block genannt. Dieser ist 12 Bytes lang und wie folgt aufgebaut: Byte SD MD DD 0 Zahl der Spuren $28 $28 $28 1 Schrittrate xx xx xx 2,3 Sektoren pro Spur $12 $1A $12 4 Zahl der Köpfe-1 xx xx xx 5 Dichte $00 $04 $04 6,7 Bytes pro Sektor $80 $80 $100 8 Laufwerk ein/aus xx xx xx 9 Übertragungsrate xx xx xx 10,11 reserviert xx xx xx ------ Bei den Doppelbytes kommt immer ERST das HI, dann das LO-Byte !!!! ---- Alle mit xx bezeichneten Bytes sollten nicht verändert werden. Außerdem ist angegeben, welche Werte die Register normalerweise bei den drei Densities haben. Möchte man Double Density formatieren, muß man den Percom ändern und zurück- schicken, sowie das 'Format Single' Kommando anwenden. Irgendwie habe ich es auch noch nicht geschafft, die ersten 3 Sektoren einer in Double Density formatierten Disk mit einer 256 Byte- Anforderung zu lesen (sondern nur mit 128) Byte. Entweder hab ich da wohl den Kniff noch nicht raus, oder die Floppy behandelt diese als Bootsektoren, die ja sowieso nur mit 128 Bytes pro Sektor gebootet werden (auch bei DD!). Da sich die XF551 nicht automatisch auf das Format der eingelegten Disk ein- stellt, muß man vorher einen Sektor aus Track 0 einlesen, aber nicht Sektor 1-3 (also Sektoren 4-18). (Diese Info konnte ich noch nicht testen.) Das Status-Kommando liefert folgende Werte (der Block sollte nach $2EA DSTAT gelesen werden): $2EA DSTAT Bit 7: Enhanced Density Bit 6: reserviert Bit 5: Double Density Bit 4: Motor an Bit 3: Schreibgeschützt Bit 2: Schreib-/Lese-Fehler Bit 1: Falsche Daten Bit 0: Falsches Kommando $2EB FSTAT Bit 7: Floppy-Hebel offen B6 =0: Write Protect B5 =0: Record Type B4 =0: RNF Error B3 =0: CRC Error B2 =0: Data Lost B1 =0: Data Request B0 =0: FDC Busy Die FSTAT-Werte können je nach Floppy und eingebautem FDC Chip verschieden sein. $2EC gibt Timeout an (meist $E0) $2ED reserviert Nach dem Einsprung durch SIOV oder DSKINV wird im -Register,wie bei der CIO, der Status mitgeteilt. Ist dieser größer 127, gibt er den Fehlercode an. Viele Floppy-Speeder unterstützen noch weitere Kommandos, die man jedoch im Speeder- Handbuch nachlesen kann. Wie kann man die einzelnen Floppies unterscheiden (falls das nötig ist)? - Eine Normale 1050 hat keinen PERCOM- Block (also tritt beim Lesen der 'Kommando-kenn-ich-nicht-Fehler' auf. - Die XF551 besitzt zwei Köpfe. - Bei der TURBO 1050 kann man die mit 'xx' im Percom-Block gekennzeichneten Bytes nicht ändern. - Bei der SPEEDY 1050 und HAPPY 1050 existieren spezielle Kommandos, die von anderen Speedern nicht unterstüzt werden (ich kenn' sie allerdings noch nicht, da ich noch keine Speedy habe). Zum Schluß noch ein Beispiel zum Lesen eine Sektors (z.B. $169): DUNIT=$301 DCOMND=$302 DBUFLO=$304 DAUX1=$30A DSKINV=$E453 BUF=$3F00 RSEC LDA #1 Floppy 1 STA DUNIT LDA #'R Sektor lesen STA DCOMND LDA #BUF ab BUF STA DBUFLO LDA /BUF STA DBUFLO+1 LDA #$169 Sektor $169 STA DAUX1 LDA /$169 STA DAUX1+1 JSR DSKINV und los.. BMI .1 Fehler? RTS nein! .1 TYA doch! LSR LSR Fehlernummer LSR anzeigen LSR Bits 4-7 TAX LDA FTAB,X STA ERRZ+9 TYA AND #$F Bits 0-3 TAX LDA FTAB,X STA ERRZ+10 PLA JSR nach RSEC PLA unschädlich machen .2 LDA $D01F AND #1 Bis gedrückt BNE .2 JMP START Neustart d. Programms FTAB .AT "0123456789ABCDEF" ERRZ .AT " Fehler $xx aufgetreten ! " START ... JSR RSEC ... Soweit,so gut. Tschüß Diesem Artikel ist ein Zusatz-Artikel beigefügt, der beschreibt, wie ein DOS 2.xx die Sektoren der Diskette nutzt und belegt und wie man eigene Programme als Boots an den Anfang der Diskette schreibt. Und nächstes Mal geht's ums heikle Thema Finescrolling....