Wie kann ein 8-Bit-Prozessor mehr als 256 Byte RAM unterstützen?

Wenn ein 32 -Bit-Prozessor etwa 4 GiB RAM verarbeiten kann (d. h 2 32 = 4 294 967 296 ) Bytes, warum hat mein Arduino Mega 2560 8 KiB SRAM, wenn er als 8 -Bit-Prozessor nur 256 Bytes verarbeiten kann ( 2 8 )? Oder lese ich die folgende Seite falsch?

http://www.atmel.com/devices/atmega2560.aspx?tab=parameters

Sicherlich ist jede Turing-Komplettmaschine in der Lage, mit genügend Zeit fast jede RAM-Größe zu adressieren.
Tatsächlich kann die Anzahl der Bits in einem Prozessornamen nur für eine Vorausschätzung der internen Datenbreite verwendet werden. Der 8088 ist aufgrund seiner 16-Bit-Register ein 16-Bit-Prozessor, hat aber einen 8-Bit-Datenbus und einen 20-Bit-Adressbus. Der 68000 ist ein 32-Bit-Prozessor, der wegen seiner 32-Bit-Register meist 16/32-Bit genannt wird, aber einen 16-Bit-Datenbus und einen 24-Bit-Adressbus hat. Kleine ARM-Implementierungen sind 32-Bit-Prozessoren (32-Bit-Register und Datenbus), aber selbst wenn sie 32 Bit für Adressen verwenden, können sie nicht insgesamt 4 GB adressieren.
Ich habe die korrekten SI-Präfixe für diese Einheiten hinzugefügt. 2 30 ist Gibi (Gi) und 2 10 ist kibi (Ki).
Erwähnenswert ist, dass viele 8-Bitter (insbesondere Motorola-Derivate) eine sogenannte Zero-Page unterstützen, bei der es sich um eine Befehlssatzunterstützung handelt, um die ersten 256 adressierbaren Bytes in der Speicherabbildung etwas schneller zu verarbeiten. Aus diesem Leistungsgrund würden also die zeitkritischsten Hardwareregister usw. in die ersten 256 Bytes abgebildet. Aus diesem Grund finden Sie auf vielen Architekturen Hardwareregister, die von der Adresse Null aus zugeordnet sind.
Etwas als 8-Bit, 16-Bit, 32-Bit usw. zu bezeichnen, ist, sagen wir, ein Marketingbegriff, Ingenieure verwenden ihn, aber verstehen, dass dies nicht bedeutet, dass alles in diesem Prozessor so breit ist. Einige Leute verwenden die Größe des Befehls, sehr oft wird die Größe der Allzweckregister verwendet, manchmal der Bus. Sie haben den Programmzähler, der nicht immer zugänglich oder in Anweisungen verwendbar ist, sodass er beliebig breit sein kann. dann gibt es wie bei vielen Prozessoren vom AVR-Typ ein Mehrregister- oder Paging-Schema oder beides, um eine breitere Lade-/Speicheradresse für Datentransaktionen zu erhalten.

Antworten (9)

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).

Tatsächlich haben die meisten 8-Bit-Mikrocontroller, denen ich begegnet bin, keine 16-Bit-Adresse
@Brian Drummond Habe ich Recht: Der Controller schreibt zuerst die unteren 8 Bit, dann die oberen 8 Bit und speichert dann den Adressbus. So wird auf den 16-Bit-Adressbus zugegriffen!
Oder obere 8 Bit und dann untere 8 Bit, aber im Grunde ja, das ist die Idee.
Einige Mikrocontroller wie der PIC18 verfügen über ein Segmentregister, mit dem sie ihren Adressraum über das hinaus erweitern können, was im 16-Bit-Befehlssatz codiert werden kann. Zusätzlich kann die Verwendung von IO-Pins als Chip-Selects auf externen RAM-Bänken verwendet werden, um den Speicher zu erweitern.

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

      • AVR hat R26..R31, die in 16-Bit- und Datenadressierungsregister gepaart werden können 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 1YZRAMPXRAMPYRAMPZSPHSPL
      • Intel 8080 und Zilog Z80 sind 8-Bit-CPUs, aber sie haben Registerpaare wie H& L, B& C, D& E, die zusammen als 16-Bit-Adressregister verwendet werden können
    • Verwenden eines einzigen großen Spezialregisters, das größer als die natürliche Größe zum Adressieren ist

      • Intel 8051 ist ein 8-Bit-Mikrocontroller, dh er hat eine 8-Bit-Datenadresse. Es verwendet jedoch eine 16-Bit-Befehlsadresse und verfügt über 2 16-Bit-Register: PC und DPTR für die Adressierung im Befehlsraum.
      • AVR hat ein 16- oder 22-Bit-PC-Register
    • 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.

      • Ein Sonderfall davon ist der segmentierte Speicher , der von 16-Bit x86 verwendet wird . Bei dieser Technik wird der Speicher in mehrere Segmente der Größe 64 KB (2 16 Byte) aufgeteilt. Der normale Zugriff erfolgt standardmäßig innerhalb eines einzelnen Segments, sodass sie 16-Bit-Adressen für nahe Daten verwenden können . Daten, die weiter auseinander liegen , müssen spezifisch über den Segmentwert adressiert werden, daher müssen 2 Register für die Fernadressierung verwendet werden.
      • Ein weiteres Beispiel ist der PIC-Mikrocontroller , dessen Baseline- und Midrange-Serie eine 13- oder 14-Bit-Adresse haben kann. Bei der Verwendung von callor gotowerden 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).
      • Ein weiteres Beispiel ist die MIPS -Architektur, die auch die niedrigere 26-Bit-Sofortadresse mit den hohen 6 Bits kombiniert, PCwä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.

    • Intel 8051 verwendet Memory Banking für die Register. Es hat 32 Register, aber nur 8 davon sind gleichzeitig sichtbar.
    • x86 PAE und ARM LPAE , wobei ein größerer physischer Adressraum einem kleinen virtuellen Adressraum zugeordnet ist
    • Eine weitere Anwendung hierfür sind die Address Windowing Extensions unter Windows, die von 32-Bit-x86-Apps im PAE-Modus verwendet werden können, um auf mehr als 2/3 GB Speicher zuzugreifen. Es ist nicht genau wie eine Speicherbank auf Mikrocontrollern, kann aber als solche angesehen werden, da der große Adressbereich an kleine Fenster / Banken denken kann, die klein genug sind, um in den Adressraum der App zu passen. Wenn die App Daten in einem Fenster verwenden muss, ordnet sie dieses Fenster ihrem aktuellen Adressraum zu.
    • DOS verfügt aufgrund seines begrenzten Bereichs an adressierbarem Speicher auch über einige Arten von Bankumschaltungen wie Erweiterungsspeicher oder Erweiterungsspeicher .
  • 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:

  1. Modelle mit >256 Byte Datenadressraum (≥256 Byte RAM) haben einen 16-Bit-Stapelzeiger, wobei sich die obere Hälfte im SPH-Register befindet.
  2. 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.)
  3. 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.
  4. (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.)
  5. (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.

Sie haben Recht - PAE erlaubte die Verwendung von mehr RAM, aber da es auf Desktop-Windows nicht verfügbar war, haben es nicht viele Leute jemals benutzt.
PAE ist der Name des Features. Außerdem können 64-Bit-Prozessoren keine 64 Exabyte adressieren, da 2 64 würde vorschlagen.
x86-CPUs können nicht mehr als 4 GB ohne erhebliche Komplikationen im Betriebssystem adressieren, die nicht auf andere Architekturen portiert werden.
@Kaz ARM 32-Bit verfügt über eine ähnliche Funktion namens LPAE, mit der das Betriebssystem mehr als 32 Adressbits adressieren kann

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:

  1. Beenden Sie das Schreiben des Registers von der vorherigen Anweisung (falls vorhanden) und laden Sie den Opcode ($BD).
  2. Holen Sie das erste Operandenbyte nach dem Opcode ($34) während der Decodierung des Befehls
  3. Holen Sie das zweite Operandenbyte ($12), während Sie das zuvor geholte Byte zum X-Register hinzufügen
  4. Speicher an der Adresse lesen, die durch Verketten des zweiten Operandenbytes mit dem ALU-Ergebnis [dh $1224] gebildet wird. Führe das zweite Operandenbyte in die ALU ein, um Null oder Eins zu addieren, je nachdem, ob die vorherige Addition einen Übertrag erzeugt hat
  5. Speicher an der Adresse lesen, die durch Ersetzen der oberen Hälfte durch das ALU-Ergebnis gebildet wurde [$1334]

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 erinnere mich, einige Anzeigen für Computer mit 8-Bit-Prozessoren und 1 Megabyte Speicher gesehen zu haben. Dazu wurden zwei 8-Bit-Register auf der CPU plus ein 8-Bit-Register nicht auf der CPU verwendet, um die gesamte Adresse zu bilden.
@ user6030: Es gibt viele Möglichkeiten, solche Dinge zu erreichen. Typischerweise sind Teile des Adressraums "fest" und andere sind bankwählbar. Einige Geräte funktionieren gut für Programmierer; viele andere nicht so sehr.

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.