Optimierungsgrad KERNAL /BASIC - fiktiver Talk

Es gibt 337 Antworten in diesem Thema, welches 62.635 mal aufgerufen wurde. Der letzte Beitrag (16. September 2017 um 00:34) ist von Boulderdash64.

  • [Mir wäre] mehr an systematischen Lösungen gelegen, die keine lebenslange Erfahrung mit den C64-Interna voraussetzen, sondern auch für gelegentliche Programmierer (und User) deutliche Verbesserungen bringen.

    So wild ist das nun auch wieder nicht. Zu KERNAL und BASIC gibt es gute Referenzwerke und man muß sich die ROM-Listings ja auch nicht zur Gänze reinziehen.

    Die virtuelle Maschine, die dir da vorschwebt müßte ja auch gar nicht notwendigerweise im ROM beheimatet sein. Schließlich kann man am C64 die ROMs ja auch teilweise oder komplett wegblenden. Dann hast Du entweder 60K RAM + 4K I/O oder sogar volle 64K RAM - nur muß dein neues OS dann den I/O bei Interrupts zwischenzeitlich einblenden.

    GEOS übernimmt auf diese Weise die volle Kontrolle über den Rechner, gibt aber auch noch andere Beispiele. Gerade bei GEOS ging es aber auch um ein Mehr an Funktionalität, das wurde aber schon mit eher zäher Geschwindigkeit erkauft - ohne REU geht da eigentlich nichts gescheit. Und das, obwohl der schnarchlangsame IEC-Bus mit schnellen Übertragungsverfahren in GEOS auf ein gescheites Tempo gebracht wurde.

    Alternativ kann sich dein Entwurf an der KERNAL-Sprungtabelle orientieren und "einfach" nur das BASIC ersetzen. Zwischen BASIC und KERNAL ist die ZP ganz einfach aufgeteilt: alles von $02..$8F gehört zu BASIC und $90..$FA nutzt der KERNAL. Der KERNAL orientiert sich nur an den ersten 4 Bytes im BASIC ROM um es zu starten, andere Sprünge vom KERNAL ins BASIC gibt es nicht, man kann also das BASIC unabhängig vom KERNAL tauschen. In 9K lassen sich sicherlich noch andere Sprachen als das V2 BASIC unterbringen, wenn es bei einer ROM-Lösung bleiben soll. :)

    Interessant fände ich den Ansatz, V2 vielleicht in SWEET16 zu re-implementieren. Eventuell auch nur Teile davon, so daß der unvermeidliche Geschwindigkeitseinbruch gering bleibt. Dazu müßten dann Teile der unteren ZP so umgeschaufelt werden, daß SWEET16 seine Register dort mit unterbringen kann.

    Dann hätten Coder neben BASIC eben auch noch SWEET16 im ROM zur Verfügung und könnten das in eigenen Programmen nutzen. Und dann schauen wir mal, ob nicht doch noch eine ganze Menge Spiele trotzdem noch laufen (weil die das geänderte BASIC-ROM dann doch nicht interessiert). :D

  • on-board-Compiler

    Das dürfte leider nicht so einfach sein. Der erwähnte UCSD-Pascal Compiler benötigt bereits ca. 37 KB, und auch der "Pascal für den C64"-Compiler von Florian Matthes belegt "nur etwa 20 KByte", obwohl beide bereits auf Bytecode basieren. Beide Compiler sind zudem keine optimierenden Compiler, d. h. der erzeugte Code ist suboptimal. Erschwerend kommt hinzu, daß sie als 1-Pass-Compiler konstruiert sind, damit lokale Bezeichner nach Ende ihrer Lebenszeit direkt vergessen werden können, um Platz zu machen für neue. Ansonsten stößt man sehr schnell an die Grenzen der 64KB. Damit entfällt aber auch die Möglichkeit, Optimierungen wie Deadcode-Eliminierung oder Umsortieren von Variablenadressen vornehmen zu können.

    Es wäre doch wirklich geil, wenn das Betriebssystem auf die Weise Threads switchen könnte!

    Ehrlich gesagt, wüßte ich nicht, wozu das gut sein könnte. :gruebel Zum einen ist kaum genug Speicher vorhanden, um mehrere Programme gleichzeitig laufen lassen zu können. Zum anderen müßte geklärt werden, nach welchem Schema der Taskwechsel vonstatten gehen soll: kooperativ oder präemptiv? Kooperativ setzt vom Programmierer selbst eingefügte Aufrufe einer Systemroutine voraus. Beim präemptiven Wechsel müßten stattdessen zusätzlich alle IO-Zugriffe des Betriebssystems auf Multitasking ausgerichtet sein, d. h. man braucht z. B. sowas wie Mutex, gepufferte IO-Zugriffe mittels Warteschlangen, logisch getrennte Ausgabegeräte (Bildschirmfenster), doch dies würde das System wahnsinnig aufblähen und verlangsamen. Abgesehen davon ist die Ausführung von Bytecode ohnehin schon sehr langsam. Das Teilen des Interpreters mit anderen Programmen würde dann jedes Programm in die Knie zwingen. Dafür bräuchte man dann wohl eine Turbokarte.

    Was den Zugriff auf Systemroutinen anbelangt - und damit das Umschreiben großer Teile des Betriebssystems auf Bytecodebasis -, so könnte man diesen möglichst transparent gestalten. Das bedeutet, daß die Sprache an sich (bis auf wenige Ausnahmen) keine festen Prozeduren oder Funktionen vorgibt, sondern diese gesondert und flexibel definiert werden (mittels include etc). Dabei sollte der Aufrufmechanismus für den User sich nicht unterscheiden von den Aufrufen einer in der Sprache selbst geschriebenen Unterroutine. Ein Interpreter könnte hierzu einen speziellen Befehl "Systemaufruf" verwenden und eine Sprungtabelle zur Verfügung stellen, die idealerweise ins Ram kopiert wird, so daß man sie leicht abändern und neue Routinen ergänzen oder alte durch neue ersetzen kann.

    Nichtsdestoweniger halte ich es für wenig realistisch, heutzutage eine neue Sprache direkt auf dem C64 umzusetzen. Das dürfte an mehreren Faktoren scheitern wie zu langsamer Prozessor (ein Programm zu kompilieren dauert viel zu lange), zu wenig Speicher (es können nur kleine Programme geschrieben werden). Außerdem fehlt dann immer noch jeglicher Komfort beim Erstellen des Programmtextes an sich. Es gibt nicht nur keine IDE, sondern nicht einmal einen Bildschirmeditor, und wieviel Programmtext passen heute in 64 KB? Was ich mir aber tatsächlich sehr gut vorstellen kann, ist, mit Hilfe eines Cross-Compilers auf dem PC Code zu schreiben und mittels eines Bytecodeinterpreters auf dem C64 zum Laufen zu bringen.

    Aber wie man Programmiersprachen designt und implementiert, davon verstehe ich schon mehr.

    In welche Richtung (Design einer Sprache) würdest Du denn da denken?

    BlondMammuth: hast PN.

    Solltest Du bezüglich dessen, was BlondMammuth schrieb in Hinblick auf Spezifizierung, schon weiter sein, würde mich das auch interessieren. (Bin selber nicht ganz unerfahren.)

  • Dazu müßten dann Teile der unteren ZP so umgeschaufelt werden, daß SWEET16 seine Register dort mit unterbringen kann.

    Zwischen BASIC und KERNAL ist die ZP ganz einfach aufgeteilt: alles von $02..$8F gehört zu BASIC und $90..$FA nutzt der KERNAL.

    Die beiden Sätze verstehe ich im Zusammenhang nicht ganz, weil: Wenn der Teil bis $8F$ sowieso dem BASIC gehört, und man genau das rausschmeisst und ersetzt, bräuchte man darauf doch überhaupt nicht mehr achten? Oder meinst du es so, dass man möglichst kompatibel bleiben möchte?

    Ansonsten: Tolle Vision. Ich kenne sweet16 nicht (werds mir aber anschauen), frage mich daher, ob es sich auszahlt, es beizubehalten. Einerseits gäbe es vielleicht die Möglichkeit, noch was besseres hinzubekommen, andererseits hätte man potentiell die Kompatibilität zu mancher SW, die darauf läuft? Und genau das kann ich nicht beurteilen.

    Ich würde aber sagen: Eine VM, egal welche, sollte Plattform für verschiedene Sprachen sein. BASIC V2 würde ich nicht als dringenste Portierung sehen, das gibts eh schon, und sobald jemand Pokes und SYS einsetzt, ist es schon praktisch unmöglich, das Programm automatisch zu portieren. Aber die Grundsprache ohne Pokes und SYS und USR wäre sicher machbar. Nur würde ich DIE sicher nicht im Rom haben wollen, im Gegensatz zur VM selber (die nicht im ROM zu haben erschiene mir so, als müsste man den Prozessor erst reinschrauben). :wink:

  • In welche Richtung (Design einer Sprache) würdest Du denn da denken?

    Alle deine Argumente wiegen recht schwer, insbesondere die Sache mit dem Task-Wechsel und der I/O - wobei man da argumentieren könnte, dass die soweit kein Problem darstellen, soweit sie in derselben VM mit demselben Bytecode laufen. Nur wo wäre das möglich? Man könnte aber auch I/O (ausser vielleicht Joystick) ausdrücklich ausnehmen, wo es zeitkritisch ist.

    Ja, ich gebe zu, das ist so eine nette Idee, nicht all zu leicht zu realisieren. Genau wie virtueller Speicher, etc. Ich würd das in erster Linie innerhalb von Programmen einsetzen wollen, als Threads. Z.B. für Spiele mit mehreren Teilnehmern wäre das vielleicht ein Vorteil (obwohl mir auch da schon wieder Gegenargumente einfallen würden).

    Was die Sprache betrifft, würde ich die möglichst klein und kompakt machen wollen, eher wie FORTH, aber nicht genau so (es muss keine Religion draus werden). Aber da könnte man schon viel einsparen, z.B. wenn man präfix oder postfix verwendet, ist das Parsen viel leichter und schneller (nur für den Fall, dass man es wirklich on board compilieren will. Die von dir angesprochenen Optimierungen würd ich da übrigens ohnehin gar nicht andenken). Für mich denkbar wäre auch die Variante, dass man eine derartige maschinennahe Sprache on board hat, aber offline dann eine größere, optimierende Version davon im cross-compiler. Viel Einfluss hätte diese Frage auch auf die Architektur der VM. Die braucht ja auch nicht unbedingt einem Prozessor mit seinen Registern entsprechen, kann eher Stack-orientiert sein - obwohl das natürlich auch wieder Performance-Nachteile hat.

    Was natürlich immer bleibt, ist das Problem, dass man genau auf kleinen Systemen am meisten optimieren will, und genau dort den wenigsten Platz dafür hat. :wink:

    Jedenfalls wären für mich komplexere Hochsprachen ein Fall für den Cross-Compiler!

    Was die Systemaufrufe betrifft: Ja, sehe ich auch so. Nur gings mir konkret nicht um die Frage, wie man die Systemroutinen aufruft, sondern eher darum, wie die sich dann auswirken. Welchen Speicher brauchen sie, wie sehr unterbrechen sie den sonstigen Programmablauf, was darf man in der Zeit auf keinen Fall anrühren, oder vorher oder nachher, was muss man sichern, welche Interrupts ausschalten, und weiß der Teufel was noch alles. Da kenne ich mich sehr wenig aus, drum kann ich dazu wenig sagen. Ein wenig ist das eh schon beantwortet worden.

  • Eine VM, egal welche, sollte Plattform für verschiedene Sprachen sein.

    Das dürfte voraussichtlich mit SWEET16 nicht gehen. Der Befehlssatz enthält z. B. keine Befehle für Operationen wie Multiplizieren oder Dividieren sowie die bitweisen Integer- und Booleanoperationen UND, ODER und EXKLUSIV-ODER oder Bitverschiebungen << oder >>. Auch gestaltet sich der Zugriff auf lokale Variablen sehr umständlich. Die Bytecodeinterpreter von UCSD-Pascal oder Java verwenden je nach Höhe des Offsets 1 oder 2 Bytes (oder mehr) für einen Befehl zum direkten Lesen des Wertes. EIn SWEET16-Programm müßte zunächst zur Stackadresse die Offsetadresse addieren und könnte erst danach den Zugriff vornehmen. Zuletzt handelt es sich um eine Registermaschine mit einem Akkumulator und keine Stackmaschine. Bei der Stackmaschine wird eine Operation immer auf die letzten beiden Stackwerte angewendet und benötigt dafür nur ein Byte für die Operation. Beim SWEET16 muß zunächst der Wert in den Akku geladen, dort die Operation angewendet und dann u. U. auch zurückgeschrieben werden. Es liefe am Ende darauf hinaus, die Register nach dem Stackprinzip einer Stackmaschine zu belegen. Kurz gesagt: Für einen Interpreter, der sich auch für andere Sprachen eignen soll, sei es aus der C- oder Pascalfamilie, wäre ein gezielt dafür entwickelter Interpreter wie der von UCSD-Pascal oder Java bei der Programmausführung voraussichtlich schneller (weil das Programm kürzer und die Befehle mächtiger sind), wenn auch vom Umfang um einiges größer (ca. 3 KB ohne Fließkommapaket und Systemroutinen).

  • SWEET16 ist eine VM, die auf einem 6502 einen 16-Bit-Prozessor nachbildet.

    Dieser hat 16 Register mit je 16 Bit und dazu braucht es in der Zeropage einen zusammengehörigen Block von 32 Bytes. Diesen Block müßte man dadurch gewinnen, daß man "unkritische" ZP-Bytes in den Bereich $0200..$03FF auslagert. Dadurch brauchen die entsprechenden Befehle im BASIC-Interpreter natürlich direkt 3 statt 2 Bytes.

    Dann pickt man sich gute Kandidaten aus dem BASIC-ROM aus, die man nach SWEET16 übersetzt. Müssen gar nicht so viele Routinen sein (und am besten nur solche, die geschwindigkeitsmäßig ohnehin unkritisch sind) so daß man in der Summe wieder soviel einspart, daß SWEET16 mit ins ROM paßt.

    Die Einsprünge ins BASIC-ROM sind dann logischerweise für die Fisch, aber dafür wird der Coder eben mit einem 16-Bit-Prozessor entschädigt und kann neue Programme sicher auch auf "umgelegte" Routinen umschreiben.

    Sobald der Prototyp aber läuft, gibt's dann sicher die Möglichkeit, das BASIC-ROM noch weiter einzudampfen - wie gesagt, am besten so, daß der Geschwindigkeitseinbruch minimal bleibt. Und dann kriegt man neben SWEET16 vielleicht auch noch für's BASIC nette Zusatzfunktionalität wie ein IF ... THEN ... ELSE untergebracht.

  • Bitte melde dich an, um diesen Link zu sehen.

    Da bastelt auch jemand an sowas.

    Was ich mich frage: welche Art Software wollt ihr damit schreiben? Ich bin ja Fan von 'ernsthafter' Software, also habt ihr meine Sympathie. Aber 90% der c64 Software waren halt Spiele, und da würde ein Taskwechsel das Timing schon komplett durcheinander bringen.

    In der Run64 (wimre) war mal ein Multitasking Basic als Listing drin. Vielleicht hilft euch das?

  • wenn man präfix oder postfix verwendet, ist das Parsen viel leichter und schneller

    Nicht wirklich. Das Parsen von Ausdrücken ist nur ein kleiner Teil des Compilers. In Pascal gibt es nur 4 Stufen in der Abarbeitungshierarchie und damit auch nur 4 Prozeduren für die Analyse eines Ausdrucks: getexpression (Vergleiche), getsimple (Addition, Subtraktion, ODER), getterm (Multiplizieren, Dividieren, AND) und getfactor (Konstanten, Variablen, Funktionsaufrufe sowie NOT). Ob man die Analyse nun als rekursive Aufrufe dieser Prozeduren gestaltet oder eine Postfix-Notation in der Sprache voraussetzt, macht für den Compiler keinen großen Unterschied. Wichtiger beim Parsen von Ausdrücken ist eher die Unterscheidung der Datentypen (+ bei Integer, Fließkomma, Strings oder Chars), gegebenenfalls Optimierungen (X * 1 = X, X * 0 = 0) und das andauernde Testen auf irgendwelche Fehler im Code.

    kann eher Stack-orientiert sein

    Stackmaschinen haben den Vorteil, daß die Codeerzeugung wesentlich leichter und der erzeugte Code trotzdem recht kompakt ist.

    Was die Sprache betrifft, würde ich die möglichst klein und kompakt machen wollen

    Eine Sprache, die sehr klein und kompakt ist, wäre Oberon (Nachfolger von Pascal, aber mit verbesserter Syntax und auch leichter zu parsen als Pascal, weil einige Elemente entfernt wurden).

  • Das vorstehende ist sicher richtig; die Einfachheit von Oberon an sich überzeugend;
    jedoch gebe ich zu bedenken: Gerade Oberon ist keine Interpretersprache - eignet es sich hierfür?

    Die Merkmale "von mehreren Personen kann an einem Projekt gearbeitet werden" sowie weitgehende Objektorientierung scheinen mir wiederum 2 Schuhnummern zu groß zu sein für ein 8 bit-System.

  • NIcht zwangsläufig - Mehrbenutzersysteme auf 8Bit-Basis sind ein alter Hut: Bitte melde dich an, um diesen Link zu sehen. (gab da noch andere, zum Teil proprietäre) - Objektorientierung wird's auf 8bit eher nicht geben, weil der Hype erst nach der 8Bit-Ära begann. Wenn man das Thema Objektorientierung etwas lockerer sieht: man kann auch in C objektorientiert programmieren und das gab's auch schon in den 80ern.

    Wissen ist das einzige Gut, das sich beim Teilen vermehrt. Also seid vorsichtig damit!

  • Gerade Oberon ist keine Interpretersprache - eignet es sich hierfür?

    Als Scriptsprache auf dem C64 sicherlich nicht. Als kompiliert nach Bytecode für eine simple Stackmaschine ist dies kein Problem.
    Persönlich würde ich auch nicht Oberon nach dem von Wirth definierten Standard nehmen. Der gute Wirth hat es da in einigen Punkten reichlich übertrieben mit seiner Blockstrukturierung. So würde ich die "loop"-Anweisung aus Modula-2 beibehalten zusammen mit einer "break"- und "continue"-Anweisung vergleichbar zu C. "Goto" sollte auch möglich sein. Und daß es bei Funktionen nur ein "return" geben darf am Ende der Funktion so wie im letzten Report beschrieben, ist natürlich Blödsinn. Was die Objektorientierung anbelangt, bräuchte man eventuell ein besseres syntaktisches Konstrukt als den Weg über die Record-Struktur.
    Dies alles verlangt natürlich nach einem Cross-Compiler auf dem PC, denn sowas wäre mit den begrenzten Ressourcen des C64 nicht zu leisten. Wichtig bei der Umsetzung auf dem C64 wären dann andere Dinge.
    Bei UCSD-Pascal gab es z. B. das Konzept von Segmenten. Das waren gesondert gekennzeichnete Prozeduren oder Funktionen, die beim Aufruf transparent vom System von Diskette nachgeladen wurden. Zusätzlich gab es spezielle Segmente, die als Bibliothek fungierten (z. B. Turtlegraphics). Sollte man (unabhängig von der Hochsprache) solch ein Segmentsystem nachahmen oder eher es dem Compiler überlassen, Bibliotheken beim Kompilieren per include einzubinden und zusammen mit dem sonstigen Programmcode von Fall zu Fall zu optimieren (z. B. indem nicht verwendete Bibliotheksroutinen oder -variablen rausgeschmissen werden)?
    Eine weitere Frage wäre, wie man auf Systemvariablen zugreifen soll. Per Get-Set-Routinen wäre etwas langsam und umständlich. Wie kann man diese also in den Adressraum der virtuellen Maschine einblenden?
    BlondMammuth: Vielleicht hast Du dazu Ideen und Vorschläge?

    welche Art Software wollt ihr damit schreiben?

    All das, was man vorher schon in BASIC geschrieben hat. Ernsthafte Anwendungen, aber auch Adventures, Strategie- oder Rollenspiele (wie "Die dunkle Dimension"). Wenn man dem Benutzer erlaubt, eigene Assemblerunterroutinen einzubauen, kann man auch andere Programme mit hinzunehmen. So wäre es möglich, einen Titelvorspann oder ein Menü eines Spiels in der Sprache zu schreiben und dann für den Arcadeteil eine Unterroutine in Assembler. Der Trick besteht gerade darin, daß nicht alles in der Hochsprache geschrieben sein muß, sondern nach Belieben z. B. optimierte Grafikroutinen in Assembler ergänzt werden können.

    ...
    ...
    Kann es sein, daß das alles hier jetzt völlig offtopic ist...? :schande:

  • Bitte melde dich an, um diesen Link zu sehen.

    Stackmaschinen haben den Vorteil, daß die Codeerzeugung wesentlich leichter und der erzeugte Code trotzdem recht kompakt ist.

    Eine Sprache, die sehr klein und kompakt ist, wäre Oberon (Nachfolger von Pascal, aber mit verbesserter Syntax und auch leichter zu parsen als Pascal, weil einige Elemente entfernt wurden).

    Ja, mir gings eben genau darum, dass Stack-Maschinen es wesentlich vereinfachen, weil z.B. Optimierungen im Bezug auf Registerbelgungen (graph coloring etc.) wegfallen. Das bedeutet natürlich, dass auch die Möglichkeit dazu wegfällt, ergo bleibt mehr an aufzuwendender Intelligenz beim Programmierer hängen. Die Philosophie wird auch eine solche bleiben müssen. Je näher die Sprache an der Zielmaschine dran ist, desto leichter ist jeder Compile-Vorgang.

    Das bringt mich noch einmal zur Syntax-Frage. Klar, wenn ich einen mehr-Pass Compiler schreibe, der aufgerufen wird, um ein ganzes Programm zu compilieren, dann hast du völlig recht. Das macht dann wenig Unterschied. Was mir vorschwebt (und so richtig habe ich das grade erst jetzt eingeordnet) ist ein Compiler, der kleine Elemente des Programms (z.B. Funktionen in der Größe von Programmzeilen) bei der Eingabe direkt compiliert, so dass sie unmittelbar lauffähig sind. Und die könnten, wenn die Darstellung dem Code nahe ist, auch wieder per "List" o.ä. in Echtzeit zurückverwandelt werden.

    Extern kann man dann andere Programmiersprachen in diese Notation übersetzen.

    Und jetzt denke ich grade wieder nach, ob so ein Konzept das Design einer VM nicht hoffnungslos überfordern und ineffizient machen würde. :wink:

  • ein Compiler, der kleine Elemente des Programms (z.B. Funktionen in der Größe von Programmzeilen) bei der Eingabe direkt compiliert

    Hmm... Dafür bräuchtest Du eine Sprache, die syntaktisch direkt darauf zugeschnitten ist. Muß man Deklarationen von Bezeichnern vorher eintippen? Oder müßte man bei den Bezeichnern vergleichbar mit Basic an den Namen eine Kennung hinzufügen, anhand der der Tokenizer erkennen kann, ob es sich beim Bezeichner um eine Konstante, Variable, Prozedur oder Funktion handelt und welchen Typ sie jeweils hat? Woher weiß er, ob es z. B. eine lokale oder globale Variable ist? (Noch eine Kennung?) Was macht der Tokenizer, wenn er auf einen Bezeichner trifft, den er noch nicht kennt? Wie und wann bestimmt er die dazugehörige Adresse bzw. den Offset? Müssen die Namen aller Bezeichner (auch der lokalen) ständig im Speicher abgelegt sein? Was genau wird bei der Eingabe kompiliert? Was ist mit Kontrollstrukturen wie einer FOR- oder WHILE-Schleife, dessen Ende erst irgendwann später kommt? Was passiert, wenn ein Unterroutinenaufruf sich auf mehrere Zeilen verteilt:

    Code
    unterprogramm(	paramater_1,
    			parameter_2,
    			parameter_3)

    Und so weiter. Offen gesagt befürchte ich, daß das Konzept einer zeilenorientierten Eingabe einer Hochsprache mit wenigen Ausnahmen (vielleicht Lisp?) nur schwierig umzusetzen wäre und dem Benutzer zu starke Restriktionen auferlegt.

  • Eine weitere Frage wäre, wie man auf Systemvariablen zugreifen soll. Per Get-Set-Routinen wäre etwas langsam und umständlich. Wie kann man diese also in den Adressraum der virtuellen Maschine einblenden?
    BlondMammuth: Vielleicht hast Du dazu Ideen und Vorschläge?

    Gute, vor allem schon viel zu spezifische Frage in dem Stadium. :smile:

    Meine erste Idee wäre, die virtuelle Maschine mit einem "normal", und einem zusätzlichen "absolut"-Adressierungsmodus auszustatten, wenn es um solche Addresen geht (habe ich das richtig verstanden?). Sicher wäre das natürlich nicht, aber ehrlich - so ehrgeizig bin ich nicht. Wer sich dann immer noch durch wahlloses "Poken" in den Fuß schießen will, sollte die Freiheit auch genießen dürfen. :wink:


    All das, was man vorher schon in BASIC geschrieben hat.

    Sehe ich genauso. Vor allem: Wenn man eine VM hat, die von mehreren Sprachen angesteuert wird, und auch jederzeit Assembler aufrufen kann, dann ist der Normalfall schon wesentlich schneller als BASIC, und das wäre das Pendant zum BASIC V2: Nur komfortabler und flexibler und programmierfreundlicher. Und dann halt Assembler, wobei, wenn man es richtig macht, vieles auch so besser unterstützt wird, und oft, wo heute noch notwendig, dann nicht mehr nötig ist.

    Ein cross-Compiler von VM auf 6502 wäre auch vorstellbar, der dann theoretisch in alle Compiler bis in die Hochsprache durchgezogen werden kann. Man markiert die Teile, die man direkt in Assembler haben will, und so bekommt man es dann auch. Müsste eigentlich gehen.

    Kann es sein, daß das alles hier jetzt völlig offtopic ist...?

    Ich genieße diesen Thread grade so sehr, dass ich daran gar nicht denken will! :smile: Aber ich finde das garnicht so sehr. Die Frage war doch: Was könnte man in 8k alles unterbringen? Naja, da sind wir mit der Idee einer VM und kompaktem Byte-Code doch noch immer, oder nicht?

  • Hmm... Dafür bräuchtest Du eine Sprache, die syntaktisch direkt darauf zugeschnitten ist. Muß man Deklarationen von Bezeichnern vorher eintippen? Oder müßte man bei den Bezeichnern vergleichbar mit Basic an den Namen eine Kennung hinzufügen, anhand der der Tokenizer erkennen kann, ob es sich beim Bezeichner um eine Konstante, Variable, Prozedur oder Funktion handelt und welchen Typ sie jeweils hat? Woher weiß er, ob es z. B. eine lokale oder globale Variable ist? (Noch eine Kennung?) Was macht der Tokenizer, wenn er auf einen Bezeichner trifft, den er noch nicht kennt? Wie und wann bestimmt er die dazugehörige Adresse bzw. den Offset? Müssen die Namen aller Bezeichner (auch der lokalen) ständig im Speicher abgelegt sein? Was genau wird bei der Eingabe kompiliert? Was ist mit Kontrollstrukturen wie einer FOR- oder WHILE-Schleife, dessen Ende erst irgendwann später kommt? Was passiert, wenn ein Unterroutinenaufruf sich auf mehrere Zeilen verteilt:

    Code
    unterprogramm(	paramater_1,
    			parameter_2,
    			parameter_3)

    Und so weiter. Offen gesagt befürchte ich, daß das Konzept einer zeilenorientierten Eingabe einer Hochsprache mit wenigen Ausnahmen (vielleicht Lisp?) nur schwierig umzusetzen wäre und dem Benutzer zu starke Restriktionen auferlegt.


    Alles richtig. Ich meinte nicht so sehr "echte" Zeilen, sondern eher kleine Happen zu viellicht maximal 255 bytes? Das könnten ja auch sowas wie "screens" wie in Forth sein. Namentliche Definitionen, die sich rein syntaktisch über mehrere Zeilen erstrecken können.

    Ob man die Namen von Parametern beibehält, oder von globalen Variablen? Gute Frage.

    Einerseits kann ich mir vorstellen, dass man tatsächlich Variablen und Funktionen schon beim Editieren generell nicht an Zeilennummern sondern an Identifier hängt. Dann müssten diese Identifier gespeichert sein, solange man das Programm entwickelt. Man könnte dann mit einem Befehl alles mit Identifier speichern, um weiter zu entwickeln/debuggen, und eben auch ohne als reine Ablauf-Variante, mit Ausnahme derer, die man nach aussen exportieren will. So kann man es als Lib wieder einbinden auch. Die Identifier würden generell im Code sowieso durch Indizes ersetzt, die beim Listen - falls vorhanden - wieder durch die entsprechenden Identifier dargestellt werden. Wie man das im Speicher organisiert, ist eine eigene Frage.

    Die Typ- und Scope-Frage ist wichtig. Man könnte vielleicht zwei oder drei Bits dafür verwenden, denn 65536 Definitionen werden es auf dem C64 eh niemals. 8192 Definitionen pro Programm sind ohnehin schon herzlich viel, und grade bei lokalen (Stack)-Definitionen brauchts eher noch weniger. Da könnte man insgesamt die Byte-Größe auch noch rein kodieren. Natürlich habe ich da noch nicht die möglicherweise gleichnamigen Definitionen in verschiedenen Scopes mit einbezogen. Da müsste man noch drüber nachdenken.

    Andererseits bräuchte man beim Aufruf, besonders, wenn man stack orientiert ist, vielleicht eh keine solchen Klammerausdrücke. Aufruf mit dem, was grade auf dem Stack ist, reicht. Aber das Argument gefällt mir nicht so gut. Man kann theroetisch diese Klammern auch als Ausdrücke auffassen, die jederzeit auch ohne Aufruf dort stehen können.

    Kontroll-Strukturen? Naja, man kann sie vielleicht gleich operational abbilden? Oder man lässt da doch ein wenig mehr an Syntaxanalyse zu? Jedenfalls ein guter Einwand! Vielleicht kann man verlangen, dass eben solche Schleifen nur eine gewisse Größe haben dürfen (so groß wie eine Definiton halt), und wenn man mehr braucht, eine eigene Funktion definieren muss. Mit einem "inline"-Tag beim Aufruf wäre das sogar expandierbar, aber im Grunde will man auf der Plattform doch eh lieber Platz als Rechenzeit sparen.

    Sind alles nur so Überlegungen, aber sie machen echt Spaß! :smile:

    PS: Das Feedback macht auch viel Freude, danke! Denn so merke ich am schnellsten, wo ich auf dem Holzweg bin oder schlicht zuwenig weiß!

    Hier könnte meine Signatur stehen, wenn ich eine hätte.

    Einmal editiert, zuletzt von BlondMammuth (22. Mai 2017 um 00:12)

  • Man markiert die Teile, die man direkt in Assembler haben will

    Puuh, Du meinst also einen on-the-fly Wechsel des Backends? Knifflig... Was den erzeugten 6502-Code anbelangt, so dürfte der ähnlich aufgebläht ausfallen wie beim C65 oder gcc. Problematisch sind immer diese Konstrukte, die man in Hochsprachen so gerne findet wie lokale Variablen, da die Zugriffe nicht so einfach umzusetzen sind bzw. viele Befehle brauchen.

    Für letzteres sollte man vielleicht aus Platzgründen eine Unterroutine verwenden, aber dann ist man nicht mehr weit von der Geschwindigkeit eines Bytecodeinterpreters entfernt.

    Naja, da sind wir mit der Idee einer VM und kompaktem Byte-Code doch noch immer, oder nicht?

    Hoffentlich. Falls nicht, darf ein freundlicher Mod natürlich diesen Teil in einen eigenen Thread auslagern. ;)

  • Was den erzeugten 6502-Code anbelangt, so dürfte der ähnlich aufgebläht ausfallen wie beim C65 oder gcc.

    Glaub ich auch. War auch nur eine Neben-Idee. Um Assembler als Option wird man da nicht herumkommen.

  • Kann man die ganze Sache nicht einfach auf eine Cartridge packen und gut is? So á la SimonBasic mit samt Compiler?

    Liebe Grüße!
    ThomBraxton

  • Kann man die ganze Sache nicht einfach auf eine Cartridge packen und gut is? So á la SimonBasic mit samt Compiler?

    Liebe Grüße!
    ThomBraxton

    Zur Zeit kann man sie in ein nettes Märchenbuch packen, denn mehr als die Ideen und Gedanken gibts dazu ja erst einmal nicht. :wink:

    Nachtrag (das mit dem "Hirn vorher einschalten" und "sinnerfassend lesen" muss ich noch ein wenig üben):

    Ich bin da kein Experte, aber da viele Betriebssystem- und sonstige Spracherweiterungen auf Cartridge gepackt worden sind, würde ich einmal stark davon ausgehen. An die Experten hier: Wieviele KB gehen denn auf sowas drauf, und wie siehts mit dem Addressraum grundsätzlich aus?

    Hier könnte meine Signatur stehen, wenn ich eine hätte.

    Einmal editiert, zuletzt von BlondMammuth (22. Mai 2017 um 15:46)

  • Ein Cartridge kann so viel Speicher haben wie man will, da man per Bankswitching immer wieder neue Bänke einblenden kann. DARAN würde es also nicht scheitern :D .

    ────────────────────────────────────────────────────────────
    Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen.
    ────────────────────────────────────────────────────────────