Was bedeutet es für eine CPU, einen Stack zu unterstützen?
11
Wie kann eine CPU einen Stack nicht unterstützen? Muss keine Architektur, die Subroutinen verwendet (ich bin mir ziemlich sicher, dass dies alle Architekturen sind), die Rücksprungadresse auf den Stapel verschieben, damit sie dorthin zurückkehren kann, wo sie die Subroutine aufgerufen hat? Der Stapel bedeutet nur einen Speicherabschnitt mit einem Zeiger, der in eine bestimmte Richtung wächst und als Stapeldatenstruktur fungiert. Ich verstehe einfach nicht, wie eine Architektur einen Stapel nicht unterstützen kann.
Inwieweit wird der automatische Speicher (automatische Variablen gegenüber statischen Variablen) vom Compiler gegenüber der Hardwarearchitektur bestimmt?
Es gibt viele Low-Level-Mikrocontroller, die über Hardware-Stacks für die Verarbeitung / Rückgabe von Unterprogrammen und die Interrupt-Behandlung verfügen, die es jedoch schwierig, wenn nicht unmöglich machen, Daten (Variablen) dort zu speichern, und die Implementierung eines reinen Software-Datenstapels wäre schrecklich ineffizient. Der 8051 ist ein klassisches Beispiel, und Low-End-PICs (PIC12 / PIC16) sind ein anderes. Auf diesen Computern wird der Datenstapel durch Zuweisen statischer Speicherorte für automatische Variablen emuliert, wobei der Umfang der Wiederverwendung dieser Speicherorte von der Komplexität des Compilers abhängt.
Wenn die Stapelemulation auf diese Weise durchgeführt wird, bedeutet dies, dass die Rekursion - eine Funktion, die sich entweder direkt oder indirekt selbst aufruft - nicht funktioniert, da jede Instanz der Funktion dieselben statischen Speicherorte für ihre angeblich "privaten" Variablen wiederverwendet. Einige Compiler erlauben die eingeschränkte Verwendung der Rekursion (normalerweise mithilfe einer #pragmaArt von Rekursion implementiert ), wodurch ein echter Datenstapel erstellt wird, unabhängig davon, wie stark dies die Dinge verlangsamt.
Abgesehen davon gab es CPU-Architekturen, die überhaupt keinen Hardware-Stack hatten, auch nicht für die Handhabung von Subroutinen / Interrupts, einschließlich DEC PDP-8 und IBM System / 360. Auf diesen Maschinen wurden der PC (Rücksprungadresse) und das Statusregister (für Interrupts) in Registern oder Speicherstellen gespeichert, aber in jedem denkbaren Fall verfügte die Maschine auch über ausreichend flexible Adressmodi, die das Erstellen eines Stapels vereinfachten mit Software.
Einige frühere Computer haben eine Sprunganweisung in den Code geschrieben, um eine Rückgabe zu verursachen - ohne indirekte Sprünge -, wodurch wiedereintretende Funktionen unpraktisch werden (theoretisch könnte man über einen Sprung verzweigen, aber dies erhöht die Komplexität, in einigen Fällen insbesondere, wenn Datenadressen vollständig codiert sind in Anweisungen).
Paul A. Clayton
4
"Unterstützung eines Stapels" bedeutet
mit einem expliziten Stapelzeigerregister und
primitive Maschinencode-Anweisungen zum Manipulieren / Verwenden des Stapelzeigerregisters haben (wie reti, das den Programmzähler basierend auf dem Stapelzeiger ändert, um von einem Funktionsaufruf zurückzukehren).
Sie können dies ohne Hardwareunterstützung durch Emulation emulieren. Hierbei handelt es sich um vom Compiler generierten Code, der mithilfe von Variablen die gleichen Funktionen im RAM verwendet. Es ist selten / ungewöhnlich, dass Stack in keiner modernen Computerarchitektur direkt unterstützt wird.
Die Semantik von Variablen in Programmiersprachen hat fast nichts mit der Zielhardwarearchitektur zu tun, für jede Sprache, die höher ist als die gerade Assemblierung. Die Aufgabe des Compilers besteht darin, Maschinencode zu generieren, der dem semantischen Vertrag der Programmiersprache entspricht.
Die meisten RISC-ISAs (z. B. MIPS [außer MIPS16 und microMIPS], Alpha, SPARC, PA-RISC, Power, SuperH) verfügen nicht über ein explizites Stapelzeigerregister, das stattdessen im ABI definiert wird. ARM ist eine Ausnahme (teilweise, weil es den SP für mehrere Betriebsmodi beschattet), ebenso wie MIP16 und microMIPS (für die Codedichte).
Paul A. Clayton
2
Einige Architekturen (z. B. PIC) verfügen über einen Hardware-Stack mit eingeschränkten Funktionen (können nur für Rücksprungadressen verwendet werden, nicht für Variablen). Einige extrem kleine Architekturen verfügen nicht über eine Store-and-Inkrement- oder PUSH-Anweisung, daher ist es schwieriger, einen Stapel zu erstellen.
'Auto'-Variablen in C sollten immer zu etwas mit' Auto'-Initialisierungsverhalten und 'Statisch' mit statischem Verhalten kompiliert werden. Auf einigen Architekturen dürfen Sie keine Rekursion durchführen. In diesem Fall kann der Compiler alle Variablen statisch zuweisen.
"Unterstützung eines Stapels" bedeutet
Sie können dies ohne Hardwareunterstützung durch Emulation emulieren. Hierbei handelt es sich um vom Compiler generierten Code, der mithilfe von Variablen die gleichen Funktionen im RAM verwendet. Es ist selten / ungewöhnlich, dass Stack in keiner modernen Computerarchitektur direkt unterstützt wird.
Die Semantik von Variablen in Programmiersprachen hat fast nichts mit der Zielhardwarearchitektur zu tun, für jede Sprache, die höher ist als die gerade Assemblierung. Die Aufgabe des Compilers besteht darin, Maschinencode zu generieren, der dem semantischen Vertrag der Programmiersprache entspricht.
quelle
Einige Architekturen (z. B. PIC) verfügen über einen Hardware-Stack mit eingeschränkten Funktionen (können nur für Rücksprungadressen verwendet werden, nicht für Variablen). Einige extrem kleine Architekturen verfügen nicht über eine Store-and-Inkrement- oder PUSH-Anweisung, daher ist es schwieriger, einen Stapel zu erstellen.
'Auto'-Variablen in C sollten immer zu etwas mit' Auto'-Initialisierungsverhalten und 'Statisch' mit statischem Verhalten kompiliert werden. Auf einigen Architekturen dürfen Sie keine Rekursion durchführen. In diesem Fall kann der Compiler alle Variablen statisch zuweisen.
quelle