Adressierung (Rechnerarchitektur)
Adressierung ist in der Programmierung das Festlegen, auf welche Operanden (z. B. Datenfelder) sich ein Maschinenbefehl bezieht. Die Operanden können auf unterschiedliche Art und Weise adressiert werden (Adressierungsart oder Adressierungsmodus), zum Beispiel durch direkte Angabe im Befehl oder durch einen Verweis auf eine Speicheradresse. Bestimmend für die anzuwendende Adressierungsart sind der Operationscode und die im Maschinenbefehl nur in codierter Form enthaltenen Angaben über die Operanden.
Bei der Assemblerprogrammierung legt der Programmierer durch die Wahl bestimmter Operationscodes (und der dazugehörenden Parameter) die Adressierungsart selbst fest. Bei Nutzung höherer Programmiersprachen werden die Maschinenbefehle von Compilern automatisch erzeugt (und damit auch deren Adressierungsarten festgelegt), meist ohne direkten Einfluss des Programmierers. Der Prozessor dekodiert die Maschinenbefehle bei der Ausführung und führt die entsprechenden Adressrechnungen sowie das Laden der im Befehl zu verwendenden Daten durch.
Die verschiedenen Adressierungsarten sind ein Aspekt des Prozessordesigns. Sie sind innerhalb einer gegebenen Befehlssatzarchitektur definiert und bestimmen, wie für jede Instruktion der Maschinensprache die tatsächliche (physische) Speicheradresse ihrer Operanden ermittelt/errechnet wird, zum Beispiel mithilfe der Informationen, die in Registern gespeichert sind und/oder Konstanten innerhalb des Maschinenbefehls.
Bezieht sich ein Befehl auf mehrere Operanden (Quell- und/oder Zielfelder), so sind die zur Adressierung erforderlichen Angaben für jeden Operanden getrennt erforderlich/vorhanden. Weitere im Maschinenbefehl enthaltene Parameter (wie Angaben zur Länge von Operanden, Sprungindikatoren aus logischen Befehlen wie gleich oder größer) werden zur Adressierung im engeren Sinn nicht verwendet.
Unterschiede mit Bezug zu Adressierungsarten
Unterschiedliche Bezeichnungen
Man beachte, dass keine allgemeingültige Namensgebung für die unterschiedlichen Adressierungsarten/-modi existiert. Insbesondere verwenden teilweise verschiedene Autoren oder auch Hardwarehersteller unterschiedliche Bezeichnungen für den gleichen Adressenmodus, oder auch den gleichen Namen für unterschiedliche Modi.
Folgende Unterscheidungen in der Namensgebung von Adressierungsarten sind weit verbreitet. Eine grundlegende Unterscheidung ist die zwischen
- logischen bzw. programmseitigen Adressen einerseits (Ebene Programmierung). Logische Adressen werden in absolute, relative, indirekte und symbolische Adressen unterteilt, wobei man allerdings verschiedene genaue Charakterisierungen, Abgrenzungen und Überschneidungen findet.
- Maschinenadressen bzw. physischen Adressen andererseits (Ebene Maschinenbefehl). Maschinenadressen werden auch oft reale Adressen genannt.
Neben der unterschiedlichen Bezeichnung kann ein Adressierungsmodus, der in der einen Architektur als ein einzelner Modus behandelt wird, für eine Funktionalität stehen, die in einer anderen Architektur von zwei oder mehr Modi abgedeckt wird.
Im Detail unterschiedliche Bedeutung
Mit ‚Adressierung‘ kann im Detail Unterschiedliches verstanden werden:
- Die Tätigkeit beim Programmieren in maschinennahen Sprachen: Wahl der Befehle, dabei Codieren der Operatoren
- Die auf die Operatoren in Codeform verweisenden Angaben im Maschinenbefehl
- Die Funktionalität des Prozessors, mit der er die tatsächlichen Adressen ermittelt
In einer höheren Programmiersprache die Operatoren zu benennen (MOVE A TO B), im weiteren Sinn auch eine Art von Adressierung, zählt nicht zu dem hier im Artikel behandelten Bedeutungfeld ‚Adressierung, Adressierungsmodus‘.
Unterschiede zwischen Befehlssätzen
Die Befehlssätze einzelner Prozessortypen unterscheiden sich nicht nur im Leistungsumfang, sondern auch die Adressierung betreffend. Nachfolgend werden signifikante Beispiele aufgeführt:
- In bestimmten Befehlssätzen enthält der Opcode die Registernummer – während in anderen Fällen die Registernummer in einem eigenen Parameterfeld enthalten ist. Dementsprechend enthält ein solcher Befehlssatz sehr viel mehr Operationscodes.
- In der Prozessorfamilie System/390 können nur 1-stellige Direktwerte ('immediate') im Maschinenbefehl enthalten sein. Zur ‚indizierten Adressierung‘ wird der Offset-Wert für eine Adressangabe zusammen mit der Registernummer in einem 'Halbwort' (4 Bits Registernummer, 12 Bits Offset/ganzzahlig) gespeichert.
Typische Adressierungsarten eines Prozessors
Im einfachsten Fall sind die einzelnen Speicherplätze des Speichers von 0 an durchnummeriert (linearer Adressraum). Eine Adresse stellt dann die Nummer eines bestimmten Speicherplatzes dar. Die Register eines Prozessors werden im Regelfall ebenfalls durchnummeriert.
Aufgrund der unterschiedlichen Adressierungsarten weisen Maschinenbefehle unterschiedliche Strukturen auf, zum Beispiel gehört zu einem Operationscode ein Operand, zu anderen mehrere Operanden als Quelle oder Ziel des Befehls. Befehlsbeispiele siehe einzelne Adressierungsart.
Da in einem Prozessor meist nur wenige Register, aber viele Speicherplätze existieren, sind Registeradressen kürzer als Hauptspeicheradressen. Beispiel: Bei einem System mit einem Prozessor mit 16 Registern sowie 4 GiB Speicher benötigt eine Registeradresse 4 Bit, während eine Hauptspeicheradresse 32 Bit benötigt. In der Maschinensprache werden Registeradressen oft zusammen mit dem Befehlscode in einem Speicherwort gespeichert – stehen mithin dem Prozessor ohne weitere Speicherzugriffe zur Verfügung, während der Prozessor für die Übermittlung jeder Hauptspeicheradresse weitere Speicherzugriffe – und damit Ausführungszeit – benötigt.
Bei einem rein orthogonalen Befehlssatz ist jeder Befehl in jeder Adressierungsart verwendbar. Bei den verbreiteten Prozessorfamilien bestehen jedoch vielerlei Einschränkungen, so dass der (Assembler-)Programmierer sich über das „Programmiermodell“ des Prozessors informieren muss, welche Adressierungsarten bei welchen Befehlen tatsächlich verfügbar sind.
Adressierungsarten, die vom Hauptspeicher in den Hauptspeicher arbeiten, werden heute nur noch in Integrierten Schaltkreisen und eingebetteten Systemen mit wenig Speicherplatz angewandt. Hohe Ausführungsgeschwindigkeiten sind nur mit Befehlen zu erreichen, die in den Registern arbeiten – daher besitzen auf Leistung optimierte Prozessoren heute meist eine Load/Store-Architektur.
Registeradressierung
Bei der Registeradressierung (in Englisch „register direct“) bezieht sich der Befehl auf den Inhalt eines Prozessorregisters. Bei 'lesenden' Befehlen steht der Operand bereits im Register bereit und muss nicht mehr aus dem Speicher geladen werden. Bei impliziter Registeradressierung wird das implizit für den Opcode festgelegte Register verwendet (Beispiel: der Opcode bezieht sich implizit auf den Akkumulator). Bei expliziter Registeradressierung ist die Nummer des Registers in einem Registerfeld des Maschinenbefehls eingetragen oder Teil des Befehlscodes.
# Addiere den Inhalt von Register 1 mit dem Inhalt des Registers 2, speichere Ergebnis in Register 3 add_rrr R2, R1, R3 # Also drei Adressierungen: # Quelle_1 .. Register, # Quelle_2 .. Register, # Ziel_1 .. Register
Unmittelbare Adressierung
Der oder die Operanden (nicht ihre Adresse) sind Bestandteil des Befehls, gespeichert im Befehlscode selbst oder in den Speicherwörtern, die im Speicher dem Befehlscode unmittelbar folgen. Der Befehl enthält in der Regel einen weiteren Operanden.
# Lade das Akkumulatorregister mit dem Wert 22 (101102) (nicht mit dem Inhalt von Speicherplatz 22) load_direct acc, 10110 # Also zwei Adressierungen: # Ziel_1 .. Register # Quelle_1 .. unmittelbar angegebener Wert
Absolute oder direkte Adressierung
Bei dieser Adressierungsart wird nicht der Operand selbst, sondern seine Speicheradresse (wo die eigentlichen Daten zu finden sind) direkt und vollständig im Befehl angegeben (Referenzstufe 1).
# Addiere den Inhalt von Adresse 22 (= 101102) und Adresse 6 (= 001102) und speichere das Ergebnis in Adresse 1 (= 000012) add_AdrAdrAdr 10110, 00110, 00001
Indizierte und relative Adressierung
Beide Adressierungsarten verwenden ein Register zur Adressierung von Speicherzellen im Hauptspeicher. Bei der indizierten Adressierung wird der Inhalt eines sogenannten Indexregisters zu einer aus anderen Adressangaben gebildeten Adresse addiert. Beispiel: Es gibt ein Basis-Adress-Register (z. B. das Spezialregister „index“), zu dem der mitgegebene Parameter als Offset addiert wird. Oft sind auch negative Offsets möglich. Das Ergebnis der Adressierung ist die Adresse des Operanden, d. h. diese zeigt auf den Operanden (Referenzstufe 1)
# Addiere den Inhalt der Adressen (Index+002 =22) und (Index+012 =23) und speichere das Ergebnis in Adresse (Index+102 =24) load_direct index, 10110 # lade (Basis-)Adresse 22 ins Indexregister add_iii 00, 01, 10
Oft haben diese relativen Adressen weniger Stellen (beispielsweise 8 Bit, also 8 Binärstellen; bei 8-Bit-Opcode hat der Gesamtbefehl dann 8+3*8=32 Bit Länge), was einerseits Platz spart und den Gesamtbefehl inklusive Adressierungsdaten evtl. "auf einmal ladbar" macht; andererseits schränkt dies den Adressraum ein (im Beispiel ist so nur index+000000002 .. index+111111112 möglich).
Diese Zugriffsart wird vor allem verwendet für Zugriffe auf Arrays oder zusammengesetzte Datentypen.
Da ein Rechner im Allgemeinen mehr als ein Register hat, muss der Befehl die Angabe enthalten, welches Register als Basisregister zu benutzen ist. Im Beispiel ist angenommen, dass hierfür das Register „index“ fest vorgegeben ist.
Die relative Adressierung verläuft ähnlich, allerdings wird statt des Indexregisters der Befehlszähler (program counter, PC) benutzt. Die Adressierung erfolgt also nicht relativ zu einer im Indexregister angegebenen Adresse, sondern relativ zum Befehlszähler, d. h. der Speicherstelle, die den Befehl selbst enthält.
Mitunter kann der Offset auch in einem Register gegeben sein, insbesondere bei der sogenannten segmentierten Adressierung. Das Basis-Adress-Register wird dann oft „Segmentregister“ genannt.
Indirekte Adressierung
Der Befehl weist auf ein Register oder eine Speicheradresse im Hauptspeicher (beim 6502 in dessen Zeropage). Die effektive Adresse der Operation ergibt sich aus dem Inhalt des entsprechenden Registers bzw. der entsprechenden Speicherzelle(n) (Referenzstufe 2). Ggf. wird auf die so ermittelte Adresse noch der Inhalt eines weiteren Registers (Indexregisters) addiert (indirekt-indizierte Adressierung).
Die indirekte Adressierung wurde 1953 von Heinz Schecher patentiert.
Virtuelle Adressierung
Hier werden Werkzeuge zur Adressierung beschrieben, die das Betriebssystem zur Verfügung stellt.
Betriebssysteme verwenden die Virtuelle Adressierung, um Programme ausführen zu können, die mehr Speicherplatz benötigen, als an physischem Arbeitsspeicher im RAM überhaupt zur Verfügung steht. Der gesamte zur Verfügung stehende Speicherplatz wird als Virtueller Adressraum bezeichnet und der Zugriff auf die darin enthaltenen Adressen ist die virtuelle Adressierung. Das jeweilige Betriebssystem verwendet eine Virtuelle Speicherverwaltung, die sich einer Memory Management Unit bedient, um Teile des Programms auf die Festplatte auszulagern und ggf. in den Arbeitsspeicher zu laden, falls sich eine gewählte Adresse außerhalb des im RAM befindlichen Adressraums befindet. Die Angabe der Adressen erfolgt dabei entweder direkt, relativ, indiziert oder auch symbolisch.
Literatur
- Hans Liebig: Rechnerorganisation: Die Prinzipien. Springer-Verlag, 3. Aufl., 2003, ISBN 978-3-540-00027-3
- Hrsg. Thomas Beierlein, Olaf Hagenbruch: Taschenbuch Mikroprozessortechnik. Carl Hanser Verlag, 4. Aufl., 2010, ISBN 978-3-446-42331-2