Hello, Guest the thread was viewed2.9k times and contains 40 replies

last post from detlef at the

Wo liegt eigentlich der Stapelzeiger?

  • Ist ja witzig, dass es nicht "direkt" geht. Drängt sich die Frage auf, warum das nicht geht :)

    Ja, ist im Prinzip eine Design-Entscheidung bei einer CPU. Dass ein Stackregister uniform wie andere Register behandelt werden, kenne ich bei 8-Bit-CPUs (die ich zur 2. Generation zählen würde) erst mit dem Motorola 6809, dann mit 16-Bit aufwärts wirklich einheitlich bei der M68K-Familie und üblicherweise auch bei etlichen RISC-Architekturen.
    Bei den frühen 8-Bit-CPUs waren Register stark an ihren Hauptzweck gebunden und die Befehle sehr eng auf diese zugeschnitten. Da der Entwurfsprozess noch nicht sehr automatisiert oder elektronisch unterstützt war, war auch der Spielraum nicht wahnsinnig groß, um Eleganteres (und meist umfangreichere Konzepte) umzusetzen, schließlich wollte man ein Produkt auch in endlicher Zeit auf den Markt zu bringen.

  • Ist ja witzig, dass es nicht "direkt" geht. Drängt sich die Frage auf, warum das nicht geht :)

    Ja, ist im Prinzip eine Design-Entscheidung bei einer CPU.

    Die Design-Entscheidung beim 6502 war: so billig wie irgendwie möglich. Dafür musste die Chipfläche möglichst klein sein und damit war die Anzahl der Transistoren und damit auch die Anzahl der Funktionen begrenzt. Deswegen kostete der Prozessor beim Erscheinen auch deutlich weniger als die Konkurenzprodukte und deswegen war er so erfolgreich. Wir reden hier nicht von ein paar Dollar, sondern von $25 für den 6502 gegenüber $175 für den 6800.


    Aber die Geschichte ist doch eigentlich bekannt? :nixwiss:

  • Wo liegt eigentlich der Stapelzeiger?

    Da:


    Beste Antwort. :thumbsup:


    Jetzt habe ich mal ne doofe Frage an alle. Gibt es besondere Gründe warum ein Stapelspeicher immer nach unten wächst und nicht nach oben?

  • Jetzt habe ich mal ne doofe Frage an alle. Gibt es besondere Gründe warum ein Stapelspeicher immer nach unten wächst und nicht nach oben?

    Aus Sicht von "fetten" 6502/6510-Computern mit 64k Speicher ist das schwer nachzuvollziehen.


    Aber stell dir mal als Extemfall ein kleines Embedded-System mit 128 oder 256 Byte RAM vor. Da wird der Speicher mehrfach gespiegelt um die Pages 0 (Zero Page) und 1 (Stack) überhaupt abdecken zu können. Wenn der Stack dann von unten nach oben wachsen würde, dann beginnt er (gespiegelt) in der Zero Page bei Adresse 0. Das ist ja irgendwie unschön, weil man dort ja mit seinen Zero-Page-Variablen beginnen möchte. Wenn der Stack von $FF bis $00 läuft, kommt man sich nicht ins Gehege, solange man den Stack nicht soweit ausreitzt, dass er einem in die Zero-Page-Variablen reinläuft.


    Aus solchen Überlegungen heraus, was es damals (als der 6502 entwickelt wurde) üblich, dass der Stack von oben nach unten wächst. Das war einfach üblich und die Programmierer daran gewöhnt.


    Es gibt noch andere Argument, zum Beispiel, dass man auf dem Stack abgelegte Daten leichter über Indizierte Adressierung erreichen kann, wenn die Daten immer oberhalb des aktuellen Stackpointers liegen. Anderenfalls müsste man mit einem negativen Index arbeiten, um an die Daten ranzukommen. Aber ob solche Tricks wirklich die Design-Entscheidung beeinfluss haben, das bezweifle ich. Embedded-Programme arbeiten üblicherweise mit PUSH und POP auf dem Stack. Dass indiziert auf den Stack zugegriffen wird, ist doch eher die Ausnahme. Der 6502-Stack ist auch viel zu klein um dort mehr als mal ein paar Bytes abzulegen.

  • Aber stell dir mal als Extemfall ein kleines Embedded-System mit 128 oder 256 Byte RAM vor. Da wird der Speicher mehrfach gespiegelt um die Pages 0 (Zero Page) und 1 (Stack) überhaupt abdecken zu können. Wenn der Stack dann von unten nach oben wachsen würde, dann beginnt er (gespiegelt) in der Zero Page bei Adresse 0. Das ist ja irgendwie unschön, weil man dort ja mit seinen Zero-Page-Variablen beginnen möchte. Wenn der Stack von $FF bis $00 läuft, kommt man sich nicht ins Gehege, solange man den Stack nicht soweit ausreitzt, dass er einem in die Zero-Page-Variablen reinläuft.


    Aus Ataris 2600 Programmers's Guide:


  • Jetzt habe ich mal ne doofe Frage an alle. Gibt es besondere Gründe warum ein Stapelspeicher immer nach unten wächst und nicht nach oben?

    Aus Sicht von "fetten" 6502/6510-Computern mit 64k Speicher ist das schwer nachzuvollziehen.


    Aber stell dir mal als Extemfall ein kleines Embedded-System mit 128 oder 256 Byte RAM vor. [...] Wenn der Stack von $FF bis $00 läuft, kommt man sich nicht ins Gehege, solange man den Stack nicht soweit ausreitzt, dass er einem in die Zero-Page-Variablen reinläuft.

    Wobei man sagen muss, dass selbst beim voll ausgebauten C64 noch Teile des wertvollen Stacks für andere Zwecke benutzt werden. Laut "Mapping the C64" für Variablenkonvertierungen und als Zwischenspeicher für Kassettenoperationen. Immer rein in die gute Stube!


    In der entsprechenden Routine zur Speicheranforderung sieht man daher, dass der angeforderte Speicher immer um 62 erhöht wird.

    Code
    1. .C:a3fb 0A ASL A ; 2 Bytes pro gewünschtem Eintrag
    2. .C:a3fc 69 3E ADC #$3E ; Anzahl der Bytes um 62 erhöhen
    3. .C:a3fe B0 35 BCS $A435 ; Überlauf? ==> OUT OF MEMORY
    4. .C:a400 85 22 STA $22 ; Anzahl erforderlicher Bytes merken
    5. .C:a402 BA TSX ; mit Stapelzeiger
    6. .C:a403 E4 22 CPX $22 ; ... vergleichen
    7. .C:a405 90 2E BCC $A435 ; Stapelzeiger schon zu weit "unten"? ==> OUT OF MEMORY
    8. .C:a407 60 RTS ; ok

    Ich vermute, das kommt noch aus einer Zeit, als das Microsoft BASIC auf Plattformen mit weniger RAM laufen musste. Also sagte man sich wohl: Beim Stack wissen wir wenigstens, dass er da ist. :)

  • Ja, ist im Prinzip eine Design-Entscheidung bei einer CPU.

    Da ist davor noch eine viel grundsätzlichere Entscheidung fällig: von Neumann oder Harvard?


    Harvard haben heut meist nur noch Controller, die neben dem ROM auch das RAM intern haben und somit die sonst sehr vielen Leitungen für unterschiedliche Busse entfallen mit dem Manko, das das Speichermodell (und im Wesentlichen auch die verfügbare Größe) durch das festgelegt ist, was sich auf dem Chip (oder SoC) integrieren lässt.

    Vorteil ist eben, das man VIELE Register haben kann, die auch im Adressraum abbildbar sind. Beispiel für so eine Architektur sind die kleinen PIC Controller von microchip, ich schreibe "kleine" denn deren Wortbreite ist recht schräg und passt in kein sonstiges Schema, eben WEIL die auch Harvard-Architektur nutzen und z.b. in den Befehlsworten gleich noch andere Dinge mit decodieren, was sich durch zusätzliche Bits äussert.


    von Neumann ist das, was man im Allgemeinen seit den ersten 8-Bit Prozessoren so kennt, d.h. RAM und ROM teilen sich einen Adressbus, bei den 68xx und 65xx ist auch das I/O memory-mapped, die sind an dieser Stelle quasi puristisch von Neumann *), während u.a. die Intel und Zilog-Architekturen zwar den gleichen physikalischen Adressbus nutzen, aber getrennte Zugriffs-Controll-Leitungen dafür haben was gerade bei 8Bit CPUs mit dem kleinen 16bit Adressraum durchaus ein Vorteil ist, aber generell natürlich für durchgängiges RAM sorgt und auch ne gewisse Schutzfunktion hat, so kann eine falsch laufende Kopierschleife zwar das RAM korrumpieren und eventuell die CPU zum Absturz bringen, aber eben nicht irgendwelche HW-Register überschreiben mit eventuell fatalen Folgen (z.b. mochten es Röhren-Monitore (CRTs) überhaupt nicht, wenn man falsches H/V-Timing ausgab, denn deren Netzteile takteten teils direkt damit, d.h. geht auf den Zeilentrafo dann...) Zudem vereinfacht das auch das DMA zw. Speicher und I/O in gewissen Konstellationen.



    *) speziell die 65xx mit ihren extrem wenig internen Registern aber dafür "Kurz"-Befehlen für die Zero-Page sind aber dadurch auch wieder ne Art Zwitter, denn damit liegt ein Großteil der real benötigten Register ja im RAM, zwar uniform angesprochen, aber doch abweichend genutzt (und diese Page ist ja auch nicht frei verschiebbar, d.h. so richtig "universell" ist das dann auch nicht mehr... (und die Zugriffe auf diese "Register" kosten dann die zusätzlichen Zyklen, die komplexe CPUs wie die Z80 eben durch ihr ausgefeiltes Bustiming und deutlich aufwändigere Befehlsdekodierung "verschwenden", was zu weniger Leistung je MHz Takt führt, sofern man auf 65xx Seite eben mit dendrei Registern auskommt, was eher selten der Fall sein dürfte, bei Hochsprachen, sprich automatischen Compilern schon gleich gar nicht... Da zieht dann eine Z80 oder gar i86 CPU recht deutlich am 65xx vorbei...

  • *) speziell die 65xx mit ihren extrem wenig internen Registern aber dafür "Kurz"-Befehlen für die Zero-Page sind aber dadurch auch wieder ne Art Zwitter, denn damit liegt ein Großteil der real benötigten Register ja im RAM, zwar uniform angesprochen, aber doch abweichend genutzt (und diese Page ist ja auch nicht frei verschiebbar, d.h. so richtig "universell" ist das dann auch nicht mehr... (und die Zugriffe auf diese "Register" kosten dann die zusätzlichen Zyklen, die komplexe CPUs wie die Z80 eben durch ihr ausgefeiltes Bustiming und deutlich aufwändigere Befehlsdekodierung "verschwenden", was zu weniger Leistung je MHz Takt führt, sofern man auf 65xx Seite eben mit dendrei Registern auskommt, was eher selten der Fall sein dürfte, bei Hochsprachen, sprich automatischen Compilern schon gleich gar nicht... Da zieht dann eine Z80 oder gar i86 CPU recht deutlich am 65xx vorbei...

    Der 6502 ist beim Bus-Zugriff doppelt so effizient wie der Z80. Der 6502 braucht minimal 2 Zyklen und der Z80 braucht minimal 4. Deswegen laufen Z80-Systeme typischerweise mit 2 oder 4 MHz. Wenn man mit den 256 Byte Stack des 6502 auskommt, dann ist der 6502 mit seinen schnellen 256 Zero-Page "Registern" im Vorteil. Erst bei größeren Systemen, wie zum Beispiel CP/M, wo mit C und Pascal gearbeitet wird und 16-Bit Zeiger benötigt werden, ist der Z80 wirklich im Vorteil. Für sowas wurde der 6502 aber auch gar nicht designt.

  • sofern man auf 65xx Seite eben mit dendrei Registern auskommt, was eher selten der Fall sein dürfte, bei Hochsprachen, sprich automatischen Compilern schon gleich gar nicht... Da zieht dann eine Z80 oder gar i86 CPU recht deutlich am 65xx vorbei...

    Ach schau Dir mal llvm-mos an, das optimiert schon ziemlich gut für die drei Register und "weiß" auch von der Zeropage.

  • sofern man auf 65xx Seite eben mit dendrei Registern auskommt, was eher selten der Fall sein dürfte, bei Hochsprachen, sprich automatischen Compilern schon gleich gar nicht... Da zieht dann eine Z80 oder gar i86 CPU recht deutlich am 65xx vorbei...

    Ach schau Dir mal llvm-mos an, das optimiert schon ziemlich gut für die drei Register und "weiß" auch von der Zeropage.

    Ja, wenn man es speziell dafür schreibt und sogar Sprachelemente passend sozusagen zu den Fähigkeiten auslegt, dann sicherlich!


    Wenn ich heute von Hochsprache spreche, dann meine ich C/C++, bestenfalls noch was in Richtung Python, ist meine subjektive und den eigenen Fähigkeiten und Interessen entsprechende Gewichtung, ich möchte weder den Compiler oder gar die Sprache mir erst selbst zimmern müssen, noch will ich damit irgendwas Vernetztes oder sonstwie Komplexes "interaktives" erstellen und sehe natürlich die 65xx auch rein im embedded bereich noch als reizvoll an (aufgrund z.b. der kurzen IRQ-Latenzzeiten, die durchaus mit deutlich größeren Controllern mithalten können...)


    Aber wie gesagt: ohne dazu erst ne Sprache bauen oder lernen zu müssen. C ist so die "universelle" Sprache im embedded Bereich, keine "echte" hochsprache, aber eben auch kein hochgradig typspezifischer Assemblercode mehr und strukturierter und flotter als Basic (dem ich für die einfache Handhabung, insb. "direct mode" immer noch etwas nachweine..)


    Für sowas wurde der 6502 aber auch gar nicht designt

    Heißt im Umkehrschluss, das der 6502 eben NICHT in der Liga der PC-Prozessoren spielt, sondern eher im Bereich der embedded controller. Das deckt sich mit meiner Einschätzung, aber wird von einigen hier sicher schon als 6502 "bashing" wieder gesehen werden...


    Praktisch gesehen wurde diese Geschwindigkeit gegen mittelfristige Skalierbarkeit erkauft, denn selbst 10 Jahre später noch, also Anfang der 1990er waren Speicher kaum für mehr als 16 MHz-6502 Clk also 33 MHz "normalen" Clk verfügbar (als CACHE S-RAMs für x86-Systeme) , d.h. schnellere 6502 als die 14MHz Variante von WDC machen keinen Sinn mehr. Die Prozessorentwicklung ging da andere Wege und die Entkopplung des Rechnerkerns von der Speicherschnittstelle war da einer der innovationspfade, die Mittel dazu unterschiedlich und meist komplex, aber eben weit weg vom Konzept des 6502.


    Baut man den Speicher intern in einen Controller oder SoC ein, geht mehr, siehe z.b. Renesas mit deren größeren Controllern "SHxx", die teils 100MHz direkt aus dem internen Flash können (war mal Bestmarke, aber auch schon wieder ne Zeit her, verdammt, 2008 war ich mal auf nem Workshop zu...)