Mikroprozessoren/Mikrocontroller - Haben Register Adressen?

Mein Professor für eingebettete Systeme bezeichnet die Speicherorte von Registern immer wieder als ihre jeweiligen "Adressen". Das verwirrt mich; Ich hatte immer den Eindruck, dass die CPU-Register in jedem Mikroprozessor keine Adressen haben, da sie sich nicht im Hauptspeicher befinden (sie befinden sich im Mikroprozessor selbst). Ich bin auch verwirrt darüber, worauf wir uns beziehen, wenn wir den "Speicherort des Registers" sagen - auch hier befindet es sich nicht im Hauptspeicher.

Warum beziehen wir uns vor diesem Hintergrund mit "Adressen" auf die Speicherorte der CPU-Register? Haben alle/einige Register Adressen?

Ich habe darüber nachgedacht und festgestellt, dass sie möglicherweise mit bestimmten Hauptspeicherorten "verbunden" sind und den Zugriff auf die in den Registern gespeicherten Werte ermöglichen. Um diesen Gedanken zu erweitern, ist das Memory Mapping?

Ich sollte auch hinzufügen, dass wir speziell mit dem LPC1768-Mikrocontroller von NXP arbeiten, der den ARM Cortex-M3-Mikroprozessor verwendet.

Antworten (9)

Es hängt vom jeweiligen Prozessor ab, ob "Register" im selben Adressraum wie reguläre Datenspeicher oder getrennt sind. In beiden Fällen, wenn es mehrere davon gibt, braucht jeder noch eine Adresse.

Nehmen wir an, der Prozessor hat 16 Register, die eng mit der CPU gekoppelt und getrennt vom Datenspeicher implementiert sind. Diese Register müssen noch irgendwie identifiziert werden. In diesem Fall wäre eine 4-Bit-Adresse erforderlich, um einzelne Register zu unterscheiden. In einer RISC-Architektur würde die 4-Bit-Adresse eines oder mehrerer Register, an denen ein Befehl arbeitet, in den Befehlscode aufgenommen. Beispielsweise könnte der ADD-Befehl den Wert eines Quellregisters in ein Zielregister addieren. Dieser Befehl würde 4 Bits zum Identifizieren des Quellregisters und weitere 4 Bits zum Identifizieren des Zielregisters enthalten. Die Dokumentation kann sich auf diese Register mit "Nummer" 0 bis 15 beziehen, aber das ist wirklich die Adresse, an der sich die Register in einem speziellen kleinen Speicher der CPU befinden.

Zusätzlich zu dem oben Gesagten könnten diese Register, selbst wenn ein Prozessor über spezielle dedizierte Register verfügt, in den Allzweck-Datenadressraum abgebildet werden. Verweise auf diese Adressen werden abgefangen und auf die internen Register verwiesen.

Es gibt viele Schemata da draußen, aber wenn Sie mehr als ein Register haben, müssen diese Register irgendwie voneinander unterschieden werden, und innerhalb der Hardware, die mit einer "Adresse" versehen sein wird, ob es in der Dokumentation so heißt oder nicht.

Ah, da ist also das Problem. Ich habe immer ausschließlich Hauptspeicher/RAM mit Speicheradressen verknüpft ; Ich wäre nie auf die Idee gekommen, Speicheradressen mit irgendetwas anderem zu verknüpfen. Danke, dass du das geklärt hast!
Außerdem bin ich jetzt neugierig; Welche Komponente ist für das Auffinden und den Zugriff auf diese Registeradressen verantwortlich?
Wenn es sich um dedizierte Register handelt, ist nur Hardware vorhanden, um ein Register auszuwählen. Da es so wenige Register gibt, kann mehr Hardware zum Decodieren und Bearbeiten der Adressbits verwendet werden, als Sie in einem normal großen Speicher verwenden könnten. Dies kann die Dekodierung beschleunigen, mehrere Ports ermöglichen usw. Normalerweise kann jedes einzelne Register einen der beiden ALU-Eingänge steuern und den ALU-Ausgang speichern. In einigen Architekturen (dsPIC ist ein Beispiel) können drei separate Register diese Dinge separat in derselben Anweisung erledigen.

Die Quelle der Verwirrung ist, dass es (im Allgemeinen) zwei Arten von Dingen gibt, die als "Register" bezeichnet werden können.

Das erste ist wahrscheinlich das, womit Sie vertraut sind: In ARM ist es registers R0, R1, R2, ... R12, SP, LR, PCund in x86 ist es eax, ebx, ecx, edx, ebpund so weiter. Diese können auch als „ Kernregister “ oder „ Prozessorregister “ bezeichnet werden. Sie haben keine Adressen im Systemspeicherbereich und können nur durch spezielle Befehle aufgerufen werden.

Das andere sind die Register, die verschiedene Hardwareblöcke (Peripheriegeräte) in der CPU selbst oder außerhalb davon steuern können. Auf LPC1768 und vielen anderen eingebetteten Prozessoren sind sie normalerweise speicherabgebildet und haben deshalb Adressen. Beispielsweise befindet sich der UART0-Block an der Adresse 0x4000C000, und dort müssen Sie lesen oder schreiben, um mit ihm zu kommunizieren. Zur Unterscheidung von den Kernregistern können sie „ Peripherieregister “ oder „ Hardwareregister “ genannt werden.

Auf einigen Low-End-8-Bit-Mikrocontrollern wie 8051 oder PIC gibt es möglicherweise überhaupt keine Kernregister außer vielleicht einem Akkumulator, und alle anderen Register werden in verschiedene Speicherbereiche wie "internes RAM" (für vorübergehende Speicherung / Berechnung) oder "Special Function Registers" (SFR) Speicher für die Steuer- und Peripherieregister. Darin haben "Register" fast immer eine Adresse.

Größere ARMs haben auch Coprozessorregister , die verwendet werden können, um verschiedene Kernfunktionen (z. B. MMU oder Cache) mit Anweisungen wie MRCoder zu steuern MCR. Diese Register ähneln den Kernregistern darin, dass sie keine Speicheradresse, sondern nur eine Nummer haben.

Außerdem können Sie auf x86 E/A - Ports haben , auf die über Anweisungen inund zugegriffen werden outkann, die zur Steuerung einiger Hardwareblöcke verwendet werden können. Diese ähneln in ihrer Funktion den peripheren Registern, werden aber normalerweise nicht als solche bezeichnet.

Sind die Prozessorregister in irgendeiner Weise zugänglich?
@ ProSteve037: natürlich, sonst hätte es keinen Sinn, sie zu haben :) Normalerweise arbeiten die meisten Anweisungen tatsächlich mit Prozessorregistern. ZB auf ARM: MOV, LDR, STR, ADD, SUB und so weiter.
@ ProSteve037 In gewissem Sinne haben Prozessorregister eine Art Adresse, aber sie wird im register fieldOpcode (dem Maschinencode-Befehlswort) verwendet und kann nicht mit Speicheradressen verwechselt werden (ihre Positionen im Opcode-Format sind unterschiedlich , und die Felder sind unterschiedlich groß).

Sie haben Recht, dass sich einige Register nicht im Hauptspeicher befinden, sondern im Mikroprozessor selbst, und dass diese Register an bestimmten Stellen im Speicher abgebildet sind.

Der LPC1768-Mikrocontroller hat nur 64 KB RAM (was Sie meiner Meinung nach mit Hauptspeicher meinen), jedoch einen 32-Bit-Adressbus und 4 GB Gesamtadressraum. Der Rest dieses Adressraums enthält den Flash-Speicher, in dem Ihr Programm gespeichert ist, und die Register für alle Peripheriegeräte (z. B. die Zustände der Ausgangspins oder den ADC).

Wenn Sie versuchen, auf einen speicherabgebildeten Ort zuzugreifen, erkennt die Logik im Mikrocontroller normalerweise, wo sich die Speicheradresse physisch befindet, und steuert Steuerleitungen, damit die Daten dorthin gelangen, wo sie beabsichtigt waren, unabhängig davon, ob sie sich im RAM befinden, a GPIO-Port oder ein peripheres Steuerregister.

Dies vereinfacht das Schreiben von Software, da Sie sich nicht allzu viele Gedanken darüber machen müssen, wo sich die Register physisch befinden, und macht das Kompilieren höherer Sprachen (wie C) viel einfacher.

Im speziellen Fall des LPC1768 sehen wir im Datenblatt ( http://www.nxp.com/documents/data_sheet/LPC1769_68_67_66_65_64_63.pdf ) die Adresskarte auf Seite 20 (Abbildung 4), die zeigt, wo sich alle befinden Peripheriegeräte werden im Speicher abgebildet.

Natürlich enthält der Prozessor auch eine Handvoll interner Register, die nicht speicherzugeordnet sind. Auf diese kann viel schneller zugegriffen werden als auf alles im Adressraum, da die Speicherverwaltungslogik im Vergleich zum Kern langsam ist und als temporärer Speicher verwendet wird während Operationen. Ein Teil der Aufgabe eines Compilers besteht darin, Daten in Registern zu speichern und sie für Sie aus dem/in den Speicher zu verschieben.

Wie andere gesagt haben, hängt es von der Mikrocontroller-Familie ab. Und es hängt davon ab, was Sie mit registrieren meinen.

Der msp430 zum Beispiel hat zwei Sätze von "Registern". Die erste ist die RISC-Registerdatei mit 16 16-Bit-Registern. Dazu gehören die Register Programmzähler, Stapelzeiger, Status und Konstantengenerator sowie 12 allgemeine Register. Dies sind Register im traditionellen Architekturgebrauch des Wortes.

Datei registrieren

Der zweite Registersatz ist alles andere. Ports, Peripheriegeräte, Interrupts usw. Diese sind Teil der einzelnen Speicherdatei und teilen sich den Speicherplatz mit dem allgemein verwendeten RAM und Flash (Code Space).

Speicherkarte

Beispielsweise hat der msp430g2231 ein Ausgangsregister für Port 1 an der Speicheradresse 0x21.

Besonderheiten

Sie können auf das Register mit dem Registernamen p1out zugreifen, aber das ist nur ein Zeiger auf die 8-Bit-Speicheradresse 0x21. Am wichtigsten ist, dass der Compiler es so sieht. Die Header-Datei, in diesem Fall msp430g2231.h, definiert „p1out“ als 0x0021. Abgesehen von der RISC-Registerdatei bedeutet die übliche Verwendung von Register nur eine Speicheradresse für eine x-spezifische Option. Was Sie als Register p1out sehen, ist genau so, wie eine höhere Sprache Ihnen das Programmieren erleichtert, anstatt sich Speicherkarten zu merken.

Wenn Sie einen Zeiger auf die Speicheradresse 0x27f verwenden, würden Sie stattdessen aus dem RAM lesen. Zeiger auf Speicheradresse 0xffdf, und Sie würden stattdessen Ihren kompilierten Code lesen. Alles, was ein Register ist, ist eine Speicheradresse für eine spezielle Funktion.

Als Oberbegriff bedeutet „Register“ nur einen Ort, an dem Sie Informationen speichern („registrieren“) können, nicht mehr.

Die meisten Architekturen reservieren den Begriff Register für Orte innerhalb der CPU, die durch Bits in einem Befehl identifiziert werden und auf die oft viel schneller zugegriffen werden kann als auf allgemeinen Massenspeicher ("RAM"). (Und oft kann in einem Ausführungszyklus auf 2 oder 3 Register parallel zugegriffen werden.)

Die PIC-Dokumentation von Microchip bezieht sich jedoch beispielsweise auf alle adressierbaren Stellen als Register, sogar einschließlich RAM. Wenn Ihr Professor diese Verwendung des Begriffs kopiert, sollte er Sie meiner Meinung nach darüber informieren, dass dies nicht die Art und Weise ist, wie der Begriff "Registrieren" heutzutage üblicherweise verwendet wird. (Wie ich es hoffentlich in meinen PIC-Assembler-Kursen getan habe.)

Nicht nur Mikrochip - sehen Sie sich den 8051 für ein viel früheres Beispiel an, und selbst das kann durchaus Vorgänger haben.
@ChrisStratton: Ich bin mir ziemlich sicher, dass der PIC von General Instruments (auf dem der 16C54 von Microchip basierte) älter als der 8051 ist, und er könnte sogar älter als sein Vorgänger, der 8048, sein.
Ja, es sieht so aus, als ob es dem 8048 um etwa ein Jahr vorausgeht.

Register haben Adressen, obwohl sie sich im Allgemeinen nicht im Speicher befinden.

Denken Sie eine Minute darüber nach: Eine Adresse bezeichnet einen Ort in einem Raum, wo der Speicher nur eine Instanz eines Raums ist. E/A hat oft einen eigenen Adressraum; In einigen Mikrocontroller-Architekturen sind Codespeicher und Datenspeicher getrennte Räume.

Und so können Register auch ihren eigenen Platz haben: Manchmal haben FP- und Integer-Register (und auf dem 68000, glaube ich, Adressregister) jeweils ihren eigenen separaten Platz.

Eine Frage ist: Wie können wir feststellen, ob sich Adresse 1 auf Byte 1 im Speicher, I/O-Port 1 oder Register 1 bezieht? Normalerweise aus dem Kontext: in einer IN- oder OUT-Anweisung offensichtlich ein Port. Bei einem Register-zu-Register-Befehl handelt es sich um eine Registeradresse. In einem Ladebefehl gibt es eine (große) Speicheradresse und eine (kleine) Registeradresse und so weiter.

In einem ARM-Kern ist eine Speicheradresse normalerweise eine 32-Bit-Zahl; eine Registeradresse ist eine 5-Bit-Zahl.

Viele Prozessoren haben einige Register, auf die "nach Nummer" zugegriffen wird, aber auch einige Register, auf die nur unter Verwendung spezieller Anweisungen zugegriffen werden kann. Ich weiß nicht, wie man das "S"-Register des 6502 zum Beispiel sinnvoll als eine Adresse beschreiben könnte. Abgesehen von Push/Pop/Call/Return sind die einzigen Befehle, die darauf zugreifen, TSX/TXS (Transfer S to X oder X to S). Bit 4 des Opcodes wählt zwischen TSX und TAX oder zwischen TXS und TXA aus, aber es macht keinen Sinn, die Opcodes als "Transfer X to register #b" zu betrachten, da sich keine anderen Anweisungen auf A beziehen, ist Reg #0 und S wie Nummer 1.

Wenn man eine Adresse als eine Menge von kBits definiert, die verwendet werden können, um ein Element aus einer Menge von bis zu 2^kElementen auszuwählen, dann ist es üblich, dass viele Register in vielen Prozessoren und Controllern Adressen haben, aber auch Controller einige haben Register, die von Schaltkreisen abgetastet werden, die bestimmte Bedingungen erkennen, und die nicht über irgendeine Art von Adresse identifizierbar sind. Es ist jedoch wichtig zu beachten, dass in vielen Fällen die Adressleitungen, die CPU-Register steuern, keine Beziehung zu den Adressleitungen haben, die mit größeren Speichersystemen verbunden sind. Als solche existieren Register-"Adressen" oft in einem völlig getrennten "Universum" von Speicheradressen.

Bei den meisten Prozessoren werden Register-"Adressen" immer entweder intern von der Prozessorlogik außerhalb der Kontrolle des Programmierers generiert oder von bestimmten Bits in jedem Befehl abgerufen. Der einzige Weg, wie ein Änderungscode per Software beeinflussen könnte, welches Register von einem bestimmten Befehl abgerufen werden sollte, wäre, die entsprechenden Bits innerhalb dieses Befehls zu patchen. Auf dem PIC von General Instruments, dessen Design in Form des Microchip PIC weiterlebt, würde Hardware den Inhalt eines anderen Registers an Adresse 3 ersetzen, wenn ein Opcode nur Nullen für eine Adresse spezifiziert. Dies ermöglicht dem Code, Berechnungen zur Auswahl zu verwenden eine Adresse.

Das vielleicht Wichtigste, was man über Adressen wissen muss, ist, dass es möglich ist, dass ein System unterschiedliche Adressräume hat, die tatsächlich in verschiedenen Universen existieren. Beim 8051 zum Beispiel gibt es, je nach Zählweise, mindestens vier verschiedene Adressräume, möglicherweise sogar sechs; vier von ihnen sind völlig unabhängig (die Anweisungen:

mov a,80h  ; Direct address space
mov a,@r0  ; Assume R0 = 80h
movc a,@a+dptr ; Assume A = 0 and DPTR = 80h
movx a,@dptr ; Assume DPTR = 80h

Alle rufen Daten von "Adresse 80h" ab, aber sie lesen vier unabhängige Dinge: eine Adresse im E / A-Bereich (das Datenregister von Port 0, glaube ich), das interne Datenregister 80h, den Codespeicher bei Adresse 0x0080 und den externen Datenspeicher bei Adresse 0x0080 . In vielen Systemen hätten diese Dinge tatsächlich keinerlei Beziehung zueinander. Die Tatsache, dass ein Register auf eine bestimmte Adresse in einem Universum reagiert, sagt wenig oder gar nichts darüber aus, ob es auf diese oder irgendeine andere Adresse in einem anderen Universum reagiert.

RISC bedeutet "Computer mit reduziertem Befehlssatz". Sie reduzieren die Größe des Befehlssatzes teilweise, indem Sie nur eine Art von Datenspeicherort haben, der Register, RAM oder I/O umfasst.

Damals, als die Leute diese Ideen ernst nahmen, waren die beiden erwarteten Vorteile von RISC-Designs, dass Sie den Prozessor viel schneller machen könnten, wenn Sie es viel einfacher machten, und dass Sie Ihren Programmcode optimieren könnten, wenn Sie jede Speicheradresse für alles verwenden könnten. Anstatt alles zum Laden und Entladen zu zwingen, gehen Sie durch das ALU-Register für Arithmetik, das Speicheradressenregister für die Speicheradressierung usw.

Zwei Überbleibsel dieser Denkweise sind: (1) Wir haben Prozessoren, die so tun, als seien alle Register gleich, indem sie Register in den Speicherraum abbilden, und (2) wir haben Professoren, die so tun, als seien alle Register gleich, indem sie Speicherorte der Register aufrufen.

Sei tolerant. Es war ein wichtiges Forschungsgebiet für Doktoranden, das einen signifikanten und nachhaltigen Einfluss auf die Art und Weise hatte, wie einige Prozessoren entworfen wurden.

Nein. RISC bedeutet in der Regel keinen Verlust der Unterscheidung zwischen Registerdatei und Hauptspeicher, da dies die Befehlsdecodierung erschweren würde, was das Gegenteil von RISC-Zielen ist. Bei RISC geht es klassischerweise um einfache Anweisungen, die schnell das tun, was sie tun, und es dem Programmierer/Compiler überlassen, sie aneinander zu reihen. Daher haben Register- und Speicheradressversionen von Anweisungen in einer klassischen RISC-Architektur unterschiedliche Codierungen. Und der Speicherzugriff erfolgt normalerweise auf eine Adresse, die von einem Register mit einer begrenzten unmittelbaren Verschiebung bereitgestellt wird, da nur so viele Bits im Befehlswort verfügbar sind.
Bis auf den ersten Satz hast du das richtig verstanden. Der Verlust der Unterscheidung zwischen Registerdatei und Hauptspeicher ist eine der Möglichkeiten, wie klassisches RISC die Befehlsdecodierung vereinfacht, was eines der Ziele von RISC ist. In der Praxis greifen praktische Erwägungen ein. Siehe zum Beispiel The Ultimate RISC
Ein RISC-Befehlswort codiert ganz explizit eine Registernummer oder eine Speicherreferenz, was eine Unterscheidungswahrung im Vergleich zu der hier betrachteten Situation darstellt, in der ein Register genauso wie eine Speicheradresse codiert ist.
Bitte lesen Sie zuerst die Referenz. Vor dem Posten.
Der Verweis bezieht sich auf eine seltsame akademische Architektur, nicht auf klassische Risikodesigns, wie sie tatsächlich gebaut wurden.
Du hast es bemerkt! Gehen Sie jetzt zurück und lesen Sie den ursprünglichen Beitrag und meine Antwort. Beachten Sie das Wort "Professor" in beiden Beiträgen. Sehen? Frage Antwort. Antwort, Frage. Enge Beziehung. Ich habe es mir nicht ausgesucht, über ein anderes Thema zu schreiben.

Wenn ich mich recht erinnere, könnte der 8051 über Speicheradressen auf die Register zugreifen, aber dies ist nicht der allgemeine Fall für alle Prozessoren. Die ARM-Prozessoren haben dazu keine Möglichkeit, auf die Mehrzweckregister r0-r15 kann auf dem Speicherbus nicht zugegriffen werden.