Wenn ein 32 -Bit-Prozessor etwa 4 GiB RAM verarbeiten kann (d. h ) Bytes, warum hat mein Arduino Mega 2560 8 KiB SRAM, wenn er als 8 -Bit-Prozessor nur 256 Bytes verarbeiten kann ( )? Oder lese ich die folgende Seite falsch?
Die meisten 8-Bit-CPUs haben 16-Bit-Adressbusse, mit denen sie 64 kByte adressieren können, gerade weil 256 Byte wirklich nicht ausreichen, um viel zu tun! Es bedeutet nur, dass sie jedes Mal zwei Bytes statt einem laden müssen, wenn sie eine Adresse laden müssen. Etwas langsamer, aber in Anbetracht ihrer Größe erträglich.
(Und ja, es gibt viele Ausnahmen, die meistens entwickelt wurden, als 64k zu klein wurde, aber wir sprechen hier über die Grundidee).
Der Adressbus und der Datenbus sind getrennt, sodass sie unterschiedliche Größen haben können. Für bestimmte Adressbusgrößen gibt es viele Techniken, um mehr Speicher als die Registerbitbreite zu adressieren
Die gebräuchlichste Methode besteht darin , die Adressbusbreite irgendwie zu erhöhen
Verwendung mehrerer Register für die Adresse
X
, um maximal 64 KB RAM zu ermöglichen. Diese wiederum können mit , , gepaart werden , um in noch größeren Versionen auf höhere RAM-Adressen zuzugreifen. Außerdem hat er für die High-Bytes des Stackpointers zusätzlich bei Varianten mit mehr als 256 Bytes RAM 1Y
Z
RAMPX
RAMPY
RAMPZ
SPH
SPL
H
& L
, B
& C
, D
& E
, die zusammen als 16-Bit-Adressregister verwendet werden könnenVerwenden eines einzigen großen Spezialregisters, das größer als die natürliche Größe zum Adressieren ist
Verwendung eines speziellen Registers für den oberen Teil der Adresse . Beim Adressieren von Speicher werden standardmäßig die 8 niedrigen Bits der Adresse aus dem 8-Bit-Immediate- oder 8-Bit-Register auf einem 8-Bit-Mikrocontroller genommen, während die hohen Bits durch den Wert des anderen Adressregisters ersetzt werden.
call
or goto
werden 8 oder 9 niedrige Bits der Adresse vom Direktwert angezeigt, und der Rest wird vom aktuellen Programmzähler genommen. Der Zugriff auf alles in der Nähe des aktuellen Segments benötigt also nur 1 Befehl, während weitere Adressen 2 Befehle benötigen (um die hohen Bits zu setzen).PC
während sie bedingungslos springt.Eine andere Möglichkeit, dies zu erreichen, ist Memory Banking . Dies ist eine nützliche Methode, die heutzutage noch in einigen Architekturen verwendet wird. Bei diesem Modell ist der Speicher in mehrere Bänke unterteilt . Sie können jeweils nur eine bestimmte Bank ansprechen. Es gibt oft einen globalen Bank- oder Adressbereich, der jederzeit sichtbar ist, aber für andere Teile müssen Sie bei Bedarf die Bank wechseln.
Es gibt auch eine nicht ganz verbreitete Technik, die aber im Intel 8051 zu finden ist . Als Mikrocontroller mit 8-Bit-Datenadresse kann er maximal 256 Adressen haben. Die Hälfte des Speicherplatzes (der hohe Teil) wird für Spezialfunktionsregister ( SFR ) verwendet, wodurch das wirklich adressierbare RAM auf nur 128 Bytes begrenzt wird. Die Hersteller moderner 8051-Serien haben jedoch einen cleveren Weg gefunden, dies zu überwinden, indem sie den Speicherzugriff getrennt haben . Die direkte Adressierung greift auf den SFR zu, während die indirekte Adressierung auf den oberen Teil des RAM zugreift, was bedeutet, dass Sie jetzt 256 + 128 = 384 adressierbare Bytes haben.
1 https://en.wikipedia.org/wiki/Atmel_AVR_instruction_set#Memory_addressing_instructions
Die kleinsten Kerne haben ≤256 Byte Datenadressraum (d. h. ≤128 Byte RAM, nachdem E/A-Ports und andere reservierte Adressen entfernt wurden) und ≤8192 Byte (8 KiB) Programm-ROM. Diese haben nur einen 8-Bit-Stapelzeiger (in SPL) und unterstützen nur die relativen 12-Bit-Sprung-/Aufrufbefehle RJMP/RCALL. (Da der AVR-Programmzähler 16-Bit-Wörter und keine Bytes zählt, reicht ein 12-Bit-Offset aus, um 213 Bytes ROM zu adressieren.)
Zusätzliche Speicheradressierungsfunktionen sind nach Bedarf vorhanden, um auf verfügbare Ressourcen zuzugreifen:
- Modelle mit >256 Byte Datenadressraum (≥256 Byte RAM) haben einen 16-Bit-Stapelzeiger, wobei sich die obere Hälfte im SPH-Register befindet.
- Modelle mit >8 KiB ROM fügen die 2-Wort (22-Bit) JUMP- und CALL-Anweisungen hinzu. (Bei einigen frühen Modellen tritt ein Fehler auf, wenn auf eine Skip-Anweisung eine 2-Wort-Anweisung folgt.)
- Modelle mit >64 KiB ROM fügen den ELPM-Befehl und das entsprechende RAMPZ-Register hinzu. LPM-Befehle erweitern die ROM-Adresse in Z um Null; ELPM-Befehle stellen das RAMPZ-Register für hohe Bits voran. Dies ist nicht dasselbe wie die allgemeinere LPM-Anweisung; Es gibt "klassische" Modelle mit nur der Nulloperandenform von ELPM (ATmega103 und at43usb320). Wenn Auto-Increment verfügbar ist (bei den meisten Modellen), wird die gesamte 24-Bit-Adresse einschließlich RAMPZ aktualisiert.
- (Seltene) Modelle mit >128 KiB ROM haben einen 3-Byte-Programmzähler. Unterroutinenaufrufe und -rückgaben verwenden ein zusätzliches Byte Stapelplatz, es gibt ein neues EIND-Register, um zusätzliche hohe Bits für indirekte Sprünge und Aufrufe bereitzustellen, und es gibt neue erweiterte Befehle EIJMP und EICALL, die EIND:Z als Zieladresse verwenden. (Die vorherigen IJMP- und ICALL-Befehle verwenden nullerweitertes Z.)
- (Seltene) Modelle mit >64 KiB RAM-Adressraum erweitern die 16-Bit-RAM-Adressierungsgrenzen mit RAMPX-, RAMPY-, RAMPZ- und RAMPD-Registern. Diese stellen zusätzliche hohe Bits für Adressierungsmodi bereit, die die X-, Y- bzw. Z-Registerpaare oder die direkten Adressierungsbefehle LDS/STS verwenden. Im Gegensatz zum ROM-Zugriff gibt es keine eindeutigen "erweiterten" Anweisungen; stattdessen werden die RAMP-Register unbedingt verwendet.
Datenbusleitungen (Pins) und Adressleitungen (Pins) sind vollständig getrennt. Einfach ausgedrückt, Datenbusleitungen bestimmen die maximale Anzahl von Bits, die einzeln übertragen (und im Speicher gespeichert) werden können, während Adressleitungen die maximale Anzahl von Speicher-"Zellen" bestimmen, die ausgewählt werden können.
Es war hauptsächlich eine Marketingsache, dass 32-Bit-x86-CPUs nicht mehr als 4 GB RAM adressieren konnten. Ich erinnere mich irgendwo, dass es auf Pentium 4-CPUs A33-34-Pins gab.
Nahezu alle 8-Bit-Prozessoren haben eine gewisse Fähigkeit, eine 16-Bit-Adresse aus einem niederwertigen Teil und einem höherwertigen Teil zu bilden. Auf einigen Prozessoren, einschließlich des ursprünglichen 8080, gibt es Register, die dazu bestimmt sind, den oberen und unteren Teil einer Adresse zu halten (obwohl es aus Sicht eines Programmierers einige Register wie den Stapelzeiger des 8080 geben kann, die keine Anweisungen bieten, um sie separat zu adressieren). In einigen anderen Prozessoren gibt es keine Register, die der oberen oder unteren Hälfte einer Adresse gewidmet sind, aber Adressen werden "on the fly" zusammengestellt. Beispielsweise lädt beim 6502 der Befehl „LDA $1234,X“ den Akkumulator mit der Adresse, die durch Hinzufügen von $1234 zum 8-Bit-X-Register gebildet wird [angenommen, es enthält $F0]. Die Ausführung dieser Anweisung würde in 4 oder 5 Schritten ablaufen:
Die Übertragung des gelesenen Bytes zum Akkumulator überlappt das Holen des nächsten Befehls. Außerdem hätte Schritt 4 bei vielen Operationen die richtige Adresse gelesen, wenn Schritt 3 keinen Übertrag erzeugt hätte, und die Ausführung könnte direkt von Schritt 4 zur nächsten Anweisung springen, wobei Schritt 5 umgangen wird.
Wenn man die Abfolge der Operationen untersucht, wird man feststellen, dass eine Little-Endian-Architektur in den meisten Fällen (wenn auch nicht in dem gezeigten) einen deutlichen Vorteil gegenüber einer Big-Endian-Architektur hat, obwohl die ALU einen Zyklus für die Ausführung benötigt Zusätzlich ist es möglich, ein Byte aus der berechneten Adresse zu lesen, ohne auf das ALU-Ergebnis zu warten, da normalerweise das abgerufene High-Byte das High-Byte des Zieloperanden ist. Auf einer Big-Endian-Maschine mit einer 8-Bit-ALU würde ein indiziertes Laden mindestens 5 Zyklen dauern (da die untere Hälfte der Adresse erst in Schritt 3 gelesen und somit in Schritt 4 berechnet würde).
Ich werde diese Frage speziell für die von Ihnen erwähnten AVR-Controller beantworten. Das Grundprinzip gilt auch für viele andere 8-Bit-Architekturen.
AVRs sind 8-Bit-Kerne. Das bedeutet, dass sie 8-Bit-Register haben. 8 Bit reichen jedoch nicht aus, um auf eine nutzbare Speichermenge zuzugreifen. Daher ist der AVR-Kern in der Lage, einen bestimmten Satz von Registern zu verwenden, die als 16-Bit-Zeigerregister kombiniert sind. Ein Beispiel hierfür sind die Register r30 und r31 (auch als ZL und ZH bezeichnet). Zusammen bilden sie den Z-Pointer.
In Assembly würde das Lesen eines Bytes an Adresse 0x1234 so aussehen:
ldi ZL, 0x34 ; Load r30 (ZL) with low byte of address
ldi ZH, 0x12 ; Load r31 (ZH) with high byte of address
ld r16, Z ; Load byte to r16
Die AVR-Familie hat 3 Registerpaare, die dafür verwendet werden können. Sie sind speziell in der Hardware entwickelt, um solche Operationen zu ermöglichen.
Beim Programmieren in einer höheren Sprache wie C übernimmt der Compiler diese Dinge.
Hinweis: Einige AVRs unterstützen sogar größere Speichergrößen als 64k. Diese Controller haben ein spezielles Funktionsregister, in das vor dem Zugriff zusätzliche Bits der Adresse geschrieben werden. Die Adresse besteht also aus folgenden Bits (MSB bis LSB):
Sonderfunktionsregister (normalerweise wird nur 1 Bit verwendet), ZH (8 Bit), ZL (8 Bit). Dies ergibt eine Gesamtadresse von 17 Bit und ermöglicht den Zugriff auf 128 kB RAM.
Es stimmt oft, dass es eine gewisse Beziehung zwischen der adressierbaren Speichergröße und der internen Registergröße gibt, obwohl die Beziehung aus verschiedenen Gründen variiert. 256 Byte Adressraum wurden selbst in den sehr frühen Tagen der Mikroprozessoren als zu klein angesehen, so dass die meisten Acht-Bit-Prozessoren 16-Bit-Adressen (zwei Byte) erzeugten, die 64 Kilobyte adressierten. Mit der Bankumschaltung (im Wesentlichen unter Verwendung bestimmter E / A-Leitungen, um noch mehr Adressleitungen zu erzeugen) war es jedoch möglich, viel mehr zu haben.
In den ersten 16- und 32-Bit-Prozessoren gab es nicht immer genügend Pins auf dem Gerät, um den gesamten Platz zu erreichen, den ihre internen Adressregister adressieren konnten. Beispielsweise gab es beim Motorola 68000 nur genügend Adressstifte (24), um 16 Megabyte RAM zu adressieren, obwohl die internen Adressregister 32 Bit breit waren.
Wikipedia erklärt es ganz gut:
Acht-Bit-CPUs verwenden einen 8-Bit-Datenbus und können daher in einem einzigen Maschinenbefehl auf 8 Datenbits zugreifen. Der Adressbus ist aufgrund praktischer und wirtschaftlicher Erwägungen typischerweise ein doppeltes Oktett breit (dh 16 Bit). Dies impliziert einen direkten Adressraum von nur 64 KB auf den meisten 8-Bit-Prozessoren.
Die 8-Bit-AVRs von Atmel verwenden tatsächlich eine 16-Bit-Datenadresse. Sie haben zahlreiche andere 16-Bit-Register und sogar einige 16-Bit-Timer. Da es sich nur um einen 8-Bit-Prozessor handelt, verwendet er normalerweise zwei Taktzyklen, um ein 16-Bit-Register zu laden.
Die Vorstellung, dass die "Bitbreite" eines Prozessors die maximale Menge an RAM festlegt, die der Prozessor adressieren kann, ist einer der am weitesten verbreiteten Mythen in der Computertechnik. Tatsächlich ist die Industriegeschichte nur mit CPUs übersät, für die diese Beziehung nicht galt.
HP 21MX, HP 1000: 16-Bit-CPU, Speicher bis 16 MB
PDP-11: 16-Bit-CPU, Speicher bis 4 MB
VAX-11/780: 32-Bit-CPU, Speicher bis 512 MB
usw. usw.
John u
die fleißige Biene
Elliot Alderson
Lundin
Oldtimer