Optimierungsgrad KERNAL /BASIC - fiktiver Talk

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

  • Au, weh, Stephan, daß deine Statistik über alle möglichen Einsprungpunkte zum Scheitern verurteilt ist - nun, dazu muß man nicht unbedingt den ganzen Korpus an existierenden C64-Programmen durchsuchen. Ein spezielles, gut funktionierendes und sinnvoll einsetzbares Gegenbeispiel reicht: Paradoxon-BASIC.

    Der Loader von PB "schiebt" den BASIC-Interpreter unter I/O und der ersten Hälfte des KERNAL-ROMs. Dabei wird in etwa *jeder* Sprung-Befehl und alle anderen absoluten Adreßangaben (z.B. die Zieladressen beim Token-Dispatch, etc.) anhand einer *großen* Tabelle so umgepatcht, daß das BASIC dann ab $D000 im RAM laufen kann. Zusätzliche Routinen sorgen für das jetzt notwendige Bank-Switching, zum Schluß wird das ganze sogar noch durch eine BASIC-Erweiterung abgerundet und man bekommt 51199 BYTES FREE.

    Mein Multiplikations-Patch arbeitet nur deswegen erfolgreich mit PB zusammen, weil erstens der betroffene Sprung-Befehl immer noch an der gleichen Stelle steht, dort anhand der Patchtabelle lediglich das High-Byte der Zieladresse angepaßt wird (mit konstantem Offset!) und die "Aufrufkonvention" der Zielroutine die gleiche ist - sie springt mit einem RTS zurück, genau wie das Original, und nicht etwa mit einem ("neuen") JMP, der bliebe dann nämlich ungepatcht!

  • *räusper*

    darf ich dich darauf aufmerksam machen, dass es in den letzten Stunden / Tagen darum ging, eine Art "ultimative" Neu-Implementierung von BASIC zu erschaffen?

    Sozusagen ein "Orthodoxon-Basic".
    :)

    Stillschweigend vorausgesetzt ist damit, dass man dann kein anderes (Paradoxon-)Basic mehr braucht,
    bzw. weil der Zweit-C64 ROM-mäßig dank des "neuen Basic" (das supertoll werden wird :) ) sich selbst genügt...
    Kompatibilität zu mancherlei , dies das und jenem wünschenswert, aber kooperative Einsprungverträglichkeit zu einem alternativen Basic-Aufsatz wohl am allerwenigsten..


    Zitat von Mike

    Statistik über alle möglichen Einsprungpunkte

    ähm ... - - wieso alle?
    ich wiederhole mich bedarfsfalls auch noch öfters:
    es kann hier keineswegs F.D.P.-mäßig um Maximalziele (a la "Projekt 18%" oder "mehr netto vom brutto") gehen, sondern wiederum nur um eine Statistik über die meisten /hinreichend /genügend viele Einsprungpunkte".

    Wie kommst du denn darauf, dass jemand "alle" möglichen Einsprungpunkte abdecken will? :anonym
    ;(

  • Ganz einfach gesagt: wenn so ein "Monstrum" wie Paradoxon-BASIC sich am Interpreter zu schaffen macht, kann praktisch keinerlei Änderung des Interpreters toleriert werden. Es wird anderseits auch eine Menge Programme geben, denen Änderungen am Interpreter überhaupt nichts ausmachen (und sei es nur deswegen, weil sie ihn ohnehin nicht benötigen oder halt wegblenden).

    Und dazwischen hast Du halt ein Kontinuum an wegbrechender Kompatibilität zu Maschinenprogrammen (speziell hier: BASIC-Erweiterungen oder -Compiler, oder Direkteinsprünge in die Fließkommaroutinen, etc.) je mehr am Interpreter geändert wird. Das ist doch ganz klar.

    In meinem Manifest hatte ich darum auf diese Kompatibilität zu Maschinenprogrammen unausgesprochen auch gar keine Rücksicht mehr genommen; der Geschwindigkeitsgewinn an sich und ggfs. zusätzliche Features im Sinne einer zuvor erforderlichen BASIC-Erweiterung für Grafik, Sound, DOS-Befehle, Monitor, etc. sollten diesen Aspekt in den Hintergrund rücken lassen. Ich hatte mir auch keine Illusionen darüber gemacht, daß dieses erweiterte und verbesserte BASIC zusammen mit dem KERNAL immer noch in 16K unterzubringen wäre.

    Eher wäre so etwas wie BASIC 7.0 dabei herausgekommen, nur halt mit verbessertem "Unterbau" und z.B. einem CIRCLE-Befehl, der keine Eier zeichnet...

  • eine kritisch-konstruktive Korrektur (KKK) bzw. Kommentierung werde ich aushalten müssen


    Ich auch. ^^:bia

    ich möchte zu bedenken geben, dass die Emulatoren heutzutage tiefreichende Möglichkeiten eröffnen; z.b. im laufenden Betrieb Daten auswerfen, wie oft ein bestimmter Einsprungpunkt (oder sogar TRAP im emulierten Rom) benutzt wird in Relation zu allen übrigen; auch gibt es "just-in-time 6502-Emulatoren bzw. just-in-time dynamische Rekompilierung" (ich glaube aus der Ecke "Farbrausch" / bero), denen nur noch eine Schnittstelle zum Statistik-Export fehlt (den man dann noch "aufsammeln" bzw. "Abmelken" müsste).


    Interessanter Gedanke. Allerdings müßte ich hier anmerken, daß eine Emulation, d. h. das Ausführen des Programms, auch jemanden voraussetzt, der es im laufenden Betrieb bedient. Man bräuchte also noch so etwas wie eine Liste der nötigen Tastendrücke oder Joystickbewegungen, um das Programm wirklich in jeden Winkel hinein austesten zu können. Übertrieben gesagt: Was macht man, wenn ein Sprung erst am Ende des vierten Levels beim Endgegner nach Nachladen des auf dem Datenträger komprimierten Programms auftaucht? Das reine Ablaufenlassen eines Programms garantiert nicht, daß tatsächlich alle Verzweigungen durchlaufen werden. Da gibt es technisch gesehen viel zu viele potentielle Seiteneffekte, um sie durch statische Codeanalyse oder zufälliges, zielloses Drücken von Tasten alle herauszufinden. (Okay, ich übertreibe hier wohl ein wenig bezüglich der Komplexität der C64-Programme. Ich hab halt generelle Bedenken gegen einen solchen Ansatz, da er meiner bisherigen Erfahrung mit Softwareaufbau und -analyse widerspricht. Ich lasse mich aber gerne vom Gegenteil überzeugen.)

    Auch spricht m.E. nichts dagegen, in einem fortschrittlichen Analyseprogramm das Umfeld vor jedem RTS in den Zielprogrammen zu untersuchen, ob da bestimmte Muster von PHA auftauchen, z.b. paarig, und dazwischen der Kontrollfluss recht zielstrebig auf das RTS (oder auch RTI) zu-eilt.

    Stimmt. Dagegen spricht nichts. Nur a) ist das schon nicht mehr ganz trivial, b) wird es dann immer noch nicht ausreichen. Woher soll denn die automatische Analyse wissen, welche konkrete Adresse auf den Stack gebracht wird? Wie ist das mit solchen Programmen:

    Code
    lda	(bytecode), y
    		asl
    		sta	.jump + 1
    .jump:		jmp	(jumptabelle)


    Woher weiß das Analyseprogramm, welche der dort gelisteten Sprünge wirklich relevant sind? Es gibt einfach zu viele Möglichkeiten, indirekte Sprünge zu realisieren, als daß man sie alle mal eben so in das Analyseprogramm einbauen könnte. Das Grundproblem ist hierbei, daß eine Turingmaschine eine andere zwar emulieren kann, aber dadurch keinen Einblick erhält in die Struktur des emulierten Programms, besonders dann nicht, wenn auch noch rückbezügliche, d. h. selbstmodifizierende Befehle hinzukommen. (Erst neulich hatte ich ein ansonsten recht einfaches Programm in den Händen, welches nur zu einem ganz bestimmten Zeitpunkt eine Kopierschutz-Unterroutine dechiffriert, anspringt und anschließend wieder verschlüsselt.)

    Klar ist es möglich, dass dann irgendwann Programme die mit STA 0104,X auf den Stack schreiben, (oder schlimmer, indirekt über ZP-Zeiger) einem Analysetool zunächst durch die Lappen gehen -

    Gerade die Verwendung von Zeigern in der Zeropage ist meiner Beobachtung zufolge sehr, sehr häufig anzutreffen.

    andererseits kann man auch eine (Scheinbarer-)Dead-Code-Erkennung einbauen, die dann zur gezielten Nachbearbeitung von Code-Abschnitten auffordert, die "scheinbar" nicht angesprungen werden.

    Uff, wenn das so einfach wäre. Dazu muß man dem Analysetool beizubringen versuchen, zwischen Code und Daten zu unterscheiden. Nicht trivial. Könnte mittels einer statistischen Musterhäufigkeitsanalyse geschehen, wäre aber alles andere als sicher. Zudem war es früher üblich, daß in einzelnen Programmteilen Reste von altem Code übrig blieben, die dann fälschlich als Code eingestuft werden könnten etc. Dummerweise sind ausgerechnet die alten Programme die schlimmsten, weil die Entwickler noch keine umfangreichen (Cross-)Assembler verwendet haben. Alter Code besteht oftmals aus einem grausamen Haufen Spaghetti quer über den ganzen Speicher verstreut und mit alten Coderesten durchsetzt, daß einem schon beim Angucken davon blöde im Kopf wird. Und ausgerechnet diese Programme sind oftmals diejenigen, die besonders häufig von Romroutinen gebrauch gemacht haben...

    Die Entwicklung solch eines Analysetools wird mancherlei zutage fördern an verschrobenen Techniken; andererseits lässt es sich ja erweitern. (mit den Aufgaben wachsen)

    Sicherlich, doch wer sollte das schreiben? Sorry, aber meiner Meinung nach ist der Aufwand einfach viel zu groß und steht in keinem Verhältnis zum Nutzen. Semantische Analyse eines Assemblerprogramms ist kein Zuckerschlecken und erfordert viel Zeit und Gehirnschmalz. Freiwillige vor.

  • Klar, große Änderungen sind wegen Kompatiblität nicht sinnvoll und der Nutzen eines neuen Interpreters in heutigen Zeiten eh gering, wo man auch am PC mal eben was Cross machen kann. Aber als Gedankenspiel für Verbesserungspotentiale finde ich das doch großartig.


    Hier ähnlich Mikes Manifest mal ein paar Ideen für ein "alternatives" Basic.
    So Wahnsinnig viel anders würde ich letztlich gar nicht machen, das bleibt alles viel dichter am vorhandenen Basic und am Editor als an Alternativen, wie sie im Speccy oder QBasic stecken. Wie das Basic von den alten Ataris aussieht weiß ich nicht.

    Es bleibt also dabei: Eine Zeile im Textformat kommt von irgendwo her und wird tokenisiert. Fängt sie mit einer Ziffer an, wird sie der Basic-Verwaltung übergeben, sonst kommt noch ein Endezeichen ran, und die Zeile wird ausgeführt. Zeilen werden also einfach so vom Editor in die Zeilenverwaltung gepusht.
    LIST gibt das Programm irgendwohin aus, auch da gibt es keine weitere Verbindung zum Editor. Das Speccy-Konzept, die Tastatureingabe mit dem Tokenisieren zu verbacken gefällt mir nicht, und ein "richtiger" Editor scheint mir doch etwas mehr Speicher zu brauchen.

    ABER: Da sollten unbedingt Basic-Befehle/Unterprogramme her, die eine Basic-Zeile lesbar in einen String schieben, umgekehrt einen String wieder tokenisieren, den String ausführen oder im Programm ablegen!

    Es wird wohl kaum ohne das Umwandeln von Codes zwischen Tastatur, Screen und Petscii gehen, da man im Code eh Strings mit Steuerzeichen braucht. Das könnte man jetzt ganz oder gar nicht machen, also beide von 0 bis 35 mit 0-9 und den Buchstaben belegen, weil das für Monitore und Zahlenausgabe nützlich wäre. Aber lieber wäre mir ein engeres Anlehnen beider Codes an Ascii, das ist man gewöhnt.

    Es sind einige Parteien im Spiel:
    -Interpreter: Speicherbedarf und Speed.
    -Tokenisierer/Editor: Speicherbedarf
    -LIST-Befehl: Speicherbedarf.
    -Und das Programm und Variablen wollen auch noch Speicher und machen Verwaltungsaufwand im Code.

    Wenn man dem Interpreter das Leben leicht machen will, schiebt man mehr Aufgaben an die anderen, was aber Speicher frisst.
    Sonderwürste einzelner Befehle müssten in Editor, List-Befehl und Interpreter berücksichtigt werden, das könnte vom Platzbedarf her schnell in die Hose gehen.
    Da ich eh schon ein paar mehr Sachen haben will muss ich mehr Kompromisse für kleine Code-Größe eingehen, während diverse Ideen aus Mikes Manifest schneller wären, aber mehr Code brauchen und das Programm vergrößern.

    Auch würde ich es so lassen, dass während der Ausführung die Befehle entscheiden/wissen müssen, welche Parameter sie erwarten und wie sie auf Folgezeichen reagieren. Sonderwürste im Tokenisieren einzelner Befehle gibt es ja heute glaub ich nicht, und sollte es auch künftig nicht geben. Die Tabelle mit den Befehlswörtern wird gebraucht, sonst imho aber nur ein bisschen Wissen zum internen Aufbau des Programms, aber nicht für einzelne Befehle.

    Selbst Variablen würde ich (fast) genau so dynamisch ablegen, wie es heute gemacht wird.

    Innerer Aufbau
    -Ein System ohne Zeilennummern und stattdessen mit Labeln wäre schön. Würde das Speichern von Zeilennummern sparen, aber sicher viel mehr Aufwand für den Editor bedeuten. Und Fortwärts-Referenzen auf Label wären auch ein Problem. Daher System mit Zeilennummern beibehalten.

    -Anderer Speicheraufbau: Ein Bereich für Zeilennummern + deren Adressen, ein Bereich für das eigentliche Programm.
    => Schnellere Suche von Zeilen, normaler Programmablauf kann einfach über alles hinweg aus dem Programmbereich lesen, quasi endlos lange Zeilen denkbar.
    => kein Binär/Token-Ascii-Misch im Programmbereich, für die Klammern [] und andere Suchen innerhalb des Textes nützlich. Programmbereich wird etwas kürzer.

    -Ich hätte gerne eine Hauptschleife, die mit JSR ab einem Pointer genau einen Befehl ausführt, z.B. für Debugger und um auch aus Assembler heraus ein bisschen Basic aufrufen zu können.
    => Macht imho einen Software-Stack für While/Wend, For/Next und so nötig. Schwer zu sagen, ob das gut oder schlecht ist...

    -Variablen wie gehabt, ein Speicher, wo alle nacheinander mit Namen und so abgelegt werden.
    -Im Detail aber 11 Bit für den Namen (36*36 Möglichkeiten), 1 Bit als Array-Flag, 4 Bit für Datentypen.
    -Außerdem alle mit variabler Länge, wo heute alle auf 5 Byte plattgemacht wird. Sonderbehandlung für Längen wird für Arrays eh gebraucht.

    Sprache
    -Ich hab probiert, heute übliche Befehle für strukturiertes Programmieren einzubauen. Also ELSE, LOOP und möglichst ohne GOTO.

    -Zeilenenden sind nicht wichtig, das Nullbyte fällt weg. Zeilennummern sind nur Sprungziele für GOTO und GOSUB. Zwar hasse ich das, ein Trennzeichen am Zeilenende zu setzen, ist aber für die Interpreterschleife nützlicher.
    -REM überliest einen folgenden Ausdruck, sollte also nützlicherweise von einem String gefolgt werden. Weitere Befehle in gleicher Zeile sind möglich! Ergibt sich so, weil Zeilenenden nicht wichtig sein sollen.
    -Mehrere Befehle in Klammern [] zu setzen ist heute üblich und bei IfThenElse sehr nützlich, ohne Klammern ist dort Schachteln schmerzhaft.
    -Ohne Zusammenhang mit anderen Befehlen ist [] eine Endlosschleife. Bei Platzmangel fällt das weg.
    -Die Klammer [ legt noch ihren Typ und weiteres auf einen Stapel. Ermöglicht mit WHILE etwas strukturierte Programmierung und beschleunigt solche Loops.
    -FOR-Schleifen würde auch in dieses Klammerkorsett gepresst. Aber mehr technisch als optisch.
    -Doppelpunkt bleibt Trennzeichen für Befehle,ist aber fast optional, [] wirken auch als Befehlstrenner. Generell könnte nach vielen Befehlen das Trennzeichen entfallen.
    -Space optional fürs Formatieren.
    -Wie gehabt: Taucht an Stelle eines Befehls ein Variablennamen auf, dann ist das Zuweisung. Danach wäre = üblich, aber + oder - fressen jetzt auch nicht viel Platz.

    Vorher:

    Nachher:


    Im Detail:
    [ legt seine Adresse mit Typ START auf den Stapel.
    FOR testet wie gehabt auf alle Parameter und auf [, legt dann die Adresse als Typ FOR auf den Stapel, danach normaler Ablauf der Befehle.. Die Schleife wird also wie heute mindestens einmal durchlaufen!


    DO testet auf [, legt dann einen Startpunkt vom Typ DO auf den Stapel, dann normaler Ablauf.
    Die passende ] findet das DO auf dem Stapel, erwartet WHILE, wertet einen Ausdruck aus und springt dann entweder zum DO oder entfernt sich vom Stapel.

    IF wertet einen Ausdruck aus und erwartet dann eine [
    True: Flag IFTRUE auf den Stapel legen und Befehle ausführen.
    False: Vorwärts nach dem passenden ] suchen.
    Wenn Else kommt, dann [ suchen, Flag ELSE auf den Stapel legen und Befehle ausführen.
    Ohne Else einfach weiter Befehle ausführen
    Die schliessende ] kann IFTRUE oder ELSE auf dem Stapel finden. Falls IFTRUE, dann auf ELSE testen.
    Wenn Else kommt, dann passende ] suchen, weiterer Ablauf normal.

    Die passende ] am Ende finden die FOR auf dem Stapel und ersetzen das NEXT. Funktionsweise fest eingebaut wie gehabt.am Ende das FOR vom Stapel nehmen

    Die letzte ] findet START auf dem Stapel und springt in die Endlosschleife.

    IF braucht eh eine Suche nach einer passenden ], so dass man auch kopfgesteuerte Schleifen machen könnte.


    Komische Nebeneffekte
    -[] sind Befehle, auch wenn sie wie Struktur aussehen! Schindluder ist möglich. Wo man heute mit GOTO aus einem Unterprogramm oder in eine Schleife springen kann, so kann man auch mit Klammerkonstruktionen Chaos machen, wenn man es drauf anlegt. IF a=1 [GOTO 7] wäre bereits so ein Fall...
    -Den Neben-Effekt von NEXT mit Variable würde ich fallen lassen.
    -Nicht durchdacht habe ich Arrays und wie sie Ihre Dimensionen holen. Ich denke da eher flach und nicht rekursiv, ich würde wohl bei A(B(1)) erst mal auf die Nase fallen.
    -Nicht befasst habe ich mich mit Strings und Variablentypen überhaupt innerhalb von Ausdrücken. Ist wohl recht tricky, wie die Formelauswertung Ihren Typ (String oder Float) bestimmt.

    Wenn Platz bleibt
    -Zahlen von mehr als 1 Ziffer könnten gleich als Byte, Int oder Float abgelegt und durch Token eingeleitet werden.
    => Mehr Aufwand,
    => vielleicht komische Effekte bei Variablen mit Ziffer im Namen.
    => Doch wieder Binär-Mischmasch im Text, Zahlen meist etwas länger.

    -Einen neuen Datentyp "Label" bauen, der per DEF mit aktueller Zeilennummer / Adresse gefüllt werden kann. In einem Vorlauf das Programm nach den DEF durchsuchen.
    => Kann GOTO/GOSUB beschleunigen und Zeilennummern im Programm überflüssig machen.

    -Variablen nach Typ getrennt ablegen und Pointer setzen, ähnlich, wie es jetzt schon mit Arrays ist.
    => Beschleunigt die Suche nach Variablen.

    Verworfenes:
    Verlockend fand ich, ähnlich Cobol / Mikes Vorschlag / heute üblich die Variablen alle am Programm-Anfang zu deklarieren, nach Typen getrennt, alphabetisch, nach starrem Schema formatiert. Macht den Interpreter sicher schneller, aber schwierig, das mit dem dummen Pushen tokenisierter Zeilen zu kombinieren.
    -Auch Floats brauchen ein Typzeichen, um Sonderfälle im Interpreter auszuschalten.
    -Variablen eindeutig über alle Typen halten und im Programm ohne Typzeichen (%$) arbeiten.
    -Die Syntax aller Befehle in ein strengeres Korsett stecken und dem Tokenisierer mehr Kontrollen ermöglichen.

    -Wenn eine Eingabe nicht in das starre Korsett des Tokenisierers gepresst werden kann, dann kann sie nicht ins Programm!! War beim Speccy glaub ich auch so.
    -Andere Schreibweise für FOR: for[x=0][x<40:x+1: Passt zwar ins Konzept, dürfte sogar Speicher sparen, hat aber schlechtere Laufzeit.


    Erkenntnisse?
    -Der andere Aufbau des Basic-Programms sorgt für kürzere Programme und schnellere Zeilensuche.
    -Der Aufwand fürs Einfügen von Zeilen steigt, weil 2 Bereiche dazu verschoben werden müssen. Und nach dem Einfügen muss weiterhin wie bisher neu verlinkt werden. Scheint mir also unterm Strich mehr ROM zu brauchen.

    -Platzersparnis im Programm wird aber von den zusätzlichen [ und Trennzeichen aufgewogen.
    => Befehle, die [ erwarten, sollten das gleich mit ins Token aufnehmen, beschleunigt auch den Interpreter. Eigentlich kann man es dann auch gleich wegfallen lassen, find ich aber fürs Schachteln doch verständlicher.

    -Ob man TO und STEP schreibt statt ; oder THEN statt [ scheint keinen richtigen technischen Unterschied zu machen. Der Tokenisierer macht sein Ding, und Befehls-Token sind Trennzeichen.
    -] statt ENDIF oder NEXT macht aber schon einen im Ablauf: Die Befehle brauchen kein Token (spart), die Daten auf dem Stack entscheiden die Aktion (frisst das wieder auf). -Genauso das WHILE: Ginge ohne und würde Platz sparen, solange es kein UNTIL gibt. Fand ich aber mit WHILE leserlicher.
    Außerdem finde ich, dass die Befehle eine nützliche Extra-Kontrolle auf falsch geschlossene ] bieten. Daher hab ich die mit aufgenommen.
    -Am 64er wird man nicht einrücken, der Nutzen der Extra-Kontrolle von ENDIF, NEXT und so wird dadurch noch höher.
    -IF hat schlechte Laufzeit, weil bei False eine langsame Suche gestartet wird. Vielleicht ist die heutige Variante mit Zeilennummern und Zeilenende doch nicht so übel....


    FOR und GOSUB bringen heute schon Stack-Sachen mit, das dürfte einen Teil des []-Krams aufwiegen.
    READ/DATA/RESTORE haben heute schon kompliziertere Forwärts-Suchen im Basic-Code, könnte man für IF hier recyclen.

    Letztlich muss aber trotzdem noch sehr viel an anderen Stellen gespart werden, und die Laufzeit von IF ist schlechter. Und ich habe nicht das Gefühl,dass ich da ganz Easy den nötigen Platz woanders freischaufeln könnte, wo das frühe Original ja mal in 8KB passen musste...

    PS: Hab mir jetzt ernsthaft 12 Stunden den Kopf zerbrochen, gefühlt bin ich grad erst aufgestanden. Und das, wo ich überhaupt nicht vorhabe, sowas zu programmieren... :drunk:

  • Hoogo: Donnerwetter - stimmt das mit den 12 Stunden? Auch hast du ja anfangs geschrieben, dass dich dieses Gedankenspiel fasziniert, bzw. dass du es großartig findest.

    Aber was würdest du jetzt - nach deinen eigenen Ideen - sagen, war das okay, was seinerzeit in 16 KB ROM reingeqetscht wurde? War es funktional genug, und effizient, konnte man mit "schaffe"?

  • +1: Hoogo, 12 Stunden intensiv an so einem Konzept dranzuhängen... Hammerhart! Ich hab' das ja auch erst unmittelbar nach meinem abgeschickten Post Bitte melde dich an, um diesen Link zu sehen. lesen können.

    Ich stelle mir an dieser Stelle echt jetzt die Frage, ob derartige Konzepte nicht ohnehin schon mal auf dem C64 verwirklicht worden sind. Nach etwas reiflicher Überlegung kommt mir da COMAL in den Sinn... das gab's soft-loadable als Version 0.14 und als Cartridge in der Version 2.0(?).

    Es wäre dann zwar kein BASIC mehr, aber immer noch ähnlich genug und immer noch ein Interpreter.

    Mal einen scharfen Blick drauf werden. Morgen früh. Ausgeschlafen.

    Gute Nacht alle beisammen. :)

  • oder Forth oder GEOS :wink:

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

  • Habe noch irgendwo das verstaubte COMAL Modul rumfahren... Jau, Gut' Nacht!

  • Ich würde sagen, soweit hab ich mehr verschlimmbessert: IF langsamer, sehr wahrscheinlich mehr ROM. 40 Jahre später sind mehr Inhalte aus der strukturierten Programmierung zwar naheliegend, aber für das ursprüngliche Ziel, 8KB mit genug Raum für I/O, wär das wohl schwerer zu schaffen gewesen. Von daher sag ich, dass die den Job schon echt gut gemacht haben und die Wahl der Spaghetti-Sprache mit ihren Nullbytes korrekt war.

    Klar, wenn man mit 16KB herumaasen kann, dann kann man auch die Ziele und Prioritäten ein bisschen anders setzen - macht aber größere Neuentwicklung nötig, und das wäre aus Sicht von Microsoft 77 eine saudumme Zeitverschwendung gewesen.

  • Es sind einige Parteien im Spiel:
    -Interpreter: Speicherbedarf und Speed.
    -Tokenisierer/Editor: Speicherbedarf
    -LIST-Befehl: Speicherbedarf.
    -Und das Programm und Variablen wollen auch noch Speicher und machen Verwaltungsaufwand im Code.

    Du hast die Thematik sehr eingehend strukturiert und von vielen Seiten beleuchtet, Respekt!

    Ich kann vielleicht "komplementär" nur Dinge beisteuern, die das flankieren. Und da habe ich obiges Zitat herausgegriffen. Genau so eine kurze "Liste" wie in dem Zitat hab ich auch mal aufgestellt. Sie korrespondiert tlw. mit der Aufteilung des BASIC-Interpreters bzw. der Aufgabenteilung gemäß Michael Steil zwischen Bill Gates, Monte Davidoff und dem Dritten (der mir nicht einfällt).

    Meine Ideen sind entsprechend meinen Möglichkeiten ganz bieder:
    - häufig gebrauchte Funktionen auf Zeit optimieren,
    - den Rest auf geringen Platzbedarf.
    (So ähnlich wurde es wohl beim Entwurf des RISC-Prozessorkonzepts gehandhabt, wenngleich ich das stark verkürze und vielleicht gibt meine Zuspitzung nicht ganz das her was sie meint.)

    • Das Tokenformat sowie der binäre Programmaufbau, Zeilenaufbau nebst Nullen und Linkzeigern und Zeilennummern bleibt unverändert erhalten (Ausnahme extra Tokens, s.u.)
    • Die Speicheraufteilung und Verwaltung bezüglich Variablen wird komplett geändert
    • für das RAM unter dem ROM wird eine einfache Speicherverwaltung a la MS-DOS eingebaut
    • Direktmodus-Aufgaben oder solche bei denen der Cursor blinkt, folgen der Langsamkeit des Benutzers und werden daher maximal kompakt (und langsam) durch einen Zwischencode-Interpreter a la Sweet16 von Steve Wozniak erledigt. Also vor allem LOAD ,SAVE (nur die Vor- und Nachbereitung), Tokenisierung von Eingabezeilen, LIST. Um die Langsamkeit bei Tokenisierung zu kaschieren, wird die Routine per Interrupt / Taskswitcher "nebenläufig" gemacht, sodass der Benutzer an der Folgezeile weitertippen kann auch wenn im Hintergrund noch eine Sekunde lang weiter die vorherige tokenisiert wird.
    • Integer-Arithmetik wird von der Gleitkomma-Artihmetik entflochten und schneller sowie nach Möglichkeit (Edit: im Hinblick auf den Speicherverbrauch der Variablen; nicht der Code, der wird länger!) speichersparender gemacht. Gegenwärtig wird das allermeiste an Arithmetik mit Taylor-Reihenentwicklungen (oder dergleichen) realisiert. Denkbar ist, hier je Aufgabe (sin, cos, Potenzen..) jeweils spezialisiertere Routinen wie z.b. für die Quadratwurzel am bekanntesten, zu verwenden.
    • Ins ROM werden Packer-Entpackerroutinen und gepackte Archiv-Routinen aufgenommen. Diese können zusätzliche Funktionalität, die relativ selten gebraucht wird, "on demand" in einen "transienten" Speicherbereich (unter dem Kernel z.b.) entpacken.
    • Als erste "Kunden" dieses Entpackers benenne ich die Trigonometrischen Funktionen, die in ein gepacktes ROM-Archiv ausgelagert werden und nur bei Benutzung in das (reichlich vorhandene) RAM ausgepackt werden. Begründung: offensichtlich werden diese nicht von allen Programmen genutzt und das war schon zu Zeiten der Erschaffung des MS-Basic bekannt, weshalb es laut Michael Steil Versionen gab die diese Arcus Tangens und so weiter-Funktionen weglassen konnten - iirc, nicht ins RAM laden (MS-Basic war nicht nur ROMable).
    • Zweiter (dritter, usw.) Kunde des ROM-Archivs wären: die seriellen RS232 Routinen, ein Maschinencode-Monitor mit Assembler (u.a.? Spriteeditor)
    • Die Funktionalität des Interpreters wird um Strukturierte Elemente, verbesserte Garbage Collection (mit Backlink usw.) sowie Grafikbefehle u. evtl. Sound erweitert; Der Einfachheit halber würde ich mich an Basic 3,5 und/oder 4.0 orientieren.
    • u.U. Zeiger(-arithmetik ), benannte Prozeduren bzw. deren Verschachtelung a la Pascal wäre auf meinem Wunschzettel, allerdings wohl kaum realisierbar.

    2 Mal editiert, zuletzt von Stephan (29. Dezember 2015 um 10:58)

  • Nachtrag: Zu COMAL hab ich dieses gefunden:

    Bitte melde dich an, um diesen Link zu sehen.
    (Der Server C64-Wiki ist momentan down, habe den Link aus dem Cache.)

    Laut Wiki soll das CBM-Comal public domain geworden sein. Kann das wer bestätigen? :)

  • Das Tokenformat sowie der binäre Programmaufbau, Zeilenaufbau nebst Nullen und Linkzeigern und Zeilennummern bleibt unverändert erhalten (Ausnahme extra Tokens, s.u.)
    Die Speicheraufteilung und Verwaltung bezüglich Variablen wird komplett geändert

    Das finde ich jetzt sehr interessant, dass wir an dieser Stelle zu umgekehrte Lösungen gekommen sind. Was für ne Struktur schwebt Dir denn zu den Variablen vor?

    Hab heute noch einen vielleicht guten Gedanken gehabt, gleiche Verwaltung für Basic-Zeilen wie für Variablen:
    -Alle "Variablen" sind als 1 Bit Array, 4 Bit Typ und 11 Bit Name auszudrücken. Zeilennummern wären ein Typ davon und dürften bis 4095 reichen.
    -Alle Variablen werden zur späteren Suche sortiert abgelegt. Das gibt es für Zeilennummern eh schon, würde sich dann für Variablen nebenher ergeben.
    Damit wären die bisher 2 getrennten Routinen für das Ablegen des Programms, Suche von Zeilennummern und das gleiche für Variablen in einer Routine erledigt.
    Dadurch würde es sinnvoll, mehrere Listen für Name und Inhalt getrennt zu führen, was auch für Variablen gelten würde. Das erste Anlegen von Variablen würde deutlich langsamer, Suchen dafür schneller.
    Nebenbei hatte ich auch den Gedanken, dass LIST, LOAD, SAVE auch für Variablen anwendbar wären und man so Programm mit Startwerten für Variablen speichern könnte.

    Direktmodus-Aufgaben oder solche bei denen der Cursor blinkt, folgen der Langsamkeit des Benutzers und werden daher maximal kompakt (und langsam) durch einen Zwischencode-Interpreter a la Sweet16 von Steve Wozniak erledigt. Also vor allem LOAD ,SAVE (nur die Vor- und Nachbereitung), Tokenisierung von Eingabezeilen, LIST. Um die Langsamkeit bei Tokenisierung zu kaschieren, wird die Routine per Interrupt / Taskswitcher "nebenläufig" gemacht, sodass der Benutzer an der Folgezeile weitertippen kann auch wenn im Hintergrund noch eine Sekunde lang weiter die vorherige tokenisiert wird.

    Der Zwischencode-Interpreter gefällt mir sehr. Selbst wenn darin programmierte Sachen den Speicherbedarf nicht aufwiegen sollten (unwahrscheinlich...), hätte man doch einen C64 mit gleich 2 eingebauten Sprachen! Zum Befehlssatz hätten bestimmt die Leute vom Z80 noch Ideen, was so die häufigsten komplizierten Befehle sind.
    Ob für Multitasking-Sachen noch Platz wäre ist eine andere Frage, ich hätte jedenfalls eine Langsamkeit im Direktmodus akzeptiert.

    für das RAM unter dem ROM...

    Bei all den anderen Punkten bin ich mir erstmal unsicher, ob dafür der Platz noch da wäre und ob es eine gute Idee ist, aus dem ROM auszubrechen und Sachen im großen Stil im RAM laufen zu lassen. Klar, wenn man Datasette, RS232 usw. "rauswirft" oder frisch macht, dann wäre der Platz natürlich da.

    Nachtrag: Zu COMAL hab ich dieses gefunden:

    Die Files sind allerdings auch 32KB groß. Was kann man sich denn unter einem 3Pass-Interpreter vorstellen? 2 Vorab-Läufe zum Festlegen diverser Zusatzinfos?

  • Zitat von hoogo

    Was kann man sich denn unter einem 3Pass-Interpreter vorstellen? 2 Vorab-Läufe zum Festlegen diverser Zusatzinfos?

    Ich hab' da mal etwas recherchiert:

    1. Pass: Tokenisierung der Eingabezeilen (wie in CBM BASIC),
    2. Pass: direkt nach RUN: Auflösung aller Sprungziele - das betrifft auch übersprungene Blöcke in IF...THEN...ELSE/ELSEIF...ENDIF Strukturen, Schleifen und Prozeduraufrufen!
    3. Pass: eigentliche Programmausführung.

    An dieser Stelle macht COMAL also das, was ich mit den Zusatzdaten hinter den GOTO/GOSUB-Token vorschlagen hat, allerdings einmalig direkt nach dem Programmstart, während ich eher einen "lazy" Approach im Sinn hatte.

    Die Strukturbefehle in Waterloo BASIC arbeiten übrigens ähnlich! Ich hab das für den VC-20 mal vor ein paar Jahren re-engineered und dabei gesehen, daß da für LOOP, etc. 3-Byte-Tokens zum Einsatz kommen. IF wird auch umdefiniert.

  • Nachtrag: bei CA2 / CB2 des VIA könnte man sogar versuchen, die Polarität des Flankensensors bei jeder Flanke umzuschalten (togglen), vom abfragenden Interruptprogramm aus...

    Schade, hab da in meinen Dokus zur CIA kein passendes Bit zum Umschalten gefunden.

  • Schade, hab da in meinen Dokus zur CIA kein passendes Bit zum Umschalten gefunden.

    Das Eingangssignal hängt ja auf /FLAG und das erkennt ja nur negative Flanken - da kann man nichts drehen. Je nach Codierungsschema, könnte man z.B. anhand der Zeit zwischen aufeinanderfolgenden negativen Flanken die tatsächlichen Bits schießen (was ja auch die Originalroutine oder etwa auch das SuperTape-Verfahren für den C64 so machen).
    Bits nur als Pegel zu codieren ist sowieso keine gute Idee und gängige Tape-Formate verwenden auch immer Pegelwechsel für die Codierung, sonst könnte es passieren, dass bei einer langen 0 oder 1 Folge sich überhaupt nichts tut und das ist für eine sichere Dekodierung ziemlich hinderlich, da die Gleichlaufschwankungen bei einem Band doch ausschlaggebend sind und mit dem Pegelwechseln immer eine implizite Synchronisation (quasi Taktung) gegeben ist.

  • Irgendwie ist das doch mittlerweile total vom Thema abgeglitten. Im Eingangs-Post ging es doch nur um die Optimierung, also, so wie ich es verstehe, dass bestehender (BASIC-)Code (weitestgehend) noch laufen sollte. Jetzt sind aber schon wilde andere BASIC-Dialekte/Formen oder sonstige Sprachen im Gespräch...

    Ich hatte mich spaßeshalber mal etwas mit der 80/88/240-Zeichen-Zeilen-Geschichte befasst. Es läuft fasst. Nur die CHRGET-Routine funkt noch dazwischen. Den Grund suche ich zur Zeit noch :gruebel , bzw. wie ich das abstellen kann. Es dürfte dann hoffentlich mit 'altem' BASIC-Code verträglich sein. Mal sehen.

    Vielleicht könnte man diesen Thread mal wieder in diese Richtung zurückbringen. (Ungenutzte) BASIC-Erweiterungen gibt es ja nun zuhauf. Da muss nicht noch eine her. Das Thema dürfte auch ziemlich ausgereizt sein; aber das Standard-BASIC besser machen, fände ich schwer interessant 8o .

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

    Ex-TLI (The Level 99 Industries) & Ex-TNP (The New Patriots) & Ex-TEA (The East Agents) & ?

  • ...z.B. anhand der Zeit zwischen aufeinanderfolgenden negativen Flanken die tatsächlichen Bits schießen (was ja auch die Originalroutine oder etwa auch das SuperTape-Verfahren für den C64 so machen).Bits nur als Pegel zu codieren ist sowieso keine gute Idee und gängige Tape-Formate verwenden auch immer Pegelwechsel für die Codierung, sonst könnte es passieren, dass bei einer langen 0 oder 1 Folge sich überhaupt nichts tut und das ist für eine sichere Dekodierung ziemlich hinderlich, da die Gleichlaufschwankungen bei einem Band doch ausschlaggebend sind und mit dem Pegelwechseln immer eine implizite Synchronisation (quasi Taktung) gegeben ist.

    Ack. Pegel Erkennen hin oder her, einfach Bytes schreiben sollte man nicht. Tape, Floppy, selbst DVD arbeiten mit Zeitmessung von (Pegel)-Änderungen, für die auch mal eine Obergrenze ohne Änderung definiert wurde. Beim Tape sind 2 Längen üblich, was sich leicht in 1 Bit umrechnen lässt, bei der Floppy sind es 3 Längen, die mit GCR in Bits umgerechnet werden, und bei DVD erheblich mehr.
    Praktisch wird beim Tape aber 01 oder 001 geschrieben, um Kurz und Lang darzustellen. Eine Pegelerkennung könnte das auf 0 und 11 kürzen, 40% schneller.

    Irgendwie ist das doch mittlerweile total vom Thema abgeglitten. Im Eingangs-Post ging es doch nur um die Optimierung, also, so wie ich es verstehe, dass bestehender (BASIC-)Code (weitestgehend) noch laufen sollte. Jetzt sind aber schon wilde andere BASIC-Dialekte/Formen oder sonstige Sprachen im Gespräch...

    Ich hatte mich spaßeshalber mal etwas mit der 80/88/240-Zeichen-Zeilen-Geschichte befasst. Es läuft fasst. Nur die CHRGET-Routine funkt noch dazwischen. Den Grund suche ich zur Zeit noch :gruebel , bzw. wie ich das abstellen kann. Es dürfte dann hoffentlich mit 'altem' BASIC-Code verträglich sein. Mal sehen.

    Vielleicht könnte man diesen Thread mal wieder in diese Richtung zurückbringen. (Ungenutzte) BASIC-Erweiterungen gibt es ja nun zuhauf. Da muss nicht noch eine her. Das Thema dürfte auch ziemlich ausgereizt sein; aber das Standard-BASIC besser machen, fände ich schwer interessant 8o .

    Eigentlich ja, die Ursprungsfrage war glaub ich so "low level" gemeint.

    Allerdings ist Bill ja nicht gezwungen worden, ein bestimmtes Basic mit bestimmtem Aufbau zu erstellen. Vielleicht wäre ein anderes Konzept im Großen ja schneller oder kürzer gewesen? Hier auf "mid level" findet sich sicher auch was, schließlich ist das ganze ja über Jahre aus einem 4KB-Basic für noch kleinere Rechner gewachsen. Diesen Teil finde ich wiederum sehr interessant, wobei sich da glaub ich um Welten mehr im Teil von Commodore finden lässt.

    Und auf "Hi level": Das Basic war da, als die ersten richtigen Computer für den flammneuen 6502 kamen, Geld gab es für Lizenzen, genauso schnell gab es das Basic für X86, und bei Erscheinen des C64 hatte Bill schon lange IBM am Wickel. Noch optimaler geht es kaum, wie suboptimal wäre es gewesen, bis in die 80er das 6502-Basic zu polieren?

  • Allerdings ist Bill ja nicht gezwungen worden, ein bestimmtes Basic mit bestimmtem Aufbau zu erstellen. Vielleicht wäre ein anderes Konzept im Großen ja schneller oder kürzer gewesen? Hier auf "mid level" findet sich sicher auch was, schließlich ist das ganze ja über Jahre aus einem 4KB-Basic für noch kleinere Rechner gewachsen. Diesen Teil finde ich wiederum sehr interessant, wobei sich da glaub ich um Welten mehr im Teil von Commodore finden lässt.

    Und auf "Hi level": Das Basic war da, als die ersten richtigen Computer für den flammneuen 6502 kamen, Geld gab es für Lizenzen, genauso schnell gab es das Basic für X86, und bei Erscheinen des C64 hatte Bill schon lange IBM am Wickel. Noch optimaler geht es kaum, wie suboptimal wäre es gewesen, bis in die 80er das 6502-Basic zu polieren?

    Bill hat das genommen was da war und weiter entwickelt. Und Bills Basic-Interpreter war Dank massiver Schwarzkopien weit verbreitet und ich glaub er hat es diesem Umstand auch zu verdanken, dass Commodore diesen einst für den PET herangezogen haben, weil in einschlägigen Kreisen eben bekannt. ... und Bill wollte endlich Geld sehen für seine "Software". Da waren ihm so hehre Ziele, wie einen effizienten BASIC-Interpreter der neuen Generation eher nicht so wichtig. ;)
    Was man wirklich aus BASIC herausholen kann, wenn man einen eigenen Weg geht, sieht man ja auch z.B. am BBC-Basic ...

    Aber mir gefällt auch Hexworx' Ansatz sehr gut, unter der Haube neue, bessere Ansätze zu verwirklichen und dabei die Kompatibilität zu bestehenden Software zu wahren. :thumbsup:
    Hat ja auch eine sportliche Komponente, nach dem Motto: Was hätte man da (wann auch immer) herausholen können ... und hätte nebenbei auch jetzt noch einen Sinn, ohne das neue Software geschrieben werden müsste.

  • Hoogo: sorry ich konnte dem Thread eine Zeitlang nicht folgen die letzten Tage, hoffe später noch mehr zu deinen Beiträgen erwidern zu können (spannende Thematik)..

    JeeK:

    Du schriebst "was man herausholen kann...BBC Basic". Da ist leider ein wenig der Wurm drin,
    soweit ich lesen konnte, hatten die BBC Micro-Rechner alle mindestens 32 KB ROM.

    Da würden also Äpfel mit Birnen verglichen.

    Im vorliegenden Fall ist es wirklich witzlos, das Basic V2 das incl . Kernal mit 16 KB auskommen musste, mit einem Rechner zu vergleichen der doppelt soviel zur Verfügung hatte.

    Bitte relative Vergleiche nur mit Rechnern vornehmen, die gleiche ROM-Größe haben. Der sportliche Gedanke den du formulierst, wird von mir geteilt - aber bitte ohne Gatter-Doping ;) oder ROM-Bloating ... ;)