Adressierungsarten Ein Mikroprozessor bietet meist eine Reihe von Möglichkeiten, die Operanden für eine Rechenoperation zu bestimmen. Diese Möglichkeiten bezeichnet man als Adressierungsarten. unmittelbare Adressierung (immediate) Bei dieser Adressierungsart ist der Operand eine Konstante, die direkt hinter dem OpCode im Speicher steht. MOVE #123,D1 Lade D1 mit 123 Eine Konstante kann nur als Quelloperand auftreten, nie als Ergebnis einer Rechenoperation. Häufig wird diese Adressierung verwendet, um Register des Prozessors mit Startwerten oder Adressen vorzubelegen. In Assemblerschreibweise wird der Konstanten beim 68000 das Zeichen # vorangestellt. absolute Adressierung (direct, absolute) Die effektive Adresse des Operanden befindet sich als absolute Adresse direkt im Anschluß an den Opcode im Speicher. In der Assemblersyntax (68000) steht die Adresse ohne spezielle Kennzeichnung als Zahlenwert direkt hinter dem Opcode.
Registeradressierung (register direct) Der Operand steht in einem der Prozessorregister. Die Adresse steht als kurze Registeradresse im OpCode. Als Register können universelle Register wie z.b. Datenregister oder Adreßregister, aber auch spezielle Register wie Stackpointer, Statusregister usw. angesprochen werden. CLR D1 Lösche D1 Registerindirekte Adressierung (register indirect) Die effektive Adresse steht in einem Register, üblicherweise in einem Adreßregister, der Operand steht im Speicher. Diese Adressierungsart hat gegenüber der absoluten Adressierung den Vorteil, daß beim Holen des Befehls die Operandenadresse nicht gelesen werden muß. Sie wird eingesetzt, wenn innerhalb eines Programmteils häufig auf dieselbe Operandenadresse zugegriffen wird. In Assemblersyntax wird der Name des zur Adressierung verwendeten Registers in Klammern geschrieben. MOVE D1,(A1) Lade die Speicherstelle, mit der Adresse in A1 mit D1.
Registerindirekte Adressierung mit Postinkrement Bei der Adressierung wird der Inhalt des verwendeten Adreßregisters verändert. Beim Postinkrement wird nach der Verwendung der Adresse der Inhalt des Registers inkrementiert, wobei das Inkrement abhängig von der Datenbreite des adressierten Operanden die Werte 1, 2 oder 4 annehmen kann. Diese Anpassung der Schrittweite nennt man Skalierung, da das Inkrement mit dem skalaren Faktor 1,2 oder 4 multipliziert wird. Wird zum Beispiel mit dem Befehl MOVE.B D1, (A1)+ ein Byte vom Datenregister D1 in den Speicher kopiert, so wird A1 anschließend um den Wert 1 erhöht. Wird mit MOVE.L D1, (A1)+ ein Langwort, also 4 Byte kopiert, so wird A1 entsprechend um den Wert 4 inkrementiert. Nach der Befehlausführung zeigt daher das Adreßregister immer auf das nächste Datenwort im Speicher. Diese Adressierungsart eignet sich für die Bearbeitung von Datenfeldern in einer Schleife, wie das Beispiel 5.5 zeigt. Soll das Feld nicht byteweise, sondern wortweise mit 1 belegt werden, so muß nur move.b durch move.w ersetzt werden, die Adreßberechnung passt sich automatisch an. Im folgenden Programmausschnitt werden die Elemente eines Feldes mit dem ; Wert 1 vorbelegt. FELDANF equ 10000 ; Startadresse des Feldes FELDEND equ FELDANF+100 ; Endadresse des Feldes move.l #FELDANF,A1 ; Startadresse ins Register A1 LOOP move.b #1, (A1)+ ; 1 in das akt. Feldelement cmp.l FELDEND, A1 ; Vergleich auf Feldende ble LOOP ; Verzweigung zu LOOP, falls ; Feldende noch nicht erreicht ist
Registerindirekte Adressierung mit Prädekrement Das Gegenstück zum Postinkrement ist die Adressierung mit Prädekrement. Hierbei wird vor dem Speicherzugriff der Inhalt des Adressregisters dekrementiert. Diese Adressierungsart wird durch ein Minuszeichen vor dem Adreßregister symbolisiert. Wird als Adreßregister der Stackpointer verwendet, so ersetzen diese beiden Adressierungsarten die Befehle PUSH und POP zur Stackverwaltung Registerindirekte Adressierung mit Displacement Bei der Adressierung mit Displacement wird die effektive Adresse aus dem Inhalt eines Adreßregisters und einer konstanten Adreßdistanz (Displacement) berechnet. Das Displacement ist vorzeichenbehaftet (2er-Komplement) und erlaubt so eine positive und negative Adreßdistanz zur Basisadresse im Adreßregister. Diese Methode wird beim Zugriff auf Daten verwendet, die in einer festen Struktur im Speicher vorliegen, wie z.b. Directoryeinträge im Dateiverwaltungssystem oder Register eines Peripheriebausteins. Durch Ändern der Basisadresse im Adreßregister wird so auf das gleiche Element im nächsten Datensatz zugegriffen bzw. es kann eine variable IO-Basisadresse berücksichtigt werden. In der Assemblersyntax wird das Displacement durch eine Zahl vor dem Adreßregister angegeben.
Indizierte Adressierung mit Displacement Wird neben einer Konstanten noch eine variable Adreßdistanz benötigt, die erst zur Laufzeit eines Programms feststeht, so wird die indizierte Adressierung verwendet. Die effektive Adresse wird hier aus der Basisadresse in einem Adreßregister, einem konstanten und einem variablen Adreßversatz aus einem weiteren Register berechnet MOVE D1,$5(A1,D0) Lade die Speicherstelle an der Adresse A1+D0+$5 mit D1.
PC-relative Adressierung Eine interessante Variante ist die Verwendung des Befehlszählers (program counter) als Adreßregisters. Die effektive Adresse wird hier immer mit Bezug zum aktuellen Befehlszähler gebildet, d.h. alle Adressen werden nur mehr als relativer Adreßabstand zum Befehlszähler abgespeichert. Die befehlszählerrelative Adressierung ermöglicht es, ein übersetztes Programm mitsamt Daten und Konstanten im Speicher zu verschieben. Der Befehlszähler darf dabei natürlich nicht verändert werden, da sonst das Programm nicht mehr korrekt ablaufen würde. Von den bisher vorgestellten Methoden eignen sich daher nur die indizierte Adressierung oder die Adressierung mit Displacement zur PC-relativen Adressierung. Die Assemblersyntax verwendet die bereits besprochene Schreibweise, statt einem Adreßregister steht in Klammern das Symbol PC für ProgramCounter.
Assemblerprogramm 1 ; Es werden alle Zahlen von einem Startwert bis zu einem Endwert addiert 2 org $10000 ; Startadresse des Programms 3 STEP equ 1 ; Schrittweite wird als Konstante vereinbart 4 5 clr D0 ; Register D0 wird gelöscht 6 move FIRST,D1 ; Startwert ins Register D1 7 SCH add D1, D0 ; D1 wird zu D0 addiert, ; Ergebnis in D0 8 add #STEP,D1 ; D1 wird um Schrittweite inkrementiert 9 cmp LAST, D1 ; Vergleich von D1 mit dem Endwert 10 ble SCH ; Verzweigung zu SCH, falls Endwert ; noch nicht erreicht ist 11 move D0, SU ; Ergebnis wird in den Speicher kopiert 12 stop #0 13 14 FIRST dc.w 1 ; Speicherplatz für Startwert 15 LAST dc.w 100 ; und Endwert 16 SU ds.w 1 ; Speicherplatz für Ergebnis 17 18 end ; Ende des Programms Maschinencode im Speicher in hexadezimaler Schreibweise Zeilen nr Adresse OpCode Operandenadres se 5 10000 4240 6 10002 3239 0001 0020 7 10008 D041 8 1000A D27C 0001 9 1000E B279 0001 0022 10 10014 6F00 FFF2 11 10018 33C1 0001 0024 12 1001E 4E72 0000 13 14 10020 0001 15 10022 0064 16 10024 0000 17 18