Posts by BlondMammuth

    Hallo Alle,


    ich stehe grade wie die Kuh vorm neuen Tor, weil in meinen VICE 3.1-Installationen offenbar der Menü-Punkt "Peripheral Settings" verschwunden ist. Irgendwo hab ich was vergessen, falsch gemacht, missverstanden .. ich weiß es nicht. Kann mir jemand einen informationstechnischen Tritt geben, damits wieder weiter geht?


    Danke!



    UPDATE: Nicht mehr nötig, schon bemerkt: Die entsprechenden Punkte sind mittlerweile in die anderen Untermenüs integriert worden.

    Es ist wirklich witzig: Grade vor ein paar Tagen habe ich begonnen, mich ernsthaft mit DurexForth 1.6.3 zu beschäftigen, dabei sind zwei Fragen aufgetreten, und ich habe mir gedacht: Schau ich einmal ins Forum, vielleicht hat sich schon einmal jemand damit beschäftigt - und finde diesen großartigen Einstieg! :-)


    Mir geht es allerdings um drei andere Fragen, vielleicht weiß zufällig jemand von euch mehr darüber:

    • Im Handbuch wird "forget" erwähnt, und zwar so:
    Code
    1. marker forget
    2. : x ;
    3. forget

    Das soll angeblich, wenn man das Wort aufruft, dieses Wort selbst und alles danach an Definitionen löschen. So weit so logisch. Nur bekomme ich die Fehlermeldung forget?. Ist das überhaupt richtig implementiert, oder wende ich es bloß falsch an?


    • folgender Eintrag:
    Code
    1. \ Comment to end of line. (Used when cross-compiling from PC/ASCII.)

    Meint er damit das Editieren der Sourcen auf PC, oder gibt es tatsächlich einen Cross-Compiler? Wenn ja, ist er gut versteckt!


    • und das hier:

    Ich hatte damals ein Programm für die C-64-Floatroutinen geschrieben für Durexforth und habe eine Lösung gefunden um 2 Grafikbildschirme wechselseitig zu nutzen desweiteren die Reubefehle eingebunden.

    Genau danach habe ich grade gesucht. Hast du die noch? Funktionieren sie? Das Zeichnen und dann umschalten auf die fertige Graphik wäre wichtig.

    Ich hab dummerweise in meiner VM noch zuviel anderen Kram, sonst würd ich Dir einfach die VM kopieren.


    Ich setze mir für sowas immer ne neue VM auf, wo ich alles mögliche drin installieren kann, ohne mein Hostsystem zu beeinflussen.


    Vielleicht ist das ne Idee für Dich?

    Sogar eine sehr gute, so halte ich es nämlich auch. ;-)


    Ich hab eine Lubuntu-VM extra nur für das Emulations-Thema. Aber nach etlichen Versuchen krieg ich nicht einmal noch raus, wo der Fehler in meinem Fall liegt. Ich glaub ich warte bis eine neue Version rauskommt. So wird das nix. *g*


    Wobei .. was alles würdest du mir dann kopieren wollen? Ich bräucht ja eigentlich nur den GCC-6502. Ist da soviel mehr Kram dabei?

    Sollten sich verschiedene Instanzen bei Aufruf einer Methode verschieden verhalten? Aber sicher! Braucht man sowas? Ja, laufend.

    Latürnich braucht man das laufend. Gerade deshalb gibt es ja eine potentiell nach unten hin unendlich tiefe Typ-Hierarchie, und man kann jeden, aber auch wirklich jeden Spezialfall auf diese Art konstruieren, und eine oder mehr Instanzen davon erstellen. Dazu braucht es immer noch kein Instanz-spezifisches Methoden-Dispatching, und ich habe das Gefühl, dass du genau da ein wenig auf der Leitung stehst: Du siehst Möglichkeiten bloß in der Instanz-spezifischen Implementierung, die es in Wirklichkeit aber anders auch gibt. Vielleicht ist das vergleichbar mit der Art, wie ich bei der Adressierungsart oben etwas eindimensional gedacht habe.


    Vergiss nicht, dass die Instanz einer Klasse IMMER auch Instanz jeder Oberklasse ist, daher natürlich Instanzen einer Klasse immer auch im Verhalten individuell abweichen können, einfach indem sie auch Instanzen verschiedener Unterklassen sind.


    Natürlich setzt die volle Nutzung dieser Möglichkeit dynamische Methodentabellen in Klassen voraus, aber das wäre ja auch nichts anderes als Funktionsvariablen, nur eben auf Ebene der Klassen statt der Instanzen. Hält man es statisch, muss man die genaue Klasse halt im Programm jedesmal an der Stelle angeben, um die richtige Methode zu erwischen. Das ist halt der Nachteil des statischen Methoden-Dispatching.

    Kannst Du nicht mal nen Laptop mit zu Deinem Kumpel (mit der guten Internetverbindung) nehmen und dort ein clone machen?

    Ja, das habe ich hiermit versucht, beim besten aller Freunde, nämlich mir selber zuhause - hier geht das Internet wie die Feuerwehr - und jetzt habe ich diese nette Meldung beim build:


    Ich verzweifle langsam mit dem Zeugs. Irgendwo tief im Urschlamm der komplizierten Sourcen und windigen make-build-compile-sonstwas-Konstruktionen geht immer die dritt-unnötigste Zwergen-Operation von links schief.


    Warum stellen die nicht einfach ein binary für Linux online? Oder haben sie selber noch keines erstellen können? :cry:

    Beim Umkopieren würde man zunächst die absoluten Zeiger des Quell- und Zielobjekts berechnen. Dafür gibt es die Anweisung LEA (= Load effective address). Der Befehl "LEA offset(sp), Rx" berechnet die Adresse einer beliebigen Variable auf dem Datenstapel und schreibt das Ergebnis nach Rx.

    Stimmt, und gestern ist mir die Erleuchtung auch gekommen, leider viel zu spät: Selbst wenn es so eine Möglichkeit nicht gäbe, berechnet man in dem Fall einfach die Stack-Addresse vorher (explizite Addition), und springt danach eine Routine an, die diese fixe Adresse benutzt.

    Von welchen Registern sprichst Du hier?

    Stell dir vor, du hast es in Routinen mit Addressen zu tun, die du aus zwei Komponenten berechnen musst, die erst zur Laufzeit bekannt sind. Dann wirst du die beiden addieren müssen, das Ergebnis in ein drittes Register ablegen, und die Routine anspringen. Die beiden Komponenten wirst du entweder rausspeichern oder zwei Register dafür besetzt halten. Darum gings.


    Allerdings habe ich meinen Denkfehler bezüglich der Notwendigkeit bereits bemerkt, deine Antwort gibt eine zusätzliche Möglichkeit, und gebe dir umso mehr recht, als es im CPU-Design ein beliebter Denkfehler ist, wenig gebräuchte Möglichkeiten mit viel Aufwand trotzdem vorzusehen.


    Da die Addresse auch dann, wenn sich zwei variable Komponenten ergeben, effizient vorher berechnet werden kann, wäre so eine Adressierungsart tatsächlich ein veritabler Overkill!


    Übrigens, falls du es noch nicht kennst, rate ich dir sehr zu diesem extrem guten Klassiker!

    Gehen wir mal davon aus, daß es sich bei der VM um eine Stackmaschine handelt, die ähnlich funktioniert wie die p-code-Maschine von UCSD-Pascal.

    Würd ich ja nicht, aber du hast mehrere Modelle besprochen, also ist das irrelevant. ;-)

    lda (datenzeiger), y

    Genau da haben wir sie, die doppelt variable Addressierungsart. Und genau das geht mir ab, wenn es das nicht gibt. Du zeigst mir zwar oben, wie man 2-Byte-Zahlen oder auch 4-Byte-Zahlen halt mit der entsprechenden Anzahl Befehlen doch noch einigermassen knapp verschieben kann, aber sobald ich z.B. ein recht umfangreiches Objekt auf dem Datenstack habe, und es einfach nur woanders hin kopieren will, steigt entweder die Länge des Codes proportional zur Größe dieses Objekts, oder, wenn ich das anders lösen will, wird mein Code-Stück enorm unhandlich, weil es jedesmal die Adress-Addition explizit vornehmen muss, und weil dafür nicht zwei, sondern drei Register gebraucht werden (eines, in dem das Resultat steht, die beiden andere, weil man sie noch braucht).


    In dem Fall würde ich die Aussage, dass das selten vorkommt, sehr ungern akzeptieren, weil das völlig von der Sprache abhängt, die ich auf der VM exekutieren will. Auf die Weise nimmt man einfach eine Möglichkeit weg, die u.u. wichtig werden kann.

    Das ist unverhältnismäßig viel dafür, daß diese Adressierungsart in Programmen eher selten vorkommt.

    Bei mir würde sie eben sehr oft vorkommen, sofern ein Datentyp die Registerbreite übersteigt, was grade beim 6510 sehr schnell passiert, bei 16 bit wohl nicht ganz so oft, aber womöglich auch, wenn z.B. ein C-Compiler einen "long" Typ auf einem Target mit Breite 16 realisieren will.

    Wenn die Variablen eine feste Position haben, d. h. einen festen Offset, braucht man ja gerade keinen Registerindex mehr, oder? Irgendwie stehe ich hier auf dem Schlauch.

    Nicht, wenn die Befehle direkt 1:1 in Assembler übersetzt werden.


    Aber ich gebe dir das Standard-Gegenbeispiel auf dem 6510: Nimm eine 16bit-Multiplikation.


    Code
    1. FUNCTION nonsense(a:CHAR,b:INTEGER,c:INTEGER,d:CHAR):INTEGER
    2. VAR bullsh: INTEGER;
    3. BEGIN
    4. bullsh:=b*c;
    5. ..
    6. END;


    Die beiden Operanden stehen auf dem Stack in b und c. Eine 6510-VM würde vermutlich diese beiden Werte mit je 2 Bytes vom Stack in feste ZP-Register kopieren, multiplizieren, und das Ergebnis vorbehaltlich etwaiger Optimierungen vermutlich wieder auf den Stack zurückkopieren.


    Nehmen wir an, der Stack-Pointer steht in X, und wir versuchen das Ganze mit einem ZP-basierten Stack. Das Programm kennt zur Laufzeit die TOS-Position in X und z.B, die relative Position B von b auf dem Stack. Wäre b ein einzelnes Byte, wäre es kein Problem, das Laden so zu übersetzen:

    Code
    1. LDA B,X
    2. STA ARG0

    Aber es handelt sich um zwei Bytes. Oder sogar um 4 Bytes, je nach Registerbreite. Also würde alleine der Transport von Stack-Position B in ARG0 so aussehen müssen:

    Code
    1. LDA B,X
    2. STA ARG0
    3. LDA B+1,X
    4. STA ARG0+1

    .. und das müsste IMMER im übersetzten Code stehen, also 8 bytes an Code alleine für den Transport in eine Richtung verschwendet.


    Das wollen wir natürlich nicht. Also machen wir es mit Bytecode, zumindest aber mit einem Unterprogramm, das parametrisiert die 2 (oder 4) Bytes von einer gegebenen Addresse auf dem Stack in die ZP lädt.


    Und genau da rennen wir in das Problem, das ich meine. Denn obwohl für den Compiler der Offset zur Übersetzungszeit bekannt und klar ist, hat die VM keine Möglichkeit, sie implizit zu codieren. Wenn der Compiler einen Unterprogramm-Aufruf zur Kopier-Routine generiert, muss er die Position auf dem Stack noch einmal von einer Konstante in einen expliziten Übergabe-Wert verwandeln, weil das Unterprogramm ja nur einmal generiert wird, und nicht für jeden Offset neu (das wäre unverantwortlicher Wahnsinn für die Code-Länge).


    Das Unterprogramm, das er anspringt, muss also ZWEI Variablen berücksichtigen: Zum einen die TOS-Position (klar), zum anderen aber den Offset der zu kopierenden Variable. Es muss (TOS+Offset) berechnen!


    Es kann daher entweder die resultierende Addresse auf die langsame Tour berechnen (wenn es halt keine entsprechende Addressierungsart gibt), oder es hat so eine Addressierungsart mit zwei variablen Anteilen zur Verfügung - auf dem 6510 wäre das (ZP),Y (und zu Glück gibts wenigstens die!).


    Diese Address-Berechnung kommt also jedes Mal vor, wenn ein Zugriff nicht mit genau einem Assembler-Befehl direkt abgedeckt ist. Es wäre daher extrem vorteilhaft, auf irgendeine Weise so eine Addressierungsart vorzusehen, und wäre es nur für eine Registerbreite und nur für einen Lade- und einen Speicherbefehl - das würde tatsächlich völlig genügen, es wären bloß zwei OpCodes. Aber ohne die wirds echt zäh im Falle des Falles!

    Für Weiteres BITTE ruhig fragen oder kritisieren.

    Doch, mir fällt noch was ein.


    Mir ist aufgefallen, dass mir beim 6510 genau eine ZP-Indirektion fehlt. Ich bräuchte eine Adressierungsform, die zwei variable Addressen quasi addiert.


    Dieses:

    d) offset(r0) = Register indirekt mit Offset

    hat für mich dieselbe Problematik, eine Indirektion zuwenig. Ich hätte gerne etwas wie z.B. LDA (ZP),Y.


    Da habe ich den Vorteil, sowohl ZP als auch Y anpassen zu können. Leider gibts das nicht in ZP-Ausführung (also 1 byte-base mit 1-byte-offset, was es schneller machen würde). Aber bei der obigen VM scheint es sowas überhaupt nicht zu geben?


    Warum brauche ich es?


    Weil ich nur so einen Stack simulieren kann, der fest positionierte Variablen pro Stackframe enthält. Ja, ich kann auch mit ZP,X arbeiten, aber damit kann ich NUR die einzelnen Befehle so hin compilieren. Ich kann nicht sagen: Spring mir einmal in die Unterroutine und wende sie auf diese Base mit dem Y-Offset an. Geht nicht. Die konstante Base muss dazu in einem Register stehen, bzw. in der ZP, sie kann nicht implizit verwendet werden wie im reinen Assembler. Also gehts nur, wenn quasi BEIDE zu addierenden Bestandteile der Addresse in variabler Form (jedenfalls nicht implizit) vorliegen.


    Daher geht bei 6510 nur die (ZP),Y Version für eine VM, und bei der vorgestellten VM müsste man auch jedes Mal zwei Zahlen addieren, um die Addresse in der Weise rauszukriegen, und - weil man ja die Base UND den Offset sich merken will - drei Register dazu verwenden statt einem.


    Hätte man aber einen Befehl wie (Hausnummer)


    Code
    1. ld r1,(r5,r6)


    Dann wäre damit r5 die Base, r6 der Offset, und der Content von dieser summierten Addresse würde nach r1 geladen. Das wäre genau das, was man braucht, um einen Stack mit Stackpointer und Offset einfach darzustellen.

    Ich kann es mal versuchen, bitte aber um Nachsicht, wenn es etwas konfus ist, da ich nicht weiß, wo ich anfangen soll.

    Dafür ist es aber großartig gelungen und in vielen Bereichen ein Augenöffner. Wie schon woanders erwähnt, hast du viele Gedanken zuende gedacht, auf die andere (wie ich z.B.) noch nicht einmal gekommen sind, und das ist (zumindest für mich) ein enormer Gewinn!

    a) Früher hatte ich mal überlegt, ob es gut wäre, den PC als Register im Registersatz zu halten.

    Typisches Beispiel dafür! Wunderbar erläutert, warum das keine gute Idee ist, obwohl sie zunächst recht einladend herüberkommt.

    Viele RISC-Prozessoren verwenden für den Unterprogrammaufruf ein Linkregister

    Mir scheint, dass das wirklich nur eine Verschiebung darstellt. Der TOS des Return-Stacks ist dann halt im Registersatz, aber mehr schaut dabei nicht wirklich raus. Anders wäre es, wenn man auf JSR und RTS grundsätzlich verzichtet. Aber ob das so eine gute Idee ist?

    c) Beim Stapelzeiger hingegen bietet es sich an, diesen im Registersatz als r15 aufzunehmen, da man so leicht auf lokale Daten auf dem Stapel zugreifen kann.

    Ich dachte, der wäre in RISC-Architekturen ohnehin nicht explizit sondern als Multiple-Purpose-Register implizit ausgeführt? Dann wäre die Verwendung von r15 bloß Konvention (notwendig, weil sonst Chaos ausbricht).

    movq #$56, r1

    Warum "q", und nicht "l" für LO?

    Dies entspricht der 6502-Adressierung "abs, x", nur daß hier das Register 16 Bit breit ist.M. J. schrieb:

    Dabei würde ich ohnehin fragen wollen: könnte man diesen Befehllssatz mit geringem Aufwand tatsächlich bezüglich der Registerbreite variabel gestalten? Beispiel wie oben diskutiert, ich hätte gerne 32 bit Breite. Abgesehen vom Laden von Konstanten, das dann entsprechend 8 Bytes bräuchte? Wenn man das mit den Konstanten auch noch ein wenig auf neutral trimmen könnte, hätte diese Architektur den Ansatz, sich auf größere Breite übertragen zu lassen?

    Der Code von SWEET16 wurde 1977 in der November-Ausgabe des BYTE-Magazins abgedruckt:
    https://archive.org/details/byte-magazine-1977-11


    Jetzt macht sowas relativ wenig Sinn, wenn man damit nicht beabsichtigt, daß andere es in ihren eigenen Programmen verwenden können. :whistling:


    Also, mit einer Erwähnung in den Credits, daß SWEET16 von Woz im eigenen Programm zum Einsatz kommt, sollte der Drops gelutscht sein. Zumal man ja vermutlich ohnehin ein wenig Anpaßarbeit hineinstecken durfte (das Original verwendet $00..$1F zur Ablage der 16 16-Bit-Register, was auf dem C64 nicht so gut funktioniert ...)

    Ja, schaut gut aus! Vielen Dank für die Aufklärung! :puhh:

    Wenn ein Interpreter auf dem C64 schnell genug für brauchbare Sachen ist, dann sollte sie auch für einen Amiga gut genug sein - auch wenn da andere Designs schneller sein könnten. Wäre zwar schon cool, wenn auch der Zwischencode querbeet auf verschiedenen Geräten schnell interpretiert werden könnte, aber die Dinger mit ihrem fetten Speicher können das im Zweifel auch richtig compilieren.

    Ich gebe zu, ich bin ein Fan von VMs eben deswegen, weil man damit alle Plattformen erreichen kann. Dass nativer Code meistens schneller ist - eh klar. Dafür gibts ja JIT-Compiler. ;-)

    Ich befürchte, daß es nicht so einfach wird, Beispiele dafür aufzutreiben, da es SWEET16 an allerlei Befehlen wie MUL, DIV, AND, EOR, OR, >> und >>> mangelt. Berechnungen sind begrenzt auf + und - , was die Einsatzmöglichkeiten stark einschränkt. Zudem kann man diese noch relativ leicht in 6502 umsetzen. Damit sich der Einsatz von SWEET16 lohnt, muß man wirklich sehr viele Additionen und Subtraktionen oder Speicherkopier-Aktionen ausführen, damit bezogen auf die Codegröße eine Ersparnis eintritt.

    Aber damit wäre vielleicht der Ausbau der SWEET16 mit Multiplikationsbefehlen, vielleicht Fliesskomma, ein Projekt, dem man vielleicht näher treten könnte? Vielleicht sogar eine Weiterentwicklung auf wahlweise 32 bit, wie hier schon besprochen?


    Was ich nur nicht weiß, ist, wie weit es da Copyright-Probleme geben könnte. Aber theoretisch könnte man ja Steve Wozniak um Erlaubnis bitten :?::schreck!:

    Wie ich vorher geschrieben habe, sind das die Verschiebe-Befehle, da hier wirklich auch von der Semantik her Bits angesprochen werden, wohingegen AND, OR und XOR nicht nur bei arithmetischen, sondern auch bei logischen Operationen eingesetzt werden.

    Ah klar, die Verschiebungen habe ich vergessen, danke!

    Bei SWAP wird es dann haarig, weil hier zwei Elemente beteiligt sind.

    Ganz ehrlich, ich würde SWAP ersatzlos stanzen.

    Nein, das ist keine gute Idee. 128 Bytes auf der Zeropage nur für den Evaluationsstack ist meiner Meinung nach entschieden zu viel. Die VM soll ja auch in andere (Assembler)Programme als Zusatz eingebaut werden. Wenn dann schon mehr als die halbe ZP nur für die VM draufgeht, ist das mehr als hinderlich. Desweiteren bedeutet dies auch wieder, daß es zu Lasten der normalen Befehle geht, die nur 16 Bit davon verwenden.

    Warum denke ich da anders? Weil - gesetzt den Fall, dass jemand so wahnsinnig ist, tatsächlich 64bit-Arithmetik auf der VM auf dem C64 zu konfigurieren - das so ein seltener Fall ist, und die Routinen (besonders Mult und Div und Exp) dermassen bremsen, dass es dann auch schon egal ist, wieviel Platz noch in der ZP bleibt, während es im Normalfall 32 oder 64 bytes Stack wären - ausser, man macht den Stack kleiner, dann sinds noch weniger. Das gilt übrigens auch für 64 bit.

    Float64 auf dem 6502 halte ich schlicht für overkill, und Float32 auf dem PC gebrauche ich gar nicht mehr. Es sind einfach getrennte Welten.

    Ja, aber vielleicht hälts jemand anderer nicht für Overkill, und möchte die VM so ausstatten? Der kommt dir ja damit nicht in die Quere.

    Weil all diese Extrawürste massiv zu Lasten der Effzienz gehen. Diese Extrawürste sind völlig kontraproduktiv.

    Nur für den, der sie in Anspruch nimmt. Nicht für alle anderen, die ihre VM nicht so ausstatten. Wobei ich auch Sprachen im Kopf habe, die sich langsam entwickeln, und für die ich gerne bestimmte Möglichkeiten beibehalten möchte.

    Soll man dann für diese verschiedenen Speicherbreiten auch noch Befehle im Befehlssatz reservieren?

    Ja, aber anders, als du auffasst, denke ich.

    Ich werde den Eindruck nicht los, daß Du bei der VM noch viel zu hardwarenah denkst. Eine VM an sich ist bereits eine Abstraktion von der Hardware. Es gibt keinen Grund, warum man in den Befehlssatz einer VM Hardwarestrukturen abbilden muß.

    Stimmt, das hast du sehr gut erkannt. Das ist der Unterschied zwischen uns. Für mich wäre die VM der Versuch, eine potentere CPU zu simulieren, als der 6510 sie darstellt. Ich würde sie daher möglichst allgemein halten wollen.

    Das Gegenteil ist eher der Fall. Es geht um die ausführbare Repräsentation sprachlicher Konzepte einer Hochsprache, aber nicht darum, irgendwelche Bytestrukturen abzubilden.

    Ja, dir. ;-) Da sind wir, glaube ich, schon seit einiger Zeit nicht synchon gelaufen. Dabei verstehe ich deinen Ansatz recht gut, er ist ja nicht abwegig. Er ist sogar recht empfehlenswert. Ich spreche nicht nur über p-Code, sondern mir fällt gleuch auch die Warren Abstract Machine für Prolog ein, und einige mehr - in den Fällen hast du völlig recht. Aber es gibt Beides, und der Trend, verschiedenste Sprachen auf einer VM zu implementieren, ist eindeutig da. Vermutlich werden die VMs sich irgendwann wirklich in diese zwei grundsätzlichen Kategorien aufspalten.

    Der Befehlsaufbau einer VM orientiert sich daher auch an einem RISC- und nicht an einem CISC-Prozessor.

    Ja, wobei ich dir dann schon den leisen Vorwurf machen muss, dass du grade im folgenden Fall davon abweichst:

    Ich würde das aufsplitten in "berechne die Addresse" - da gibt es ein paar Fälle, wie von dir beschrieben - und "Lade x bytes von dieser Addresse" bzw. "Speichere x bytes an diese Addresse", und das sind dann maximal je 4 Fälle.

    Nein, bitte nicht. Auch das bläht den Code (Bytecode und VM) weiter wahnsinnig auf. Dann brauchst Du für eine Operation schon 2 Bytes mehr als ein normaler Befehl: 1 Byte für EXT und 1 Byte zur Festsetzung der Breite.

    Nein, das bräuchtest du im Normalfall überhaupt nicht, wenn du genau eine Breite verwendest. Nur falls du sie wechseln möchtest, müsstest du einmal was ändern. Aber mir gefallen die getrennten Befehle eh besser.

    Deine Vorgehensweise hingegen ist nur umständlich, langsam und müllt den Speicher zu. Ich weiß nicht, warum ein Programmierer sich das in der Praxis antun sollte.

    Nein, sie müllt den Speicher überhaupt nicht zu, es sei denn, du verwendest diese Möglichkeiten. Dann hast du eine eigene VM, die das tut. Warum Entwickler das tun sollten? Keine Ahnung, ich will mich da gar nicht in deren Entscheidungen einmischen. :D

    Da es sich um eine VM handelt, berechnet der Compiler alle Adressen relativ bezogen auf das jeweilige Segment, also Global, Lokal (liegt auf dem Datenstapel), Code und Konstante. Mehr nicht. Der Bytecode enthält keine absoluten Adressen bezogen auf den C64 (oder sonst eine Plattform). Das gilt für Variablen als auch für Sprungziele. Daher wird hier auch nichts gelinkt.

    Und da verstehe ich ECHT nicht, wieso du dich weigerst, einen C64-spezifischen Linker hintennach zu schalten, der - wenn diese Segmente bereits bekannt sind - die Addressberechnung erheblich einfacher macht, weil er eine Variable (die Segment-Addresse) eliminiert? Oder habe ich das falsch verstanden?

    Nein, das wäre zutiefst ineffizient. Natürlich muß der Compiler mittels verschiedenen Backends in der Lage sein, neben Bytecode für eine oder mehrere VMs auch Code für 68000 oder x86 oder ARM... auszuspucken.

    Ja klar, ich meinte, EINE Version DIESER hypothetischen VM, nämlich die, die du brauchst.

    Bei einem Objekt auf dem Heap hast Du aber immer den Zwischenschritt, daß Du einen zusätzlichen expliziten Zeiger zur Laufzeit benötigst, da es keine absolute (Offset-)Adresse bezogen auf den Heap gibt.

    Möchtest du mir jetzt sagen, dass der Byte-Code nicht weiß, wo der Heap beginnt? Genau das meine ich: Wieso nicht genau das vorher auflösen, wenn doch eh vorher bekannt ist, wo er liegt?


    Der Heap ist eben kein Segment, anders als das lokale Segment, das zwar auf dem Datenstapel im Speicher des Host angelegt wird, aber in sich kein Stapel ist, sondern nur ein Speicherbereich mit festen Adressen.

    Wieso hätte der Heap keine festen Addressen?


    Ich verstehe deine Argumentation nicht. Aus meiner Sicht:

    • Stack-Zugriff: Konstant ist der Offset eines Objekts relativ zum Stack-Pointer bei Aufruf einer Funktion, variabel (also Laufzeit-abhängig) ist der Stackpointer selbst.
    • Heap-Zugriff: Konstant ist die Lage des Heaps, variabel ist die Lage innerhalb des Heaps.

    Mir ist nicht klar, wieso ein Heap-Zugriff komplexer sein sollte, vorausgesetzt, der Zeiger liegt an einer ZP-Stelle vor. Und naja, das ist wieder eine andere Frage, wie er dort hin kommt.

    2.) Den Zeiger irgendwo speichern, aber wo?

    Zum Beispiel in irgendeiner anderen Datenstruktur, die darauf zeigt. Im Allgemeinen baut man die meisten einigermassen flexiblen Datenstrukturen so auf.

    Eine Unterscheidung mittels "PROCEDURE" und "FUNCTION" wie in Pascal würde ich auf jeden Fall vorziehen.

    Mir ist aufgefallen, dass man "VOID" überhaupt nicht brauchen würde. Wenn man den Doppelpunkt nach der Parameterliste weglässt, ergibt sich dasselbe. Ich sehe übrigens nicht den riesigen Unterschied, aber das ist Geschmackssache.

    Ähnlich unlogisch ist nebenbei auch die Bezeichnung "Atheist".

    Aus meiner Sicht ist ein Atheist nicht jemand, der sich mit Religion nicht beschäftigt, sondern jemand, der sich sehr wohl damit beschäftigt, und einen speziellen Glauben vertritt - nämlich dass es keinen Gott gäbe. In diesem Sinne betrachte ich Atheismus sehr wohl als positiv definiert und fast schon eine eigene Religion. Die Leute, die sich einfach nur nicht dafür interessieren, würde ich eher(!) als Agnostiker betrachten, wobei in dem Fall deine Begriffs-Skepsis aus meiner Sicht eher noch angebracht ist.

    Technisch werden diese zwar in den gleichen Bytecode übersetzt, semantisch aber verfügen sie nicht über den gleichen Prozedurtypen.

    Nicht? Welchen dann?

    Hab's immer noch nicht kapiert. Was Du in diesem Beispiel als "indirekt" bezeichnest, ist ja nur die Übergabe als call-by-reference. Das hat mit dem Objekt an sich überhaupt nichts zu tu

    Ich verstehe, was du nicht verstehst. Nein, es geht nicht um die Übergabe. Mir geht es um die Ästhetik des Konstrukts, um seine Semantik. Mir stellt es dabei genauso die Zehennägel auf wie dir bei "VOID", weil ich es unnötig finde, eine Klasse so zu definieren, dass sie bloß Records beschreiben kann, und alles andere, was man gerne beschreiben möchte, als Komponente drin enthalten sein muss (ausser es wäre zufällig ein Record), statt dass das Objekt selbst das ist, was man beschreibt..


    Es ist wirklich nur Geschmackssache. Bleib einfach bei dem, was dir besser gefällt! ;-)