Nachdem wir in der letzten Ausgabe die beiden Assembler-Macro-Modulbibliotheken ISAM & PRIMA vorgestellt haben, beginnen wir heute mit dem Abdruck der ersten Macro-Module von PRIMA. Es handelt sich dabei um die allgemeinen Macros. Auf Seite 27 werden noch die in den Macros benutzten Escape-Sequenzen aufgelistet, die an den Anfang des Macro-listings gestellt werden müssen.
DELAY: MACRO MOVEM.L D0-D1,-(SP) MOVE.W ?1,D0 DEL1?O: MOVE.W ?2,D1 DEL2?0: DBRA D1,DEL2?0 DBRA D0,DEL1?0 MOVEM.L (SP)+,D0-D1 ENDM |
DELAY
- Warteschleife
Dieses Macro besteht aus einer doppelten Warteschleife, d. h. beide Schleifen sind ineinander verschachtelt und werden auf -l heruntergezählt.
Beispiele: DELAY #3000,D1
DELAY #1000,# 500
REPEAT
- Wiederholungsrate der Tastatur festlegen
Bei diesem Macro sind Werte zwischen l und 20 zulässig, wobei l für schnell und 20 für langsam steht. Der alte Wert steht als Wort gespeichert im Datenregister D7.
Beispiel: REPEAT # 10
REPEAT: MACRO MOVEM.L D0-D6/A0-A6,-(SP) MOVE.W #-1,-(SP) MOVE.W #-1,-(SP) MOVE.W #35,-(SP) TRAP #14 ADDQ.L #6,SP MOVE.W D0,-(SP) MOVE.W ?1,D0 CMP.W #20,D0 BGT REP1?0 CMP.W #1,D0 BLT REP1?0 MOVE.W ?1,-(SP) MOVE.W #$0F,-(SP) MOVE.W #35,-(SP) TRAP #14 ADDQ.L #6,SP REP1?0: MOVE.W (SP)+,D7 AND.W #$FF,D7 MOVEM.L (SP)+,D0-D6/A0-A6 |
COMPARE
- Vergleichen zweier Felder
Format: COMPARE Feldl, Feld2, Länge
Die Felder Feldl und Feld2 können sowohl als Literal (z. B. Egon") als auch als Register angegeben werden. Die Register AO, AI und DO dürfen allerdings nicht benutzt werden. DO kann aber als Längenregister verwendet werden. Nicht erlaubt sind Angaben wie #Feld. Wenn man die Form Literal verwendet, sollte die Längenangabe der Literallänge entsprechen.
Alle Register bleiben unverändert.
Der Vergleich erfolgt Bit für Bit von links nach rechts. Bei der ersten Ungleichheit wird abgebrochen.
Nach Ausführung des Macros kann der Bedingungsschlüssel genau wie bei der CMP-Assembler-Anweisung abgefragt werden. Die Abfrage bezieht sich dabei immer auf den zweiten Operanden.
Beispiele:
COMPARE Dl,"Name",#4
COMPARE "Franz",A2,D0
COMPARE #Feld,Dl,# 15 ist falsch, da #Feld nicht erlaubt ist.
COMPARE: MACRO MOVEM.L DO-D1/AO-A1,-(SP) IF '?1' > 'D7' BRA COM2?0 COM1?0: DC '?1' EVEN COM2?0: MOVE.L #COM1?0+1,AO ELSE MOVE.L ?1,AO ENDIF IF '?2' > 'D7' BRA COM4?0 COM3?O: DC '?2' EVEN COM4?0: MOVE.L #COM3?0+1,A1 ELSE MOVE.L ?2, A1 ENDIF MOVE.L ?3, D0 SUBQ.L #1, D0 BMI COM6?0 COM5?0: MOVE.B (A1)+,D1 CMP.B (A0)+,D1 DBNE D0.COM5?0 COM6?0: MOVEM.L (SP)+,D0-D1/A0-A1 ENDM |
GEMDOS: MACRO MOVE #?1 ,-(SP) TRAP #1 ADDQ.L #2,SP ENDM |
GEMDOS
Die Funktionsnummer wird als Parameter in Wortlänge auf den Stack gelegt und ein TRAP #1 mit anschließender Stackkorrektur durchgeführt.
Beispiel:
GEMDOS 0 ;Rückkehr zum Desktop
CONIN: MACRO MOVE.W #1,-(SP) TRAP #1 ADDQ.L #2,SP ENDM |
CONIN
- Eingabe eines Zeichens von Tastatur mit Warten
Die Routine wartet, bis ein Zeichen über die Tastatur eingegeben wird. Das Ergebnis steht anschließend im Datenregister D0, wobei das untere Byte des Low Words den ASCII-Code und das untere Byte des High Words den Scan-Code der gedrückten Taste enthalten.
So ist der Inhalt von DO nach Betätigen der Backspace-Taste 00E 0008.
INKEY
Diese Routine wartet - im Gegensatz zum CONIN-Macro - nicht auf die Eingabe eines Zeichens, sondern überprüft nur, ob eine Taste gedrückt wurde. Man kann sie also gut als Abfrage in einer Schleife einsetzen. Das Ergebnis steht ebenfalls im Datenregister DO. Ist keine Taste gedrückt worden, steht in DO eine Null.
INKEY: MACRO MOVE.W #$FF,-(SP) MOVE.W #6,-(SP) TRAP #1 ADDQ.L #4,SP ENDM |
CONTROL
- Ausgabe von Control-Anweisungen an den Bildschirm
Für die Ausgabe von Control-Anweisungen an den Bildschirm werden die am Anfang als Equates definierten
Escape-Sequenzen benötigt. Sie werden einfach als Funktionsnamen zur Bildschirmsteuerung benutzt.
Beispiel: CONTROL CUREIN ;Cursor einschalten
CONTROL: MACRO | |
MOVE.L MOVE MOVE TRAP #1 MOVE MOVE TRAP ADDQ.L MOVE.L ENDM |
D0,-(SP) #27, -(SP) #2,-(SP) #1 #?1 ,-(SP) #2,-(SP) #1 »8 ,SP (SP)+,D0 |
CONTROLM
- Mehrfache Ausgabe derselben Control-Anweisung
Das CONTROLM-Macro wird im Prinzip genauso aufgerufen wie das CONTROL-Macro. Der einzige Unterschied besteht darin, daß man noch zusätzlich als Parameter die Anzahl der Aufrufe derselben Control-Anweisungen angeben muß.
Alle Register bleiben unverändert.
Beispiel:
CONTROLM CRECHTS,# 15 ;Cursor 15 Stellen nach rechts
CONTROLM: |
MACRO MOVEM.L MOVE.W SUBQ.W BMI MOVE MOVE TRAP #1 MOVE MOVE TRAP ADDQ.L DBRA MOVEM.L FMDM |
|
DO-D1/AO, | -(SP) | |
?2,D1 | ||
#1,01 | ||
CON27O | ||
CONI70: | #27, -(SP) | |
#2,-(SP) | ||
#1 | ||
#71 ,-(SP) | ||
#2,-(SP) | ||
«t | ||
#8,SP | ||
Dl ,CON1?0 | ||
CON270: | (SP)+,00- | Dl XftO |
CHAR
- Ausgabe eines Zeichens an der aktuellen Cursorposition
Das Zeichen darf entweder als Literal (z. B. A") oder auch als Wort (.W) in einem Register vorliegen. Nicht zulässig ist die Form #Label.
Beispiel: CHAR #"A"
CHAR | MACRO | |
MOVE | L | D0,-(SP) |
MOVE | ?1 , -(SP) | |
MOVE | #2,-(SP) | |
ADDQ | L | #4,SP |
MOVE | L | (SP)+,D0 |
ENDM |
POS
Positionierung des Cursors
Um den Cursor auf dem Bildschirm zu positionieren, müssen Zeile und Spalte als Parameter angegeben werden. Dabei können unmittelbare Werte oder auch Register angegeben werden.
Beispiel: POS #0,#15
;Spalte 0, Zeile 15
POS: MOVE.L MOVE MOVE
MOVE MOVE TRAP MOVE ADD MOVE
MOVE ADD MOVE
ADD. L MOVE.L |
MACRO 00,-(SP) #27, -(SP) #2,-(SP) #1 #-Y-,-(SP) #2,-(SP) #1 ?2,-(SP) #32, (SP) #2,-(SP) #1 ?1 ,-(SP) #32, (SP) #2,-(SP) #1 #16,SP (SP)t,D0 ENDM |
TRANSFER
- Übertragen von Daten
Format: Anfangsadr. Sendefeld, An-fangsadr. Empfangsfeld, Länge
Außer den Registern AO, AI und DO können auch beliebige Register angegeben werden. DO darf jedoch als Längenregister genutzt werden.
Das schöne an diesem Macro ist, daß es sich um ein intelligentes" Macro handelt. Damit ist gemeint, daß sich die zu übertragenden Felder auch überlappen dürfen. Ein Feld kann somit z. B. auch nur um einige Stellen nach links oder rechts verschoben werden. Wenn als Länge eine Null in DO steht, findet kein Transfer der Daten statt.
Beispiel:
TRANSFER # Feldl + 2,# Feld2,# 20
Achtung: Bei einem Aufruf nach dem dritten Parameter sofort die RETURN-Taste drücken und keine Remarks (;) auf derselben Zeile machen.
Begründung: Im Macro wird mit IF abgefragt, ob DO Längenregister ist. Wenn Remarks dem dritten Parameter folgen, so werden diese als Bestandteil des dritten Parameters mit einbezogen, so daß DO" < > DO; Remark" wird. (Dies ist offensichtlich eine Eigenart der benutzen Macro-sprache).
TRANSFER: | MACRO | |
MOVEM.L | DO/AO/A1 ,-(SP) | |
MOVE.W | ?3,D0 | |
SUBQ.W | #1 ,D0 | |
BMI | TR470+4 | |
MOVE . L | ?1 , AO | |
MOVE.L | ?2,A1 | |
CMP.L | AO, AI | |
BPL | TR270 | |
TR170: | MOVE. B | (A0)-t-, (AI > + |
DBRA | D0,TR1?0 | |
BRA | TR470+4 | |
TR270: | ADD.L | 73, A0 |
ADD.L | 73, A1 | |
IF | "73' = "D0" | |
ADDQ.L | #1 ,A0 | |
ADDQ.L | «1 ,A1 | |
ENDIF | ||
TR370: | MOVE. B | -(A0), -(AI) |
TR470: | DBRA | D0,TR3?0 |
MOVEM.L | (SP)t,D0/A0/A1 | |
ENDM |
FILL
Füllen eines Feldes
Format: FILL Adresse, Länge, Füllzeichen
Es dürfen bei diesem Macro alle Register außer DO und AO benutzt werden. DO darf wiederum Längenregister sein. Die Register werden nicht verändert.
Beispiel: FILL#Feld,#1000,#" "
; 1000 Blanks werden ab Adresse
; #Feld geschrieben.
FILL: | MACRO | |
MOVEM.L | D0/A0.-(SP) | |
MOVE.W | 72,00 | |
SUBQ.W | #1 ,D0 | |
BMI | FI270+4 | |
MOVE.L | 71 , A0 | |
FI 170: | MOVE. B | 73, ( A0)+- |
FI270: | DBRA | D0,FI 170 |
MOVEM.L | (SP)+,D0/A0 | |
ENDM |
PRINT: MACRO MOVE.L D0,-(SP) BRA PRX2?0 PRX1?0: DC ?1,13,10,0 EVEN PRX2?0: MOVE.L #PRXl?0,-(SP) MOVE #9,-(SP) TRAP #1 ADDQ.L #6,SP MOVE.L (SP)+,D0 ENDM |
PRINT
- Textausgabe auf Bildschirm mit Carriage Return (CR) und Line Feed
(LF)
Dieses Macro entspricht dem PRINT-Befehl in Basic. Der Text darf keine Kommata enthalten. Zur Ausgabe von Kommata des PRINTS-Macro verwenden. Alle Register bleiben unverändert.
Beispiel: PRINT "Hallo Welt!!!"
PRINTX: MACRO MOVE.L D0,-(SP) BRA PR2?0 PRX1?0: DC ?1,0 EVEN PRX2?0: MOVE.L #PRl?0,-(SP) MOVE #9,-(SP) TRAP #1 ADDQ.L #6,SP MOVE.L (SP)+,D0 ENDM |
PRINTX
- Textausgabe auf Bildschirm ohne CR und LF
Für dieses Macro gelten die gleichen Bedingungen wie für das PRINT-Macro.
Beispiel: PRINTX "Kein Carriage Return und Line Feed"
PRINTS
- Speicherinhalt auf Bildschirm ausgeben
Mit diesem Macro können beliebige Speicherinhalte auf den Bildschirm ausgegeben werden. Das entsprechende Datenfeld muß mit "00" abgeschlossen sein. Es dürfen auch Register benutzt werden. Die Registerinhalte werden nicht verändert.
Beispiel:
PRINTS #Feld l Feldl: de "Ausgabetext",13,10,0 ; 13 = CR 10=LF
PRINTS: MACRO | MOVE.L D0,-(SP)|||||
MOVE. | L |
71 , -(SP) |
|||
MOVE | #9,-( | SP) | |||
TRAP | #1 | ||||
ADDQ. | L | #6,SP | MOVE.L | (SP) + | ,00 | ENDM |
ZEILE
- Zeilenvorschub
Dieses Macro bewirkt ein Carriage Return und Line Feed, so daß auf dem Bildschirm in eine neue Zeile gegangen wird.
Beispiel: ZEILE
Damit erst einmal genug für den ersten Teil des Sourcecode-Listings. In der nächsten Ausgabe werden wir dann den zweiten Teil - die Disket-tenmacros abdrucken und dokumentieren.
ZEILE: MACRO | MOVE.L D0,-(SP)||
MOVE | #1 3 | , -(SP) |
MOVE | #2, | -(SP) |
TRAP | #1 | |
MOVE | #10 | ,-(SP) |
MOVE | #2, | -(SP) |
TRAP | #1 | |
ADDO.L | #8, | SP |
MOVE.L |
(SP)+,D0 |
|
ENDM |
; Escape-Sequenzen |
|||
NLIST | |||
CHOCHO : | EQU | 65 ;#"A- CURSOR HOCH OHNE NEGATIVES SCROLLING | |
CTIEF: | ES U | 66 ;#'B- CURSOR RUNTER | |
CRECHTS: | EQU | 67 ;*"C" CURSOR RECHTS | |
CLINKS: | EQU | 68 ;#"D" CURSOR LINKS | |
CLS: | EQU | 69 ;#£ CLEAR THE SCREEN, CURSOR HOME | |
CHOME: | EQU | 72 ;#"H" CURSOR HOME OHNE CLEAR SCREEN | |
CHOCH: | EQU | 73 ;#-! CURSOR HOCH GGF. MIT NEGATIVEM SCROLL | |
CCRESTB: | EQU | 74 ;<TJ- REST DES SCHIRMS AB AKT. POS (EINSCHL | . ) LOSCHEN |
CZEILEND: | EQU | 75 ;<TK" REST DER ZEILE AB AKT. POS < EINSCHL.) | LÖSCHEN |
CZEILREIN | :EQU | 76 itt-L," LEERZEILE EINFÜGEN | |
CZEILRAUS | :EQU | 77 ;#-M" ZEILE LÖSCHEN «ANDERE ZEILEN WERDEN | RANGERÖCKT) |
CBISC: | EQU | 100 ;#-d* CLEAR BILDSCHIRM BIS CURSORPOSITION | |
CUREIN: | EQU | 101 ;#-e- CURSOR EIN | |
CURAUS: | EQU | 102 ;#-f CURSOR AUS | |
CURSPEI : | EQU | 106 ;#"j- CURSORPOSITION WEGSPEICHERN | |
CURSET: | EQU | 107 ;#-k" CURSOR AUF GESPEICHERTE POS SETZEN | (SIEHE J) |
CZEI L : | EQU |
108 ;#"! ZEILE LÖSCHEN CANDERE ZEILEN UNBEEINTRÄCHTIGT) |
|
CZEILANF: | EQU |
111 ;#'o" ZEILE BIS (EINSCHL.) CURSORPOS LÖSCHEN |
|
CREVEIN: | EQU | 112 ;#-p- INVERTIERTE AUSGABE EIN | |
CREVAUS: | EQU | 113 ;#"q- INVERTIERTE AUSGABE AUS | |
CAUTOEIN: | EQU | 118 ;#-v" AUTOM. OBERLAUF AM ZEILENENDE EIN | |
CAUTOAUS: | EQU | 119 ;#"w- AUTOM. ÜBERLAUF AM ZEILENENDE AUS |