Assemblerkurs (Teil 1)

Um den Aufbau, die Adressierungsarten und die Befehle des 68000 geht es in Sven Schulers Assemblerkurs. Dabei werden die möglichen Kombinationen erläutert, die der Befehl als Quelle und Ziel zuläßt. Die Anwendung der Befehle wird an Beispielen und Programmen gezeigt.

Was ist Assembler?

Das englische Verb „to assemble" bedeutet „zusammensetzen". Um den Zahlen, die der Prozessor verarbeitet, eine sinnvolle Bedeutung zu geben, wurden für die Befehlscodes Abkürzungen eingeführt. Diese Abkürzungen übersetzt der Assembler in Zahlen und Zahlenreihen. Jede Zahlenreihe besteht aus einem Operationscode (= Op-code, d. h. das erste Wort eines Befehls), der Quell- und der Zieladresse. Werden zusätzliche Operanden benötigt, so folgen sie dem Opcode. Dadurch kann eine Zahlenfolge bis zu zehn Bytes lang sein.

Da jeder Prozessortyp seine eigenen Befehle und Adressierungsarten hat, wurde somit vom Hersteller eine eigene Assemblersprache oder Assemblerschreibweise entwickelt. Dadurch, daß jeder Prozessor seine Eigenheiten hat und jeder Hersteller sein Produkt gut ausstatten möchte, entstand eine speziell dafür zugeschnittene Sprache. Assemblerprogrammierer muß deshalb, wenn er auf verschiedenen Systemen mit verschiedenen Prozessoren arbeitet, mehrere Assemblersprachen lernen. Doch so grundlegend verschieden sind die Sprachen nicht. Kann man die eine Assemblersprache, so ist die zweite leichter zu erlernen. Es ist etwa mit zwei Basic Versionen vergleichbar, die auf verschiedenen Rechnern laufen. Jede Sprache unterstützt jene Eigenheiten, die der Rechner besonders gut kann, als wolle Sie zeigen, daß das Produkt noch besser als andere ist. Ein Versuch, Assembler zu normieren, wurde mit dem CALM-Mode (common assembly language for microprozessors) unternommen. Die Entwickler mußten aber mittlerweile für den 68000 den CALM-3-Code entwickeln. Der Vorteil ist, daß man nur den CALM-Mode lernen muß und ihn dann in Cross-Assembler einsetzen kann. Leider geht die Sprache nicht auf alle Besonderheiten ein, die einen Prozessor auszeichnen.

Ein Cross-Assembler kann aus einem Quellcode Maschinencodes für verschiedene Prozessoren erzeugen. Das bedeutet, daß auf dem eigenen System Entwicklungen für andere Systeme möglich sind.

Die Vorteile des Assemblers

Da der Assembler direkt Maschinencodes erzeugt, sind Assemblerprogramme am schnellsten und am kürzesten. In Assembler stehen, mehr als von jeder anderen Sprache aus, Tür und Tor offen.

Nachteilig ist die recht komplizierte Programmierung, die aber durch leistungsfähige Assembler wieder ausgeglichen wird. Die Erfahrung hat gezeigt, daß von vielen, die sich mit Assembler beschäftigt haben, nur wenige wirklich damit arbeiten. Doch denken Sie nur an die vielen schönen und leistungsfähigen Programme und Spiele mit ihren bunten Bildern. Sie sind fast ausnahmslos in Assembler geschrieben.

Assembler wird in vielen Anwendungen eingesetzt, die zeitkritisch sind oder von einer Sprache aus nicht erreichbar oder lösbar sind. Oft kann dann zur Problem-Lösung nur Assembler herangezogen werden, etwa beim Sortieren von Listen oder beim Drucktreiber für die eigene Schreibmaschine.

Wenn Sie also ernsthaft an der Arbeitsweise Ihres Rechners interessiert sind, ist Assembler eine gute Voraussetzung dafür. Außerdem sollte man bedenken, daß die Firma Motorola mit dem 68000 Prozessor nicht ihren ersten Mikroprozessor entwickelt hat. Er ist leistungsfähiger und besser programmierbar als die anderen Motorola Prozessoren, die ja ursprünglich nur diskrete Logik ersetzen sollten. Vielleicht sollte es auch nachdenklich stimmen, daß manche C-Compiler Assembler zulassen oder zumindest die Möglichkeit bieten, Assemblerprogramme zu linken. Das bedeutet, daß man in Assembler geschriebene und übersetzte Programme in C-Programme einbinden kann. Es gibt sogar C-Gompiler, die Assemblerquellcode liefern.

Bestes Beispiel ist das Betriebssystem des Atari: Dieses Programm wurde fast ausschließlich in C geschrieben, die wichtigen und zeitkritischen Teile jedoch in Assembler.

Struktur und Aufbau des 68000

Damit wir mit dem 68000 arbeiten können, müssen wir uns zunächst mit der Struktur des Prozessors befassen.

Der 68000 besitzt eine ganze Reihe von Registern, die universell anwendbar sind oder spezielle Funktionen haben. Zu diesen Registern gehören 1. Datenregister, 2. Ädressregister mit dem Stackpointer und 3. der Programmzähler und das Statusregister.

1.) Datenregister (DO - D7)

Der 68000 besitzt acht unabhängige Datenregister, die die Bezeichnung D für Datenregister und eine laufende Numerierung von 0-7 erhalten, also D5 für das 6. Datenregister. Jedes Datenregister hat eine Länge von 32 Bit. Diese Register sind universell einsetzbar. Man kann in ihnen Daten speichern und verarbeiten. Dies muß aber nicht mit allen 32 Bit geschehen, sondern kann auch mit l, 4, 8 oder 16 Bit durchgeführt werden. Bei der 1-Bit-Verarbeitung wird ein spezielles Bit innerhalb des 32 Bit Registers angesprochen. Die 4-Bit Verarbeitung kommt nur bei den BCD-Befehlen zum Einsatz.

Für die Verarbeitung von 8-, 16- und 32-Bit-Daten hat man folgende Begriffe eingeführt:

8 Bit Byte
16 Bit Wort
32 Bit Langwort

Bei der Byteverarbeitung werden die Bits 0-7 des jeweiligen Datenregisters angesprochen, bei der Wortverarbeitung die Bits 0—15. Arbeitet man mit Langwort, werden natürlich alle 32 Bits benutzt. Die restlichen oberen Bits bleiben unverändert. Dadurch ist es zum Beispiel möglich, bei der Wortverarbeitung mit den unteren 16 Bits zu arbeiten und sich die restlichen 16 Bits für später aufzuheben.

Bei den Operationen (Befehlen), in denen ein Datenregister das Ergebnis enthält, werden die Flags (Statusregister) entsprechend dem Ergebnis gesetzt.

2.) Die Adressregister (AO - A7)

Ebenso wie die Datenregister sind die Adressregister jeweils 32 Bit lang. Auch sie kann man als Datenspeicher benutzen. Adressregister haben jedoch hauptsächlich die Aufgabe, Daten zu adressieren, d. h., sie enthalten die Adresse, unter der die Daten im Speicher stehen. Die Besonderheit der Adressregister ist, daß sie eine vollständige und eindeutige Adresse bilden müssen. Wenn zum Beispiel ein Adressregister das Ziel einer Operation ist und es liegt Byte- oder Wortverarbeitung vor, so wird das angesprochene Adressregister vorzeichenrichtig auf 32 Bit erweitert. Ist also die Byteverarbeitung das 7. Bit l, oder bei Wortverarbeitung das 15. Bit l, so werden die Bits 9-32 bzw. 16-31 ebenfalls auf l gesetzt. Ansonsten enthalten sie den Wert 0.

Außerdem werden keine Flags gesetzt, wenn ein Adressregister das Ergebnis einer Operation enthält.

Diese Ausführungen gelten für die Adressregister AO-A6. Der 68000 hat aber noch zwei weitere Adressregister, und zwar das Adressregister A7 und A7". Dieses Adressregister ist doppelt vorhanden und hat die Aufgabe, als Prozessorstack zu dienen. Beide Register werden über A7 angesprochen. Welches jeweils gemeint ist, hängt dvon ab, ob sich der Prozessor im User- oder im Supervisormodus befindet. Somit erhalten sie auch zwei verschiedene Namen: User- (USP) und Supervisor-Stackpointer (SSP). Das Register A7 hat auch den Namen SP. Dieser wird meist in Programmlistings verwendet.

Was ist ein Stackpointer?

Stackpointer bedeutet Stapelzeiger. Man könnte es mit einem Stapel von Büchern vergleichen. Der Stackpointer ist ein Zeiger, der immer auf das oberste Buch zeigt. Wird ein weiteres Buch obendrauf gelegt, wird der Stackpoin-ter um Eins erhöht, damit er auf den nächsten freien Platz zeigt. Entnimmt man das Buch, so wird der Zeiger um Eins erniedrigt. Im Computer zeigt der Stackpointer auf einen Speicherbereich, in dem Daten (zum Beispiel Rücksprungadressen von Unterprogrammen) abgelegt werden. Die 68000-Stackpointer zeigen immer auf die letzten gültigen Daten und wachsen zu den fallenden Adressen hin. Das bedeutet, daß der Stack wie eine Traube von oben nach unten wächst, wobei oben die höheren Adressen sind.

Der Programmzähler (PC)

Der Programmzähler oder Program-counter zeigt auf die Speicherstelle, an der der nächste Befehl steht. Er ist etwa mit den Zeilennummern in Basic vergleichbar. Die Länge des Programmzählers ist 32 Bit, doch nur die ersten 24 sind für die Funktion entscheidend, denn sie sind mit den 24 Adressleitungen des Adressbuses verbunden. Ausgenommen ist hierbei die Adressleitung AO.

Das Statusregister (SR)

Das Statusregister ist wohl das wichtigste Register überhaupt. Es zeigt den Modus an, in dem sich der Prozessor befindet, steuert die mögliche Auswahl der Interrupts und zeigt den Zustand des letzten Ergebnisses an. Anhand dieser Zustände kann man Entscheidungen treffen. Das Statusregister umfaßt insgesamt 16 Bits, wovon allerdings nur zehn genutzt werden. Dieses Register spaltet sich in zwei Bytes auf: das System-Byte und das User-Byte oder Condition-Code-Register (CCR). Das System-Byte belegt das oberste Byte und kann nur im Supervisor-Mode (z. B. vom Betriebssystem aus) benutzt werden. Es enthält das Trace-Bit, das Supervisor-Bit und die drei Interrupt-Bits, die die Interrupt-Maske bilden.

Das User-Byte oder Condition-Code-Register, enthält fünf Flags. Flags sind eine Art von Merken, die den Status einer Operation anzeigen, je nachdem, ob sie gesetzt sind oder nicht.

Das Carry-Flag C oder Übertrags-Flag wird immer dann auf l gesetzt, wenn bei einer arithmetischen Operation aus dem vordersten Bit des Zieloperanden eine Eins als Übertrag entsteht, oder bei der Subtraktion ein „Borgen" durchgeführt wird. Das vorderste Bit ist abhängig von der vorliegenden Verarbeitung. Bei der Langwortverarbeitung ist es das Bit 31, bei Wort das Bit 15 und bei Byte das Bit 7.

Beispiel:

 %10011101
+%01111111
------------
%(1)00011100

Da bei dieser Operation ein Übertrag aus dem 7. in das 8. Bit stattgefunden hat, ist das Carry-Bit im CCR gesetzt worden. Bei der Subtraktion wird das Carry-Bit stets dann gesetzt, wenn die abzuziehende Zahl größer ist als die Zahl, von der abgezogen werden soll.

Das Overflow-Flag V zeigt an, ob während der Durchführung einer arithmetischen Operation ein Zahlenbereich überschritten worden ist. So wird bei der Addition zweier positiver Zahlen das Overflow-Flag gesetzt, wenn als Ergebnis eine negative Zahl im Zweierkomplement erscheint. Dieses Flag hat nur bei Zahlen mit Vorzeichen eine Bedeutung. Außerdem wird es benutzt, um bei der Division anzuzeigen, ob der Dividend zu groß ist oder ob der Quotient größer als 16 Bit werden würde.

Das Zero-Flag Z wird dann auf Eins gesetzt, wenn das Ergebnis einer arithmetischen Operation Null geworden ist.

Das Negativ-Flag N erhält dann eine Eins, wenn das Ergebnis einer negativen Zahl im Zweierkomplement dargestellt wird, also wenn das höchstwertige zu verarbeitende Bit eine Eins ist.

Das Extend-Flag X ist eine Besonderheit des 68000. Dieses Flag wird bei arithmetischen Operationen genauso wie das Carry-Flag gesetzt. Bei Vergleichen bleibt es allerdings unberührt. Das hat den Vorteil, daß man das Carry-Flag über mehrere Operationen in dem Extend-Flag aufheben kann. Als Beispiel dafür wäre die Addition mit mehr als 32 Bit zu nennen.

An dieser Stelle noch eine wichtige Anmerkung zu den negativen Zahlen: In der Praxis hat sich gezeigt, daß viele Leute große Schwierigkeiten mit negativen Zahlen haben. Sie wissen nicht, ob es sich bei einer Zahl, wenn das höchstwertige Bit Eins ist, um eine positive oder negative Zahl handelt, etwa bei %10011100. Ist das nun +156 oder -104? Ob die Zahl positiv oder negativ ist, hängt ganz davon ab, wie Sie die Zahl interpretieren. Das CCR stellt Ihnen alle Informationen über das Ergebnis zur Verfügung. Welche Sie davon nutzen, hängt davon ab, was Sie mit der Zahl vorhaben, ob Sie eine positive oder negative Zahl damit meinen! Sie selbst entscheiden, ob der Zahlenbereich bei acht Bit von 0-255 oder von -128 bis +127 geht. Eingeschränkt in der Wahl der Zahlendarstellung sind Sie nur, wenn der Computer die Zahl als eine Zahl im Zweierkomplement interpretiert.

Vom User- zum System-Byte: Es ist normalerweise vom User nicht benutzbar. Dennoch gibt es einige Möglichkeiten, auf die später eingegangen wird.

Das System-Byte

Das System-Byte besteht aus der Inter-ruptmask, dem Supervisor-Bit und dem Trace-Bit.

Die Interruptmask 10-12

Der 68000 hat drei Interrupteingänge. Mit diesen Eingängen wird die Interruptebene oder die Interruptpriorität festgelegt. Die Maske im SR maskiert den Interrupt. Damit lassen sich die Unteren sechs Interruptebenen ausmaskieren. Die oberste, siebte Ebene, ist etwa mit dem NMI (non maskable Interrupt) anderer Prozessoren vergleichbar. Dieser läßt sich nicht wie die anderen ausmaskieren. Ausmaskieren heißt hierbei „nicht zulassen"; der Interrupt dieser Ebene ist dann blockiert.

Das Supervisor-Bit S

Nach diesem Bit wird die Entscheidung getroffen, welcher Stackpointer gerade benutzt wird. Außerdem entscheidet es darüber, ob auf das System-Byte zugegriffen werden darf. Eine weitere Eigenschaft ist die Zulassung bestimmter „priviligierter" Befehle, die nur im Supervisormodus erlaubt sind. Eine Eins steht für Supervisor-und eine Null für den Usermodus.

Das Trace-Bit T

Das Trace-Bit erlaubt es, ein Programm in Einzelschritten laufen zu lassen. Ist das Trace-Bit gesetzt, also l, wird von dem Benutzerprogramm ein Befehl abgearbeitet. Danach verzweigt der Prozessor an einen festen Vektor. Dieser Vektor ist die Anfangsadresse der Traceroutine. Mit dieser Routine läßt sich dann eine Analyse des jeweiligen Zustandes ausgeben. Anschließend läßt man den nächsten Befehl abarbeiten und so weiter.

Aufbau des Speichers

Der 68000 ist ein Mikroprozessor mit einem 16 Bit breiten Datenbus. Da aber die Adressleitung mit dem niedrigsten Wert AO in zwei Leitungen aufgespalten wurde, nämlich UDS und LDS, teilt sich der Speicher in zwei Hälften zu je 8 Bit. Eine Hälfte hat die geraden, die andere die Ungeraden Adressen. Aus dieser hardwaremäßigen Gegebenheit folgen einige wichtige Voraussetzungen für die Programme.

    1. Befehle (Opcodes) müssen immer an geraden Adressen stehen.
    1. Zugriffe mittels Wort und Langwort dürfen nur an geraden Adressen erfolgen.
    1. Byteverarbeitung ist immer möglich.

Die Mißachtung dieser grundlegenden Voraussetzungen führt zu einer Ausnahmebehandlung (Exeption). Desweiteren ist der Speicher nicht direkt mit dem Prozessor verbunden. Dazwischen liegt noch ein Adressumsetzer, die MMU oder Memory Management Unit. Der Nachteil dieser MMU im ST ist der Adressraum. Dadurch kann man mit dem 68000 nur vier Megabyte (MB) RAM adressieren, obwohl von der Hardware her 16 Megabyte direkt möglich wären. Die MMU bietet dafür aber einige Vorteile, die die Leistungsfähigkeit des Systems steigern. Sonst wäre sie wohl kaum eingebaut worden. Durch sie wird erst eine schnelle Taskumschaltung erreicht. Unter Task versteht man ein abluaffä-higes Programmodul. Außerdem kann das Betriebssystem die Speicherverwaltung übernehmen, Speicherbereiche schützen und Mehrbenutzersysteme verwalten.

Die Arbeitsweise der MMU

Für unsere Zwecke interessiert uns nur die Adressumsetzung. Dazu muß man zwei Begriffe einführen: logische und physikalische Adressen. Die logische Adresse ist die Adresse, die dem Programm zugeordnet wird. Meist ist diese Adresse Null. Die physikalische Adresse ist die tatsächliche Adresse des Programms im Speicher. Würden zum Beispiel mehrere Benutzer auf ihr Programm an der gleichen Adresse zugreifen, so müßten immer erst ganze Speicherbereiche umgeladen werden. Mit der MMU können die Programme alle im Speicher stehen, und es muß bei einem Zugriff nur die MMU neu „geladen" werden, um an das entsprechende Programm zu gelangen. Diese Aufgabe übernimmt das Betriebssystem. Wir müssen uns nur um unsere logischen Adressen kümmern. Wollen etwa zwei Benutzer das gleiche Programm benutzen, ist es mit der MMU möglich, dieses eine Programm für beide zugänglich zu machen (common code). Dies bedeutet Speicherplatzersparnis, da das Programm nur einmal im Speicher ist - mit verschiedenen Datenbereichen für jeden Benutzer.

Exceptions

Eine Exception ist eine Ausnahmebehandlung, die aufgrund eines Befehls oder eines internen oder externen Fehlers hervorgerufen werden kann. Zu den internen Auslösern gehören die Befehle TRAP, TRAPV, CHK und DIV, Adressfehler und der Fall, daß das Tracebit gesetzt ist. Die extern herbeigeführten Exceptions werden durch Interrupts, Bus-Fehler oder von einem Reset ausgelöst.

Jeder Exception ist ein sogenannter Exception-Vektor zugeordnet. Dadurch ist eine Unterschneidung der Fehler möglich, und das entsprechende Programm (Betriebssystem) kann darauf entsprechend reagieren. Die Exception-Vektoren stehen im ersten Kilobyte Speicher und enthalten eine 32-Bit-Adresse. Mit dieser Adresse wird der Programcounter geladen, der dann seine Arbeit dort fortsetzt.

Die Adressierung

Heute haben die Adressierungsarten sehr an Bedeutung gewonnen. Sie sind ein Leistungsmerkmal für den 68000 und für den Einsteiger nicht ganz leicht zu erlernen. Man wird sich allerdings erst dann richtig damit auseinandersetzen, wenn die Not dazu zwingt. Aber die Möglichkeiten sollte man schon jetzt kennen. Dadurch wird manches Programm besser geplant und ist leichter zu programmieren.

Als Adressierungsart bezeichnet manl Sei die Möglichkeit, Daten zu adressieren! we also festzulegen, wie der Prozessor diel Di Adresse der Daten im Speicher berech-j net. Die Adressierung ist die Angabe,! ,. wie die Adresse der Daten zu berech-1 nen ist. Der Prozessor weiß dann, wo-1 her er die Daten nehmen oder wohin | d er sie bringen soll.

Zur Erleichterung der Arbeit werden! zunächst einige Begriffe und Schreib-! weisen erklärt. Einer der wichtigsten! ' Begriffe ist die EFFEKTIVE ADRESSE. Sie ist der Modus, in dem die Datenquelle oder das Ziel eines Befehls angesprochen wird. Sie wird mit EA abgekürzt. Wenn man die Schreibweise (ea) verwendet, so ist der Inhalt der l Speicherstelle gemeint, die die EA | adressiert. ,:.

Beispiel:

EA = $1244
An $1244 steht 34
(ea) = 34

Befehlsaufbau

Ein Befehl besteht aus dem Befehlscode der Assemblersprache (Mnemonik), der Quelle und dem Ziel, also aus dem WAS, dem WOHER und dem WOHIN. Einer der leistungsfähigsten und meistgebrachten Befehle ist der MO VE-Befehl. Move bedeutet bewegen, bringen, verschieben oder transportieren.

MOVE.x Quelle, Ziel oder
MOVE.x (eal),(ea2)

Im Klartext heißt das: Bringe die Daten von der Quelle zum Ziel. Für Quelle und Ziel ist jeweils eine effektive Adresse einzusetzen. Durch einfaches Vertauschen von Quelle und Ziel wird der Speicherbefehl zum Ladebefehl und umgekehrt. Nun sind die Operanden der Adressierung festgelegt. Die Datenlänge, die verarbeitet werden soll, wird durch das x bestimmt. Für das x kann B (Byteverarbeitung), W (Wortverarbeitung) oder L (Langwortverarbeitung) eingesetzt werden. Läßt man die Angabe weg, setzt der Assembler Wortverarbeitung ein.

Die Adressierungsarten

Es gibt insgesamt 12 Adressierungsarten. Eine Tabelle zeigt sie mit ihrer Assemblerschreibweise.

Schreibweise Adressierungsart

Dn Datenregister direkt

An Adressregister direkt

(An) Adressregister indirekt (ARI)

(An)+ ARI mit Postinkrement

-(An) ARI mit Predekrement

d!6(an) ARI mit Adressdistanz

d8(An,Rx) ARI mit Adressdistanz und

Index

SXXXX Absolut Kurz

SXXXXXXXXAbsolut Lang d!6(PC) PC relativ mit Adressdistanz

d8(PC,Rx) PC rel. mit Adressdistanz u.

Index #,SR,CCR Konstante, Statusregister

Dabei bedeuten:

D Datenregister

A Adressregister

n,x Zahl von 0 bis 7

d8 Adressdistanz 8 Bit

d!6 Adressdistanz 16 Bit

PC Programcounter

SR Statusregister

CCR Condition Code Register

1.) Register direkt

Bei dieser Adressierungsart werden die Register direkt angesprochen. Dazu werden' keine Daten aus dem Speicher benötigt. Zu den Registern, die angesprochen werden können, gehören:

1.1) Datenregister direkt

Die Schreibweise ist Dn

Beispiel: s

CLR.x DO

CLR ist ein Befehl und steht als Abkürzung für clear. Clear bedeutet löschen. Dieser Befehl löscht je nach Datenlänge (.x) die Bits mit den niedrigsten Werten in dem adressierten Register. : , . ,

CLR.W DO

vorher nachher

DO 12345678 12340000

CLR.L DO i

vorher nachher

DO 12345678 00000000

Wenn nicht das ganze Register angesprochen wird, so wird nur der untere Teil des Registers gelöscht. Dies waren Beispiele für ein Datenregister als Ziel. Nun folgt noch ein Beispiel mit Datenregistern als Quelle und Ziel.

MOVE.W D1,D5

vorher nachher

Dl 12345678 12345678 D5 87654321 87655678

Hier wird der untere Teil des Registers Dl in den unteren Teil des Registers D5 kopiert. Der Inhalt vom Register Dl bleibt dabei erhalten.

1.2) Adressregister direkt Die Schreibweise ist An

Ist ein Adressregister das Ziel der Operation, so wird dies durch Anhängen eines A an den Move-Befehl deutlich gemacht. Dabei ist nur Wort- und Langwortverarbeitung zulässig. Bei Wortverarbeitung wird das angesprochene Adressregister vorzeichenrichtig auf 32 Bit erweitert.

Beispiel:

MOVEA.W A3,A2

vorher nachher

A3 12345678 12345678

A2 XXXXXXXX 00005678

MOVEA.W D6,A5 vorher nachher

D6 43218765 43218765 A5 XXXXXXXX FFFF8765

Man sieht deutlich: Wenn das 15. Bit Eins ist, so werden die restlichen Bits ebenfalls auf Eins gesetzt.

1.3) Statusregister direkt CCR direkt

Die Schreibweise ist SR bzw. CCR

Diese Adressierungsart wird benutzt, um eine Manipulation am Statusregister durchzuführen. Grundsätzlich gilt, ob beim Status- oder beim Condition-Code-Register, daß die Datenlänge Wort ist. Eine Manipulation des CCR ist immer möglich, während Sie beim SR nur im Supervisormodus möglich ist (Priviligierter Befehl). Nichtbeachtung

führt zu einer Exception-Behandlung. Wird im Supervisormodus das SR angesprochen, so werden alle 16 Bit geändert. Die Adressierungsart CCR berührt nur die unteren 8 Bits des SR, obwohl Wortverarbeitung vorliegt.

Beispiel:

MOVE.W D1,SR

vorher nachher

Dl 12342710 12342710 SR XXXX 2710

MOVE.W D3,CCR

vorher nachher

D3 12342710 12342710 SR XXXX XX10

2.) Konstanten Adressierung

Die Schreibweise ist #=XX

oder #XXXX

oder ^XXXXXXXX

oder

Die Konstantenadressierung gibt die Möglichkeit, Daten oder Konstanten direkt im Programm abzulegen. Die Konstante folgt direkt nach dem Op-code oder ist sogar darin untergebracht. Diese Adressierungsart ist durch das Doppelkreuz (=#=) gekennzeichnet und kann nur als Quelle eingesetzt werden, da sie als Ziel kaum Sinn ergibt. Bei bestimmten Befehlen (ADD, AND, SUB...) kann es zu einem anderen Opcode kommen. Um dies zu vermeiden, wird dem Befehl noch ein I (immediate) angehängt. Ob diese Schreibweise notwendig ist, muß man dem Handbuch des Assemblers entnehmen. Mit dieser Adressierungsart kann man Konstanten in Register oder Speicherzellen laden, Konstanten aufaddieren oder subtrahieren und einiges mehr.

Beispiel:

MOVE.W #$1234,D6

vorher nachher

D6 XXXXXXXX XXXX1234

ADDI.B #$37,D1

vorher nachher

Dl 12345678 123456AF
MOVEA.L #$10A3CC42,A5

vorher nachher

A5 XXXXXXXX 10A3CC42

In dem ersten Beispiel wird das Datenregister 6 mit dem Wert, der hinter dem Befehl steht, geladen. Da Wortverarbeitung vorliegt, ist das obere Wort davon nicht betroffen. Das zweite Beispiel zeigt eine Addition der Zahl $37 zu dem Datenregister 1. Ein eventuell entstehender Übertrag wird nicht berücksichtigt. Zum Schluß noch das direkte Laden eines Adressregisters, das analog zum ersten Beispiel abläuft.

Die Programmierung

Wir haben nun einige theoretische Grundlagen geschaffen, um uns mit der Programmierung zu beschäftigen. Da man die Theorie am besten an Beispielen und vor allen Dingen an der eigenen Arbeit lernt, werde ich Ihnen ein ablauffähiges Assemblerprogramm zeigen. Dieses Programm werde ich Ihnen von der Funktion bis zum Probelauf erklären. Danach können Sie die Progframme aus diesem Kurs programmieren und testen. Selbstverständlich können Sie auch eigene kleine oder große Routinen schreiben.

Da der 68000 leider nur Zahlen interpretieren kann und nicht unsere Assemblerschreibweise, benötigen wir einen Assembler, der die Übersetzung besorgt. Die Vorgehensweise will ich an dem SEKA-Assembler von KUMA erläutern.

Bisher habe ich Ihnen nur einige Adressierungsarten nahegebracht und noch keinen Befehl vollständig vorgestellt. Sie haben jedoch bereits jetzt die Möglichkeit, mit Ihrem Assembler ein lauffähiges Programm zu erstellen. Um festzustellen, was der Computer gemacht hat und wie er auf unsere Eingabe reagiert, muß ich Ihnen noch zwei weitere Aufrufe erklären. CO-NIN, das ein Zeichen von der Tastatur holt, und PLINE, das eine Zeichenkette auf den Bildschirm ausgibt. CONIN wird nur mit der Funktionsnummer aufgerufen und liefert, nachdem eine Taste gedrückt worden ist, den ASCII-und SCAN-Code der gedrückten Taste. PLINE gibt, nach Übergabe der Adresse und Funktionsnummer, ab der Adresse die Zeichen aus, bis eine Null erscheint. Die Zeichen werden als ASCII-Zeichen interpretiert. Auf diese Weise können auch die Control-sequenzen für die Bildschirmsteuerung gesendet werden.

Zum Verlassen des Programms benötigen Sie einen Betriebssystemaufruf: TERM. Er benötigt keine weiteren Parameter auf dem Stack, es genügt, die Funktionsnummer zu übergeben. Nach dem Aufruf dieser Funktion kehrt das Programm, nach Freigabe des Speicherplatzes, in das aufrufende Programm zurück.

Außerdem stehen Ihnen alle GEMDOS-Funktionen zur Verfügung, die in „ST-Computer" ab Ausgabe 4 unter der Rubrik „Das ST-Betriebssystem" beschrieben sind. Diese Routinen erleichtern das Arbeiten, ähnlich wie bei höheren Programmiersprachen.

Unser Programm wird als erstes einen Begrüßungstext ausgeben und dann auf eine bestimmte Taste warten. Ist sie gedrückt worden, erscheint eine Bestätigung, die mit einem Tastendruck quittiert werden muß, damit das Programm beendet werden kann.

Die Eingabe

Zuerst starten Sie den Assembler. Nachdem er sich gemeldet hat, drücken Sie die ESC Taste, damit Sie in den Editor kommen. Die neuere Version mit dem Full-Screen-Editor ist wesentlich einfacher als die ältere mit dem Einzeilen-Editor. Schreiben Sie nun das Programm ab. Beachten Sie dabei, Labels (Marken, die eine Adresse während der Assemblierung erhalten) an den Anfang einer Zeile zu schreiben. Befehle und Pseudobefehle (Anweisungen an den Assembler) gehören in eine separate Spalte, die von einer weitern Spalte, dem Kommentar, beendet wird. Diese Aufteilung ist für die Funktion nicht notwendig, erleichtert jedoch die Lesbarkeit. Ebenso sollte von den Zuweisungen, Labels und Kommentaren ausgiebig Gebrauch gemacht werden, um die Lesbarkeit zu unterstützen. Dadurch wird eine spätere Änderung des Programms um so leichter möglich. Als Faustregel gilt: Ebenso viel Kommentar wie Programm.

Das Testen

Wenn Sie das Programm eingegeben haben, beenden Sie die Eingabe mit der ESC-Taste. Zum Schutz Ihrer Arbeit speichern Sie Ihr Programm erst einmal ab: mit der Eingabe w für write mit anschließendem RETURN. Seka fragt Sie nun nach dem Namen des Programms. Geben Sie nun einen Namen ein (z. B. akul), den man wieder mit RETURN abschließt. Nach der Speicherung lassen wir das Programm assemblieren. Dies tun wir mit dem Befehl a. Die Frage nach der Option beantworten wir mit einem RETURN. Wenn wir nun die Meldung „NO ERRORS" erhalten, so haben Sie ein syntaktisch fehlerfreies Programm eingegeben. Ist dies nicht der Fall, so ändern Sie die entsprechende Zeile richtig ab. Wiederholen Sie die Assemblierung und Fehlerkorrektur so lange, bis kein Fehler mehr erscheint. Dieses fehlerfreie Programm können Sie nun mit „w" abspeichern. Anschließend speichern wir noch das Objektprogramm mit dem Befehl wo unter dem gleichen Namen ab. Da das Programm unter TOS laufen soll, hängen Sie ein .tos hinter dem Namen an. Nun können Sie den Assembler mit einem ! verlassen.

Der Lauf

Es gibt zwei Möglichkeiten, das Programm laufen zu lassen, vom Assembler und von GEM aus. Vom Assembler aus kann man das Programm mit einem g und der Startadresse starten. Da der Assembler die Labeltabelle noch kennt, kann man einfach ein La-bel angeben, in unserem Fall statt. Anschließend fragt der Assembler nach dem Breakpoint. Dies ist end, da unser Programm dort endet. Die Frage nach einem weiteren Breakpoint beantworten Sie einfach mit Return.

Die zweite Möglichkeit ist hinreichend bekannt. Da es ein ablauffähiges Programm unter TOS ist, kann es vom GEM aus einfach angeklickt werden.

Zum Abschluß dieses ersten Teils wünsche ich Ihnen viel Erfolg. Wenn nicht alles auf Anhieb klappt, verzagen Sie nicht, denn nur aus Fehlern lernt man. Bei Assembler gibt es, wie in anderen Computersprachen auch, eine ganze Menge Fehlerquellen, aber hier werden sie nicht von einem Interpreter oder Compiler abgefangen.


Sven Schuler
Aus: ST-Computer 12 / 1986, Seite

Links

Copyright-Bestimmungen: siehe Über diese Seite