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

  • forth/fgforth/assembler.1295339969.txt.gz
  • Zuletzt geändert: 2011/01/18 07:39
  • (Externe Bearbeitung)