Dies ist eine alte Version des Dokuments!
Assembler
Thomas Beierlein:
Da ich in letzter Zeit eine Reihe von Fragen zur Benutzung des Z80- Assemblers in FORTH83 erhalten habe, möchte ich hier einige Hinweise zu seiner Benutzung geben. Da ich z.Z. unter chronischem Zeitmangel stehe, wird es nur eine recht kurze Barstellung. Zur Sache:
Maschinencoderoutinen werden im FORTH83 im Unterschied zu FIG mit folgenden Worten definiert bzw. abgeschlossen.
CODE <name> ………………………….. END-CODE
Diese beiden Worte sind auch ohne geladenen Assembler verfügbar und können wie früher kurze Coderoutinen als Hexcode direkt ins Wörterbuch „hineinkommaen“. Nach wie vor müssen Coderoutinen mit einem Sprung nach NEXT abgeschlossen werden. Die Adresse von NEXT wird durch die Konstante >NEXT im System bereitgehalten.
Eine zweite Art von Code sind Unterprogramme, die mit der Sequenz
LABEL <name> …………………….. RET, END-CODE
definiert werdan. Ein Beispiel zur Anwendung folgt am Schluß. Bei der Benutzung von Code-Definitionen ist zu beachten, daß die Register BC und IY vom System verwendet werden. Sie sind also bei Bedarf zu sichern.
Nach dem Laden des Assemblers stehen nach Aufruf von CODE <name> alle Befehle des Z80 in ihrer ursprünglichen Mnemonik zur Verfügung (am besten mit ASSEMBLER WORDS einmal anschauen). Bei der Anwendung sind folgende Syntaxregeln zu beachten:
- alle Mnemoniks haben ein , (Komma) am Namensende,
- die Notation der Parameter erfolgt strang nach umgekehrt polnischer Notation. Die Reihenfolge ist also <Quelle Ziel Operand>.
Folgende Regeln gelten für die Kennzeichnung der Parameter:
- Register werden mit ihrem Namen aufgerufen. Folgende gibt es:
A B C D E H L (HL) (IX) (IY) I R AF BC DE HL IX IY - alle Adressen sind durch ein nachfolgendes #) als solche zu kennzeichnen,
- alle direkt in Register zu ladenden Zahlenwerte sind durch # zu kennzeichnen,
- bei Verwendung der Indexregister in der Form (IX+displ) ist statt dessen displ (IX) zu schreiben. Eine Angabe des Displacement ist auch bei displ=0 notwendig.
- Bitoperationen sind wie folgt zu codieren
RES 4,C wird z.B. zu 4 C RES, - bei Relativspruengen ist die Distanz mit # als Zahlenwert zu markieren.
Alle Sprünge und Call's, unbedingt und auch bedingt, werden compiliert. Zu beachten ist, daß statt JMP (HL) die Sequenz HL JMP, zu verwenden ist.
Bei der Verwendung der Strukturoperatoren IF, ELSE THEN, BEGIN, UNTIL, WHILE, und REPEAT, werden nur absolute Sprünge compiliert. Die folgenden Entscheidungsbedingungen gibt es dabei:
0= (Zero)
CY (Carry)
PE (Parity)
0< (Minus)
Ein NOT nach der Bedingung negiert seine Bedeutung (0= NOT IF, entspricht so z.B. JPNZ).
Der Assembler unterstützt des weiterenden Abschluß einer Coderoutine mit den Macros NEXT, HPUSH, und DPUSH. diese compilieren einen Sprung zur Nextroutine bzw. legen vorher noch das Register DE oder DE und HL auf den Stack.
Soweit dazu. Nun noch einige Beispiel für die möglichen Parameterformen.
konventionelle Notation | FORTH-Assembler |
---|---|
EX (SP),HL | HL (SP) EX, |
RST 28H | HEX 28 #) RST, |
JPC 4236H | 4236 #) JPC, |
JMP (IX) | IX JMP, |
CANZ 1A7H | 1A7 #) CANZ, |
LD A,17 | 17 # A LD, |
LD (BC),A | A (BC) LD, |
LD A,(IX) | 0 IX A LD, |
SBC HL,DE | DE HL SBC, |
OR D | D OR, |
AND 0E7H | HEX 0E7 # AND, |
IN 23 | 23 # IN, |
OUT L | L OUT, |
JRNZ #-5 | -5 # JRNZ, |
RES 0,(IY+4) | 0 4 IY # RES, |
Hier waren nun hoffentlich alle Varianten dabei.
Zum Schluss noch ein Beispiel, welches auch die Verwendung von Labels und die strukturierte Programmierung verdeutlichen soll. Folgendes Problem steht:
An einem I/O-Port sollen zwei Steuerbits P0 und P1 überwacht werden. Eine definierte Zeit nach dem Uebergang vpn P0 auf High soll P1 abgetastet und in einem 8-Bit Puffer von rechts eingeschoben werden.
Die Lösung würde bei mir etwa so aussehen:
HEX 23 CONSTANT PORT \ die Portadresse 0 CONSTANT P0 \ die Bitnummer der Steuer- 1 CONSTANT P1 \ leitungen im Port 45 CONSTANT ZK \ Zeitkonstante der Verzög. VARIABLE PUFFER \ der 8-Bit Puffer LABEL WAIT \ realisiert Verzögerung ZK # HL LD, \ indem HL bis auf 0 \ heruntergezählt wird BEGIN, H A LD, L OR, 0= NOT WHILE, HL DEC, REPEAT, RET, CODE ABTASTUNG \ macht die Arbeit BEGIN, PORT # IN, P0 A BIT, 0= NOT UNTIL, \ warte bis P0 High wird WAIT #) CALL, \ rufe Verzögerung auf PORT # IN, P1 A BIT, \ teste P1 und wandle in 0= IF, A OR, ELSE, SCF, THEN, \ Carry-Flag um PUFFER #) A LD, \ lade A mit dem Inhalt von RLA, \ Puffer und schiebe Cy ein A PUFFER #) LD, \ lege den Wert wieder zurück NEXT END-CODE \ weiter mit FORTH
So, viel Spaß und nicht verzagen, wenn nicht gleich klappt.
Thomas Beierlein