Frage

Ich bereite einige Schulungsunterlagen in C und ich mag, dass meine Beispiele die typischen Stapel Modelle passen.

In welche Richtung sich ein C-Stack wächst in Linux, Windows, Mac OS X (PPC und x86), Solaris und letzten Unixes?

War es hilfreich?

Lösung

Stack-Wachstum in der Regel hängt nicht vom Betriebssystem selbst, sondern auf dem Prozessor läuft es auf. Solaris zum Beispiel läuft auf x86 und SPARC. Mac OSX (wie Sie bereits erwähnt) läuft auf PPC und x86. Linux läuft auf allem aus meinem großen honkin System z bei der Arbeit zu einem kümmerlich wenig Armbanduhr .

Wenn die CPU jede Art von Wahl stellen, das ABI / Aufrufkonvention von dem O gibt an, welche Wahl Sie vornehmen müssen, wenn Sie Ihren Code wollen, dass jeder nennen anderen Code.

Die Prozessoren und deren Richtung sind:

  • x86:. Unten
  • SPARC: wählbar. Das Standard-ABI verwendet nach unten.
  • PPC: nach unten, ich glaube
  • .
  • System z:. In einer verknüpften Liste, ich mache keine Witze (aber immer noch nach unten, zumindest für zLinux)
  • ARM: wählbar, aber Thumb2 hat nur kompakte Codierungen für unten (LDMIA = Schritt nach, STMDB = Abnahme vor)
  • .
  • 6502:. Nach unten (aber nur 256 Byte)
  • RCA 1802A. Wie du, vorbehaltlich SCRT Implementierung möchten
  • PDP11. Unten
  • 8051:. Oben

Es werden in meinem Alter auf die letzten paar war das 1802 der Chip verwendet, um die frühen Shuttles zu steuern (Erfassen, wenn die Türen offen waren, vermute ich, auf der Grundlage der Verarbeitungsleistung hatte :-) und meinem zweiten Rechner, der < a href = "http://en.wikipedia.org/wiki/Comx-35" rel = "noreferrer"> COMX-35 (nach meinem ZX80 ).

PDP11 Details nachgelesen von hier , 8051 Details von hier .

Die SPARC-Architektur verwendet ein Schiebefenster Registermodell. Die architektonisch sichtbaren Details auch einen Ringpuffer von Register-Fenster, die intern gültig und im Cache gespeichert sind, mit Fallen wenn dieser über / Unterschreitungen. Siehe hier . Wie die sparcv8 Handbuch erklärt, Speichern und Wiederherstellen von Anweisungen wie Befehle ADD Plus Register-Fenster Rotation. würde einen nach oben wachsenden Stapel eine positive Konstante statt der üblichen negativen verwenden.

Die oben genannte SCRT Technik ist eine andere - die 1802 verwendet, um einige oder es sechzehn 16-Bit-Register für SCRT (Standard Aufruf und Rückkehr-Technik). Einer war der Programmzähler, Sie jedes Register als PC mit der SEP Rn Anweisung verwenden könnten. Einer war der Stapelzeiger und zwei gesetzt wurden immer auf die SCRT Codeadresse zu zeigen, ein für Anruf, ein für Rückkehr. Nein Register wurden in besonderer Weise behandelt. Denken Sie daran, diese Details aus dem Gedächtnis sind, können sie nicht ganz korrekt sein.

Zum Beispiel, wenn R3 der PC war, R4 war die SCRT Aufrufadresse, R5 die SCRT Absenderadresse war und R2 war der „Stapel“ (Anführungszeichen, wie es in Software implementiert ist), SEP R4 würde eingestellt R4 der PC zu sein und starten Sie den SCRT Anruf Code ausgeführt wird.

Es wäre dann Speicher R3 auf dem R2 „Stack“ (ich glaube, R6 für temporäre Speicherung verwendet wurde), es nach oben oder unten eingestellt wird, die beiden folgenden Bytes R3 packen, laden sie in R3, dann tut SEP R3 und an der neuen Adresse ausgeführt werden.

zurückzukehren, wäre es SEP R5, die die alte Adresse aus dem R2 Stapel ziehen würde, um zwei bis sie (die Adresse Bytes des Anrufs überspringen), laden Sie es in R3 und SEP R3 starten Sie den vorherigen Code ausgeführt wird.

Sehr hart Kopf herum wickelt zunächst nach dem all 6502/6809 / z80 Stack-basierten Code aber immer noch elegant in einer Knall-your-Kopf-gegen-die-Wand Art und Weise. Auch einer der großen Verkaufsfunktionen des Chips wareine vollständige Suite von 16 16-Bit-Registern, trotz der Tatsache, Sie sofort 7 von denen verloren (5 für SCRT, zwei für DMA und Interrupts aus dem Gedächtnis). Ahh, der Triumph der Vermarktung über die Realität: -)

System z ist eigentlich ziemlich ähnlich, mit seinem R14 und R15 für Call / Return registriert.

Andere Tipps

In C ++ (anpassbar an C) stack.cc :

static int
find_stack_direction ()
{
    static char *addr = 0;
    auto char dummy;
    if (addr == 0)
    {
        addr = &dummy;
        return find_stack_direction ();
    }
    else
    {
        return ((&dummy > addr) ? 1 : -1);
    }
}

Der Vorteil nach unten wachsen ist in älteren Systemen der Stapel typischerweise am oberen Speicher war. Programme in der Regel gefüllt Speicher von unten beginnend damit diese Art von Speicher-Management minimiert die Notwendigkeit, den Boden des Stapels irgendwo sinnvoll zu messen und zu platzieren.

Stapel wächst nach unten auf x86 (durch die Architektur definiert, Pop-Schritte Zeiger stapeln, drücken Dekremente).

In MIPS gibt es keine push / pop Anweisung. Alle Schübe / Pops sind ausdrücklich von der Lade / Speicher relativ zu dem Stapelzeiger durchgeführt und dann manuell den $sp Zeiger einzustellen. Da jedoch alle Register (außer $0) für allgemeine Zwecke sind in der Theorie jeder Register kann ein Stapelzeiger sein, und der Stapel kann in jede Richtung wachsen der Programmierer will. MIPS ABIs wachsen typischerweise nach unten.

Intel 8051 der Stapel wächst, wahrscheinlich, weil der Speicherplatz so klein ist (128 Bytes in der Originalversion), dass es kein Haufen ist und Sie brauchen nicht den Stapel oben zu setzen, so dass sie von getrennt würde der Haufen von unten wächst.

Sie wächst, weil das das Programm zugewiesenen Speicher die „permanente Daten“ heißt Code für das Programm selbst am Boden hat, dann den Haufen in der Mitte. Sie müssen einen anderen festen Punkt, von dem den Stapel zu verweisen, so dass lässt Sie die Spitze. Dies bedeutet, dass der Stapel wächst nach unten, bis es möglicherweise neben Objekte auf dem Heap ist.

Bei den meisten Systemen Stapel wachsen nach unten, und meinem Artikel unter https://gist.github.com/ CPQ / 8598782 erklärt, warum es nach unten wächst. Der Grund dafür ist, dass das optimale Layout von zwei wachsenden Speicherbereichen (Heap und Stack).

Nur eine kleine Ergänzung zu den anderen Antworten, die soweit ich diesen Punkt nicht berührt haben sehen können:

Mit dem Stapel wachsen läßt nach unten alle Adressen innerhalb des Stapels haben eine positive auf den Stapelzeiger versetzt. Es gibt keine Notwendigkeit für negative Offsets, da sie sich nur auf nicht verwendeten Stapelspeicher verweisen würden. Dies vereinfacht die Stapelstellen zugreift, wenn der Prozessor unterstützt Stackpointer-relative Adressierung.

Viele Prozessoren haben Anweisungen, mit denen Zugriffe mit einem positiv nur relativ zu einem Register versetzt. Die schließen viele moderne Architekturen, sowie einige alte. Zum Beispiel stellt das ARM Thumb ABI für Stackpointer-Relativ Zugriffe mit einer positiven innerhalb eines einzelnen 16-Bit-Befehlswortes codierte Offset.

Wenn der Stapel nach oben wuchs, alle nützlichen Offsets relativ zum Stackpointer wären negativ, was weniger intuitiv ist und weniger bequem. Es ist auch im Widerspruch zu anderen Anwendungen von Register-relativer Adressierung, zum Beispiel für die Felder einer Struktur zugreifen.

Dieses Makro zur Laufzeit ohne UB erkennen soll:

#define stk_grows_up_eh() stk_grows_up__(&(char){0})
_Bool stk_grows_up__(char *ParentsLocal);

__attribute((__noinline__))
_Bool stk_grows_up__(char *ParentsLocal) { 
    return (uintptr_t)ParentsLocal < (uintptr_t)&ParentsLocal;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top