← ST-Computer 07 / 1986

ISAM & PRIMA: Zwei Assembler-Macro-Modulbibliotheken

Software

Die ISAM- und PRIMA-Macrobefehle sind in der hier veröffentlichten Form fĂŒr den SEKA-Assembler der englischen Firma KUMA gedacht. Falls man einen anderen Macro-Assembler benutzen möchte, muß man die Macromodule gegebenenfalls an dessen Macrosyntax anpassen. Die Standardroutinen können unverĂ€ndert ĂŒbernommen werden, sofern der andere Assembler die Standard-Motorola Mnemoniks beherrscht.

Beide Bibliotheken sind von Gerhard Pritz aus Berlin erstellt und von uns fĂŒr die ST Computer erworben worden. Die Source-Listings werden von der nĂ€chsten Ausgabe ab regelmĂ€ĂŸig veröffentlicht. In dieser Ausgabe soll das Modulpaket zunĂ€chst erst einmal vorgestellt und eine kurze Einleitung gegeben werden. Eine komplette Veröffentlichung in einer Ausgabe wĂŒrde den Rahmen der ST Computer sprengen und außerdem die vielen Assembleruninteressierten stark benachteiligen. Die Listings sind natĂŒrlich auf den jeweiligen, zur Ausgabe gehörigen, Disketten vorhanden. Ferner kann man das komplette Paket, also ISAM und PRIMA, fĂŒr ganz Eilige schon jetzt auf einer Extra-Diskette fĂŒr DM 49,- + DM 5,- Versandkosten, gegen Vorausscheck oder per Nachnahme, beim Heim-Verlag in Darmstadt, beziehen (beiliegende Software-Bestellkarte verwenden).

Um nun erst einmal zu erklĂ€ren, was ISAM und PRIMA ĂŒberhaupt sind bzw. beinhalten, wollen wir darauf kurz eingehen.

ISAM ist die AbkĂŒrzung fĂŒr Indexed Sequential Access Method. Es handelt sich also um eine index-sequentielle Dateizugriffsmethode. Eine ISAM-Datei kann wahlfrei, also mit Direktzugriff auf einen ganz bestimmten Satz, oder auch sequentiell vorwĂ€rts oder rĂŒckwĂ€rts verarbeitet werden. Dadurch entsteht ein enormer Geschwindigkeitsvorteil beim Suchen von Daten.

Um nun aber die ISAM-Macros verwenden zu können, muß man zuerst die PRIMA-Macros besitzen, da diese im Sourcecode des ISAM verwendet werden. Aus diesem Grund werden zunĂ€chst die Sourcelistings der PRIMA-Macros bei uns veröffentlicht.

Hinter dem Namen PRIMA verbirgt sich einfach mehr oder weniger der Name des Autors, da es die AbkĂŒrzung fĂŒr Pritzen’s Machwerk darstellt. In PRIMA sind eine Menge an allgemeinen Macros und Standardroutinen vereinigt, die einem das Programmieren in Assembler vereinfachen sollen.

Das gesamte Macro-Paket ist in vier Teile mit folgenden Macromodulen unterteilt:

1. Allgemeine Macros

  • Delay = Warteschleife
  • Repeat = Wiederholungsrate der Tastatur festlegen
  • Compare = Vergleichen zweier Felder
  • Gemdos = Aufruf einer GEMDOS-Funktion
  • Conin = Eingabe eines Zeichens von Tastatur mit Warten
  • Inkey = Eingabe eines Zeichens von Tastatur ohne Warten
  • Control = Ausgabe von Control-Anweisungen an den Bildschirm
  • Controlm = Mehrfache Ausgabe derselben Control-Anweisung
  • Char = Ausgabe eines Zeichens an aktueller Cursorposition
  • Pos = Positionierung des Cursors
  • Transfer = Übertragen von Daten
  • Fill = FĂŒllen eines Feldes
  • Print = Textausgabe auf Bildschirm mit Zeilenvorschub
  • Printx = Textausgabe auf Bildschirm ohne Zeilenvorschub
  • Prints = Speicherinhalt auf Bildschirm ausgeben
  • Zeile = Zeilenvorschub (Carriage Return und Fine Feed)

2. Diskettenmacros

  • Open = Eröffnen von Dateien
  • Close = Schließen von Dateien
  • Extend = Daten an bestehende Datei anhĂ€ngen
  • Fof = Satznummer des letzten Record ermitteln
  • Get = Bestimmten Datensatz lesen
  • Put = Bestimmten Datensatz schreiben
  • Read = NĂ€chsten Datensatz lesen (sequentiell)
  • Write = NĂ€chsten Datensatz schreiben (sequentiell)
  • Diskerror = Disketten-Fehlerbehandlungsroutine

3. Standardroutinen

  • Input = Eingabe von Zeichen von der Tastatur
  • Numeric = Eingabe von numerischen Zeichen von der Tastatur
  • Abgleich = Abgleichroutine fĂŒr Kommastellen
  • Ueplus = Überlaufkontrolle fĂŒr Addition und Subtraktion
  • Plus = Addition
  • Minus = Subtraktion
  • Durch = Division
  • Mal = Multiplikation
  • Kneif = Abschneiden der Kommastellen ohne Runden
  • Round = Runden der Kommastellen
  • Binasc = Umwandlung von binĂ€r nach ASCII
  • Ascbi = Umwandlung von ASCII nach binĂ€r
  • Divi = 32 Bit Division
  • Multi = 32 Bit Multiplikation
  • Edit = Editierroutine
  1. ISAM-Macros
  • Keylen = SchlĂŒssellĂ€nge festlegen
  • Isam = ISAM-Funktionsroutinen

In den ISAM-Macros wird die eigentliche Arbeit nicht durch die beiden Macros KEYLEN und ISAM geleistet, sondern durch die folgenden ISAM-Funktionsroutinen:

  • QWRITE = Schreiben
  • QSEARCH = Suchen
  • QREAD = Lesen
  • QREAD__R = RĂŒckwĂ€rts lesen
  • QEQ HI = Gleichen oder höheren SchlĂŒssel suchen
  • QEQ LO = Gleichen oder niedrigeren SchlĂŒssel suchen

Nicht nur fĂŒr Profis

Das gesamte Paket ist als Handwerkszeug fĂŒr Assembler-Programmierer und fĂŒr die, die bis jetzt nur flĂŒchtigen Kontakt mit einem Assembler gehabt haben, gedacht. Es verkĂŒrzt die Arbeitszeit bei der Programmerstellung erheblich, befreit von vielen Routinearbeiten und lĂ€ĂŸt Raum fĂŒr die Konzentration auf das eigentliche Programmierproblem .

Es soll hier weder ein Kurs in 68 000 Assembler abgehalten noch haarklein auch die letzte Feinheit der Anwendung erklĂ€rt werden. Ebenso wird vorausgesetzt, daß man sich mit seinem Assembler (etwas) vertraut gemacht hat. Man sollte also zumindest wissen, wie man ein Assembler-Sourcecode lĂ€dt, assembliert und wieder abspeichert. Die genauen Befehle mit ihrer Syntax kann man ja dem mitgelieferten Handbuch entnehmen, auch wenn es beim SEKA-Assembler etwas mager ausgefallen ist.

Dies alles soll AnfĂ€nger natĂŒrlich nicht abschrecken, sondern sie ganz im Gegenteil eher ermutigen. Gerade fĂŒr den Beginner wird diese Macroroutinensammlung zum wertvollen Arbeitsmittel werden und den Einstieg in die Assemblerprogrammierung vereinfachen.

Wenn man am Anfang noch bei jedem kleinen Macro nachschlagen muß, so wird doch bald alles zur Routine, und man wird nur noch bei Besonderheiten nachlesen. Eine weitere Hilfe bei Fragen dĂŒrften die Macrodefinitionen und die Beispielprogramme liefern.

Zum eigentlichen Assembliervorgang sei folgendes gesagt. Man lĂ€dt zuerst den Sourcecode PRIMA.S, danach, falls das eigene Programm ISAM-Macros benutzt, ISAM.S und zuletzt das eigene Programm. Anschließend wird ganz wie gewohnt assembliert.

PRIMA gibt automatisch den nicht benötigten Speicherplatz an das GEM-DOS zurĂŒck. HierfĂŒr ist unbedingt eine gerade Anzahl von Bytes des Gesamtprogramms erforderlich. Die GEMDOS-Funktion SETBLOCK ($ 4A) verursacht nĂ€mlich einen Totalabsturz, wenn eine ungerade Anzahl von Bytes vor liegt. Abhilfe kann man da leicht mit der EVEN-Instruktion schaffen, die zuletzt vor dem END angegeben werden muß.

Ein Stack von 300 Bytes wird von PRIMA automatisch eingerichtet. Wenn man mehr als diese 300 Bytes Stack benötigt, kann man wie gewohnt einen eigenen Stack am Anfang des Programmes einrichten. Andernfalls braucht man sich ĂŒberhaupt nicht um den Stack zu kĂŒmmern, da er einfach vorhanden ist. Eine Ausnahme ist dann zu beachten, wenn man mit dem SEKA-Assembler Debugging betreibt. In diesem Falle muß die erste Instruktion des Programmes folgendermaßen lauten:

START: LEA QSTACK+300,SP

Unter Debug startet man das Programm dann mit der G-Anweisung (in diesem Falle GSTART). Das Label START ist natĂŒrlich nicht zwingend, es kann auch ein anderer Labelname genommen werden. QSTACK darf nicht definiert werden, da PRIMA es schon gemacht hat.

Wenn das Programm fertig ausgetestet ist und selbstĂ€ndig ohne Debug laufen soll, kann die Anfangsinstruktion wieder entfernt werden. Falls man es vergißt, schadet es aber auch nichts.

Allgemeines zum Format

Ein Macromodul wird durch den Macronamen aufgerufen, dem, je nach Macro, eine bestimmte Anzahl an Parameter folgen. Folgende Parameter können zulÀssig sein:

  • Register
  • unmittelbare Daten (#UD)

  • Label (Feldadressen)

  • Label (Feldinhalte)
  • "Literal”
  • Funktionsnamen (FUNKTION)
  • sonstige numerische Angaben

Was fĂŒr den Einzelfall gilt, kann man den Beispielen, den Macrobeschreibungen oder, was im Zweifelsfall am besten ist, den Macrodefinitionen selbst entnehmen.

Sowohl bei den Macros als auch bei den Standardroutinen bleiben die RegisterstĂ€nde unverĂ€ndert; es sei denn, das betreffende Macro oder die Routine meldet in einem vereinbarten Register einen RĂŒckkehrwert (z. B. einen Fehlercode). Eine Ausnahme bildet hier das Adressregister A0, das nach Beendigung des Macros bzw. der Routine einen anderen Inhalt haben kann.

Die Parameter

  1. Register

Sofern eine Registerangabe zulÀssig ist, wird der Inhalt des angegebenen Registers zur Verarbeitung herangezogen.

Beispiel: CHAR D5

Hiermit wird das im Register D5 enthaltene Zeichen auf den Bildschirm gebracht. Man muß bei der Registerangabe auf das LĂ€ngenattribut achten, da die Registerdaten als Byte, Wort oder Langwort gefordert sein können.

  1. unmittelbare Daten

Unter unmittelbaren Daten versteht man z. B. # 12, d. h. die Zahl 12 wird verarbeitet.

Beispiel: GET 1,# 12,D1

Der Datensatz mit der Nummer 12 wird aus der Datei 1 gelesen und anschließend an die in dem Datenregister Dl enthaltene Speicheradresse geschrieben.

  1. Label

Mit Label sind Marken gemeint, die irgendwo im Programm als Feldnamen definiert wurden. Das Doppelkreuz gibt hierbei an, daß die Adresse des Feldes und nicht der Inhalt benutzt wird.

Beispiel:

PRINTS # FELDl FELDl: DC ”Ausgabetext”,0

Es wird der Text ausgegeben, der ab der Adresse FELDl im Speicher zu finden ist. In unserem Beispiel wird die Ausgabe dann beendet, wenn eine binÀre Null gefunden wird.

  1. Label

Label ohne ein Doppelkreuz sind ebenfalls im Programm definierte Feldnamen, jedoch wird hier der Inhalt des Feldes und nicht seine Adresse angesprochen.

Beispiel: PUT 2, NUMMER,# PUFFER NUMMER: DC.L 4712 PUFFER: BLK 120

Es wird der Datensatz mit der Recordnummer 4712 in die Datei mit der Nummer 2 geschrieben und zuvor die Satzdaten ab der Adresse PUFFER geholt.

  1. ”Literal”

Hiermit sind in AnfĂŒhrungszeichen eingeschlossene, alphanumerische Werte gemeint. Überall, wo Literais zulĂ€ssig sind, können niemals die Formen # Label oder Label Verwendung finden. Literais mĂŒssen immer zwischen zwei AnfĂŒhrungszeichen stehen.

  1. Funktionsnamen

Damit sind ganz bestimmte festgelegte Funktionsnamen fĂŒr bestimmte Macros gemeint.

Beispiel: CONTROL CLS

CLS ist hier der Funktionsname fĂŒr Bildschirm löschen (Clear Screen). So werden unter anderem alle CON-TROL-Sequenzen ĂŒber solche Funktionsnamen aufgerufen.

Beispiel: ISAM 1,LESEN_R,#BUF1

Dieser Macroaufruf bewirkt, daß der nĂ€chstniedere Datensatz der als ISAM-

Datei organisierten Datei mit der Nummer 1 gelesen und anschließend ab Adresse BUF1 abgespeichert wird.

  1. Sonstige numerische Angaben

Dies sind numerische Angaben ohne irgendwelche ZusĂ€tze wie z. B. das Doppelkreuz #. Sie werden als Dateinummern (FAN), fĂŒr DatensatzlĂ€ngen und auch als Funktionsnummer beim GEMDOS-Macro verwendet.

Beispiel:

OPEN ’T” ,6,”MYFILE” ,120 READ 6,A5

Die Datei mit der Nummer 6, dem Dateinamen „MYFILE“ und einer DatensatzlĂ€nge von 120 Zeichen wird als Inputdatei eröffnet. Dann wird der nĂ€chste Datensatz aus dieser t)atei 6 ab der in dem Adressregister A5 stehenden Speicheradresse abgespeichert.

Dies soll zur Vorstellung zunÀchst einmal genug sein. Wir werden dann aber der nÀchsten Ausgabe mit den allgemeinen Macros der PRIMA-Bibliothek beginnen. (HE)

Um die LeistungsfÀhigkeit der beiden Modi zu verdeutlichen, geben wir hier als Beispiel eine Telefondatei.

START: MOVE.L DSKVEC.SAVEVEC :ADR.STANDARD-FEHLERROUTINE SAVEN MQVE.L »ERROR.DSKVEC ;ADR. EIGENE FEHLERROUTINE OPEN T",l, "PHONE.DAT". 52 AOOO: MOVE.L SAVEVEC,DSKVEC :A3 JETZT WIEDER ALTE ROUTINE TST.L D0 ;ANDERER FEHLER ALS 'FILE NOT FQUND'? BMI ENDE ;JA, LEIDER KEYLEN 1,#30 REPEAT #10 ;TASTENREPEAT AUF MITTELWERT MOVE.W D7.SAVEREP ;ALTEN REPEAT-WERT RETTEN MENUE: CONTROL CLS POS #0.#5 PRINT "ISAM-DEMOPROGRAMM TELEFONVERZEICHNIS" PRINT "COPYRIGHT (1986) BY GERHARD PRITZ - BERLIN" ZEILE PRINTX "DAS VERZEICHNIS ENTHALT " MOVE.L ISAM1+4.D1 MOVE.L #REFE1.A2 JSR BINASC CLR.B REFE1+1Q PRINTS »REFE1+5 PRINT " EINTRÄGECONTROL CUREIN POS *0;#10 PRINTS #MENTXT CONIN JSR LEEREN ;SYSTEMPUFFER TASTATUR LEEREN :DENN WENN ER ÜBERLSUFT, WEIL IRGENDEIN ; HIRN MIT SEINEM FINGER AN DER TASTE ; KLEBT. STÜRZT DIE VERDAMMTE KISTE AB CMP.B #"1".D0 BEQ DANF CMP.B #"2”.D0 BEQ DEND CMP.B #"3".DQ BEQ SUCH CMP.B #"4",D0 BEQ NEUER CMP.B #''5''. DO BEQ GLEICHH CMP.B #"6".D0 BEQ GLEICHN CMP.B #"7",D0 BEQ FIN BRA MENUE DANF: MOVE.B *1,QM DA000: ISAM 1.LESEN,#BUF1 DA010: CMP.B *9.QF BNE ANZEIGE PRINT "‱** DATEIGRENZE ERREICHT ***** DELAY #5000.#300 BRA MENUE LEEREN: MOVE.L D0,-(SP) LEER1: INKEY TST.L D0 BNE LEER1 MOVE.L (SP)+,D0 RTS DEND: MOVE . B #1. QM DEOOO: ISAM 1,LESEN_R,#BUF1 BRA DA010 SUCH: CONTROL CLS PRINT "SATZ SUCHEN" PRINT »«**********‱‱‱ JSR GETKEY ISAM 1.SUCHEN.#BUF1 CMP.B #2.QF BNE ANZEIGE PRINT "SATZ IST NICHT VORHANDEN" DELAY #5000,*300 BRA MENUE NEUER: CONTROL CLS PRINT "NEUEN SATZ EINFÜGEN" PRINT "+++++++++++++++++++" N000: JSR GETKEY ISAM 1,SCHREIBEN,#BUF1 CMP.B #1 ,QF BNE NO 10 PRINT "SATZ IST SCHON VORHANDEN" BRA N020 N010: PRINTX "WELCHE TELEFONNUMMER: " MOVE.B #15,D0 MOVE.L #TELNR.A2 JSR INPUT ZEILE TST.L D0 ;*C ? BMI NO 10 ;JA ADD.L D0.A2 ;ADR.TELMR + LÄNGE DER EINGABE NEG , L DO ADD.L #15,D0 :15 - MAX.LÄNGE TELNR FILL A2.D0.#" " .-RECHTSBÜNDIG MIT BLANKS FÜLLEN CLR.B LOE ;LOESCHMERKMAL PUT 1,ISAMl.tBUFl ;NEUEN SATZ SCHREIBEN N020: ZEILE PRINTX “WEITERE NEUEINGABE (J/N) ? " CONIN AND.B #223,D0 CMP.B #"J",D0 BNE MENUE BRA NOOO GLEICHH: CONTROL CLS PRINT "GLEICHEN ODER HÖHEREN SATZ SUCHEN" PRINT ........................................ JSR GETKEY ISAM 1,GLEICH__HOCH, #BUF1 CMP.B #9.QF ;EOF ? BNE ANZEIGE GLH010: PRINT ***** DATEIGRENZE ERREICHT***" DELAY #5000.#300 BRA MENUE GLEICHN: CONTROL CLS PRINT “GLEICHEN ODER KLEINEREN SATZ SUCHEN" JSR GETKEY ISAM l.GLEICH_TIEF,#BUFl CMP.B #9.QF ;EOF ? BNE ANZEIGE BRA GLHOIO GETKEY: POS #0 #5 CONTROL CCRESTB ;REST BILDSCHIRM LÖSCHEN PRINTX "NAME : " MOVE.B #15,D0 MOVE.L #QA.A2 JSR INPUT ZEILE TST.L D0 BMI GETKEY ;CONTROL C UNERWÜNSCHT BEQ GETKEY ;EIN CHARACTER SOLLTE ES SCHON SEIN MOVE.L tQA.Dl ADD.L D0,D1 NEG.B DO ADD.B #15,D0 FILL Dl,D0.#" " MOVE.L #QA+15.A2 MOVE.B #15,D0 PRINTX "VORNAME: " JSR INPUT ZEILE TST.L D0 BMI GETKEY RTS ANZEIGE: CONTROL CLS CONTROL CURAUS PRINTS #MENTXT2 TST.B LOE BEQ ANOOO PRINT "*** GELÖSCHTER SATZ ***" ANOOO: PRINTX "NAME : " TRANSFER #KEY1.#EUF2,#15 PRINTS #3UF2 CHAR #13 CONTROLM CRECHTS, #35 PRINTX "RECORD-# " MOVE.L I5AK1,D1 MOVE.L #REFE1.A2 JSR BINASC CLR.B VORZ1 PRINTS »REFE1+4 ZEI LE PRINTX "VORNAME : " TRANSFER #KEY2.#BUF2.#15 PRINTS #BUF2 ZEILE PRINTX "TELEFON : " PRINTS #TELNR AN010: INKEY TST.L D0 BEQ AN010 JSR LEEREM :REST DES TASTENPUFFERS LEEREN AND.8 #223,D0 ;DAMIT ER NICHT UBERLÄUFT CMP.B #"M",D0 ;DENN SONST STÜRZT DER VOGEL AB BEQ MENUE CMP.B #"L",D0 BEQ ANQ20 CMP.B #“A",D0 BEQ AN050 SWAP DO CMP.B *$48,D0 ;PFEIL LINKS BEQ DEOOO CMP.B #$4D,D0 :PFEIL RECHTS BEQ DAOOO BRA AN010 AN020: TST.B LOE BEQ AN040 CLR.B LOE ;REAKTIVIEREN AN03Q: PUT 1,ISAM1.#BUF1 BRA ANZEIGE AN040: MOVE.B #l,LOE ;LÖSCHEN BRA AN030 AN050: TST.B LOE BNE AN010 ;WIR ANDERN NUR AKTIVE SATZE CONTROL CUREIN PRINTX “NEUE TELEFON-NR. : *' MOVE.B #15,D0 MOVE.L #TELNR.A2 JSR INPUT ZEILE TST.L D0 BMI AN050 ADD.L D0.A2 NEG.L D0 ADD.L #15,D0 ;RECHTSBÜNDIG BLANKS AUFFULLEN FILL A2,D0,#" - BRA AN030 ERROR: CMP.L #-33,D0 :FILE NOT FOUND ? BEQ E010 MOVE.L SAVEVEC.A0 JMP (A0) ;ZUR STANDARD-FEHLERROUTINE E010: CLR.L D0 MOVE.L SAVEVEC.DSKVEC OPEN "0".1."PHONE.DAT",52 BRA AOOO FIN: CLOSE 1 ENDE: REPEAT SAVEREP ;ALTE REPEATSPEED WIEDER EINSTELLEN GEMDOS 0 MENTXT: DC " 1 - DATEI ANFANG",13,10 DC " 2 - DATEIENDE",13,10 DC " 3 -SATZ SUCHEN",13,10 DC " 4 - SATZ EINFUGEN",13,10 DC " 5 - GLEICHEN ODER HÖHEREN SATZ SUCHEN",13,10 DC " 6 - GLEICHEN ODER KLEINEREN SATZ SUCHEN",13,10 DC " 7 - PROGRAMMENDE".13.10.10.10 DC " IHRE WAHL: ".0 KENTXT2: DC " <- - VORANGEHENDER SATZ",13,10 DC " -> - NÄCHSTER SATZ",13,10 DC " TELEFONNUMMER ÄNDERN",13,10 DC " L SATZ LÖSCHEN/REAKTIVIEREN",13,10 DC " M - MENÜ".13.10.10.10.10.10.0 EVEN SAVEREP: DC.W 0 SAVEVEC: DC.L 0 EVEN BUF1: BLK 6 KEY1: BLK 15 KEY2: BLK 15 LOE: DC 0 TELNR: BLK 15 DC 0 BUF2: BLK 15 DC 0 EVEN END