Hello, Guest the thread was called4k times and contains 62 replays

last post from BIF at the

Schnelle BASIC Versionen auf 65xx/Z80?

  • Die Umwandlung das Konstanten-Strings in die Binärrepräsentation (egal ob Integer oder FP) ist vergleichsweise aufwändig.

    Mal eine dumme Frage: Warum hat man eigentlich Zahlenwerte nicht auch tokenisiert? Platz in der Tokenliste wäre ja noch gewesen. Z. B. hätte man einfache Bytewerte speichern können als Token+Byte und 16 Bit-Werte als Token+Lowbyte+Highbyte und dann natürlich echte Fließkommawerte als Token+Exponent+Mantisse... Gibt es irgendeinen (triftigen) Grund dafür, daß Zahlenkonstanten stets als Zeichenkette abgelegt werden?:gruebel

  • Mal eine dumme Frage: Warum hat man eigentlich Zahlenwerte nicht auch tokenisiert? Platz in der Tokenliste wäre ja noch gewesen. Z. B. hätte man einfache Bytewerte speichern können als Token+Byte und 16 Bit-Werte als Token+Lowbyte+Highbyte und dann natürlich echte Fließkommawerte als Token+Exponent+Mantisse... Gibt es irgendeinen (triftigen) Grund dafür, daß Zahlenkonstanten stets als Zeichenkette abgelegt werden?:gruebel

    Ich denke, weil man das über Konstanten sehr leicht selber optimieren kann, wenn es einem auf die Geschwindigkeit ankommt.
    Beim PET hätten die zusätzlichen Routinen vielleicht nicht mehr ins vorhandenen ROM gepasst und hätten das Gerät teurer gemacht.

  • Die Umwandlung das Konstanten-Strings in die Binärrepräsentation (egal ob Integer oder FP) ist vergleichsweise aufwändig.

    Mal eine dumme Frage: Warum hat man eigentlich Zahlenwerte nicht auch tokenisiert? Platz in der Tokenliste wäre ja noch gewesen. Z. B. hätte man einfache Bytewerte speichern können als Token+Byte und 16 Bit-Werte als Token+Lowbyte+Highbyte und dann natürlich echte Fließkommawerte als Token+Exponent+Mantisse... Gibt es irgendeinen (triftigen) Grund dafür, daß Zahlenkonstanten stets als Zeichenkette abgelegt werden?:gruebel

    Ist problematisch, weil ja das High- und Low-Byte 0, $22 (") und $3A (:) enthalten kann. Die werden exklusiv für das Zeilenende, für String-Delemiter und Kommandoende vom Interpreter verwendet, ungeachtet dessen, welche Token eventuell so einen Wert einleiten. Da müsste man sonst schon einiges am Interpreter umbauen. Oder man codiert anders, sodass die besagten Werte mit Escape-Sequenzen (Token) "umgangen" werden. Sowas dürfte gehen, zumindest hab ich das für mein Grundlagenprojekt das in die Richtung geht so entworfen.

  • Wie groß ist das BBC Basic eigentlich im ROM? Also zum Beispiel im Acorn?

    16K. Der BBC Micro Computer hat vier Sockel für 16K-(EP)ROMs, die in den Adressbereich 0x8000-0xbfff eingeblendet werden können ("sideways address space"). Ab Werk war ein Sockel mit BBC Basic bestückt, die anderen kann der Anwender für Anwendungsprogramme, Systemerweiterungen oder andere Programmiersprachen nutzen. Die Systemarchitektur unterstützt ingesamt sogar 16 sideways ROMs, die übrigen 12 müsste man auf einer Erweiterungskarte unterbringen.

  • Leider kommt man mit 16-Bit-Integer mit Vorzeichen nicht sehr weit (-32768 bis +32767). Damit könnte man auf dem PET nicht mal den Bildschirmspeicher adressieren.

    Den Einwand verstehe ich nicht ganz. Ob mit oder ohne Vorzeichen ist doch nur Interpretationssache: Die CPU sieht am Ende einfach nur 16 bit, und diese bestimmen den Adressraum.

    Ja, kann man alles machen. Und wird auch super übersichtlich und nachvollziehbar

    Ich kann mir nicht helfen, ich habe das Gefühl, du verschiebst hier nachträglich die Fragestellung: Geht nicht — geht schon —- ja, aber ist nicht schön.

  • Ich denke, weil man das über Konstanten sehr leicht selber optimieren kann, wenn es einem auf die Geschwindigkeit ankommt.
    Beim PET hätten die zusätzlichen Routinen vielleicht nicht mehr ins vorhandenen ROM gepasst und hätten das Gerät teurer gemacht.

    Mehr Platz im Rom für den Basic-Interpreter könnte ein Grund sein, obgleich ... wäre das wirklich so viel? Irgendwann müssen die Zahlen ohnehin geparst und umgewandelt werden. Bliebe wohl nur die Ausgaberoutine ("LIST"), die die zusätzlichen Tokens zurück in Zahlen konvertieren müßte. Und natürlich das von JeeK erwähnte Problem.

    Was die Geschwindigkeit anbelangt, sind Variablenkonstanten wohl schneller als Zahlstrings, aber auch das Parsen der Variable kostet einiges an Zeit. Echte Zahlenkonstanten dürften im Vergleich dazu nochmals schneller sein.

    BBC Basic macht das.

    Danke für die Info. Könnte ein Grund sein, warum BBC Basic (auch bei 1 Mhz) schneller ist als andere Interpreter.

    Ist problematisch, weil ja das High- und Low-Byte 0, $22 (") und $3A (:) enthalten kann. Die werden exklusiv für das Zeilenende, für String-Delemiter und Kommandoende vom Interpreter verwendet, ungeachtet dessen, welche Token eventuell so einen Wert einleiten.

    Guter Einwand. Leider kenne ich mich mit dem C64-Basic-Interpreter nicht so gut aus. Daher weiß ich nicht, wann an welcher Stelle z. B. nach dem Zeilenende gesucht wird. Dieses ist ja eigentlich bereits in dem Link auf die nächste Zeile enthalten. Eine einfache Differenz zwischen Linkwert und Zeilenadresse dürfte das gleiche Ergebnis liefern, aber deutlich schneller sein. Während der Programmausführung lassen sich Zeilenende und Zahlenwert eigentlich gut unterscheiden, denn ein Zahlentoken würde nur auftreten in einem Term oder einer DATA-Anweisung. In anderen Fällen gäbe es einen ?SyntaxError. Wird die Ausführung einer Zeile vorzeitig abgebrochen z. B. bei Nichterfüllung einer IF-Bedingung, würde es ausreichen, den Link auf die nächste Zeile in die Programmadresse zu laden. Von daher kann ich mir als Basic-Laie keine Situation vorstellen, in der man dieses Nullbyte wirklich suchen muß. :gruebel Gleiches gilt auch für den Doppelpunkt oder das Anführungszeichen. (Nebenbei: Damals[tm] hatte ich auf dem Amiga mal so eine Art Minipascal-Interpreter geschrieben, bei dem Schlüsselwörter im Text durch Tokens ersetzt wurden teils mit Adresszeiger auf ein Sprungziel im Text. Neben den Adressen konnten auch die Tokennummern alle Werte enthalten (z. B. den Returncode), ohne daß dadurch der Interpreter durcheinandergeraten wäre...)

  • Schnelle Basic-Versionen ?
    Grundsätzlich sind alle Basic-Versionen, die zusätzliche Befehle in Maschinensprache zur Verfügung stellen diesbezüglich schneller.

    Die Frage müßte wohl spezifischer gestellt werden.
    Schneller beim Laden/Speichern, Grafik, Zeichensatz, Cursorsetzen, Rechnen, usw.

    Auch wenn man z.B. Fehler des Basics korrigiert, ist das Basic atomatisch schneller, da man sich dann die Fehlerbehandlung, die meist einigen Code erfordert, sparen kann.


    Schönen Gruß.

  • Die Systemarchitektur unterstützt ingesamt sogar 16 sideways ROMs, die übrigen 12 müsste man auf einer Erweiterungskarte unterbringen.

    Und wieder einen Punkt für den CPC. Der kann 252 ROMs verwalten. :ChPeace

  • Guter Einwand. Leider kenne ich mich mit dem C64-Basic-Interpreter nicht so gut aus. Daher weiß ich nicht, wann an welcher Stelle z. B. nach dem Zeilenende gesucht wird. Dieses ist ja eigentlich bereits in dem Link auf die nächste Zeile enthalten. Eine einfache Differenz zwischen Linkwert und Zeilenadresse dürfte das gleiche Ergebnis liefern, aber deutlich schneller sein. Während der Programmausführung lassen sich Zeilenende und Zahlenwert eigentlich gut unterscheiden, denn ein Zahlentoken würde nur auftreten in einem Term oder einer DATA-Anweisung. In anderen Fällen gäbe es einen ?SyntaxError. Wird die Ausführung einer Zeile vorzeitig abgebrochen z. B. bei Nichterfüllung einer IF-Bedingung, würde es ausreichen, den Link auf die nächste Zeile in die Programmadresse zu laden. Von daher kann ich mir als Basic-Laie keine Situation vorstellen, in der man dieses Nullbyte wirklich suchen muß. :gruebel Gleiches gilt auch für den Doppelpunkt oder das Anführungszeichen. (Nebenbei: Damals[tm] hatte ich auf dem Amiga mal so eine Art Minipascal-Interpreter geschrieben, bei dem Schlüsselwörter im Text durch Tokens ersetzt wurden teils mit Adresszeiger auf ein Sprungziel im Text. Neben den Adressen konnten auch die Tokennummern alle Werte enthalten (z. B. den Returncode), ohne daß dadurch der Interpreter durcheinandergeraten wäre...)

    Ja, die Link-Zeiger ... diese Information wird vom Interpreter eher stiefmütterlich behandelt und genutzt. Hauptsächlich für GOTO/GOSUB um sich durch die Zeilen zu hanteln. Aber der Interpreter merkt sich (quasi im Cache) weder die Adresse der "aktuellen" Zeile noch die Folgezeilenadresse. Wäre zwar billig zu implementieren gewesen sein, aber war vielleicht auch mal der ROM-Knappheit zum Opfer gefallen (die Überlegung es überhaupt zu machen).

    Das Null-Byte ist essentiell, denn die Kernroutine des Interpreters, die CHRGET-Routine, die das nächste Zeichen aus dem BASIC-Text holt, kennt nur dieses Ende-Zeichen. Das ist Ameisen-Parsing. Die Ameise sieht nichts weit voraus oder zurück, sondern nur gerade immer das nächste. Das ist das Um und Auf, das überall im Interpreter drinnensteckt (und in all den Erweiterungen zum Interpreter). Das wäre faktisch ein Paradigmenwechsel, der auf das Neuschreiben des Interpreters hinausläuft. Kann man machen, klar. Ich verstehe schon, im Gedankenexperiment ist natürlich viel vorstellbar.


    Wieso gleiches für ":" oder Anführungszeichen gelten soll, ist mir nicht klar. Das Zeilenende wäre durch die Link-Struktur immerhin bekannt. Aber einen Doppelpunkt, oder das String-Ende (das übrigens nicht nur ein (") sondern auch wiederum das Zeilenende selbst sein kann) zu finden, muss man tatsächlich suchen. Auf diesem Weg möchte ich mich als Interpreter eigentlich nicht darum kümmern müssen, ob da etwaige Ausdrücke herumliegen die Binary-Werte enthalten ... ;)

  • Rein theretisch könnte man statt 5 Bytes pro Zeile auch auf 4 Bytes pro Zeile umorganisieren, das spart dann sogar das Unterprogramm zur Zeilenverlinkung.

    Und theoretisch sind auch 3 Byte pro Zeilenanfang denkbar.
    5B : 0,L1,L2,Z1,Z2
    4B : 0,ZL,Z1,Z2 (ZL=Zeilenlänge)
    3B : ZL,Z1,Z2

    Und auch das 0Byte am Zeilenanfang, könnte theoretisch ein Token für Zeilenanfang sein.

    Außerdem könnte man das Basic theoretisch gleich nach Maschinencode kompilieren.

    Der Doppelpunkt vor einem Befehl könnte einem SYS entsprechen.
    :Befehl wäre dann sys-Token und der Sys Befehl ruft dann die Basic-Befehle über eine Tabelle auf.

    Da wären wir wieder beim Thema, dem Doppelpunkt am Anfang gehört meiner Meinung nach die Zukunft und es gibt keinen Unterschied mehr zwischen Basic und Assembler Quelltext.

    Das heißt Basic-Programme können direkt in Assembler-Programme und Assembler-Programme direkt in Basic-Programme eingefügt werden.

    Schönen Gruß.

  • Das ist Ameisen-Parsing.

    Okay, daß der Interpreter bei der Ausführung einen Lookahead von 1 hat, ist ja nichts ungewöhnliches. Würde ich auch so machen. Aber beim Durchgang durch den Code hangelt er sich ja immer nur von Token zu Token, d. h. trifft er auf ein Zahlentoken, wird der nachfolgende Wert auf den internen Wertestapel gepackt (, sofern der Modus Termbehandlung aktiv ist, ansonsten gibt es einen Syntaxerror). Da jede Zahlenkonstante also stets von einem Token eingeleitet und damit geschützt wird, kann der Interpreter bei normaler Schritt-für-Schritt-Ausführung niemals auf ein (falsches) Nullbyte oder Doppelpunkt etc einer Zahlenkonstante stoßen. Dies wäre nur dann der Fall, wenn der Interpreter Programmcode überspringen und sich irgendwo später wieder in den Codestream einklinken muß. Bei einem normalen Basic-Interpreter würde ich davon ausgehen, daß dies nur bei der Suche nach der nächsten DATA-Anweisung der Fall ist, wenn nur auf das DATA-Token und das Nullbyte getestet wird. Bei Verwendung einer Zahlenkonstante müßte man folglich die Zahlentokens ebenfalls erkennen und die Zahlenwerte überspringen. Ich kann mir aber nicht vorstellen, daß dafür wesentlich mehr Interpretercode notwendig ist. Im Gegenteil dürfte die normale Interpreterschleife als Ausgleich dafür verkürzt und beschleunigt werden, da jedes gelesene Zeichen nicht mehr automatisch auf eine Ziffer getestet wird.

    Aber der Interpreter merkt sich (quasi im Cache) weder die Adresse der "aktuellen" Zeile noch die Folgezeilenadresse.

    :facepalm:Heißt das ernsthaft, daß bei einem IF das Überspringen der Befehle nach dem IF bzw. der Sprung in die nächste Zeile dadurch realisiert wird, daß anhand des Nullbytes die nächste Adresse gesucht wird, anstelle die Adresse der neuen Zeile direkt aus dem Programmcode zu entnehmen? Das wäre allerdings eine ziemlich bescheidene Vorgehensweise, weil a) umständlich und b) langsam. Bei einer nicht zeilenorientierten Sprache wie Pascal wäre so etwas wohl notwendig, aber Basic hätte zumindest hier mal einen kleinen Vorteil gegenüber richtigen Hochsprachen. Diesen nicht zu nutzen ist ... suboptimal.

  • :facepalm:Heißt das ernsthaft, daß bei einem IF das Überspringen der Befehle nach dem IF bzw. der Sprung in die nächste Zeile dadurch realisiert wird, daß anhand des Nullbytes die nächste Adresse gesucht wird, anstelle die Adresse der neuen Zeile direkt aus dem Programmcode zu entnehmen? Das wäre allerdings eine ziemlich bescheidene Vorgehensweise, weil a) umständlich und b) langsam. Bei einer nicht zeilenorientierten Sprache wie Pascal wäre so etwas wohl notwendig, aber Basic hätte zumindest hier mal einen kleinen Vorteil gegenüber richtigen Hochsprachen. Diesen nicht zu nutzen ist ... suboptimal.

    Richtig, so arbeiten IF, REM, DATA, wenn sie zur nächsten Zeile müssen ...

    BASIC ROM $A906

    Wie schon angedeutet. Nicht nur die aktuelle Zeilenummer, sondern auch die aktuelle Zeilenadresse zu speichern (2x ZP zu spendieren) hätte schon gereicht, dann komme ich über den Link auf die nächste Zeile. Auch mir ein Rätsel warum die das nicht gemacht haben.

    Ich hab den Eindruck, man hat den Link-Adressen nicht wirklich getraut. Es können auch Aspekte von Programm/Direktmodus reinspielen. Im Direktmodus hat man zwar auch eine Pseudo-Zeile (der Eingabepuffer $200, ist eigentlich nur ein Teil davon) es beginnt bereits bei $1FC oder so), da blieb man im gedanklich sichereren Fahrwasser, scheint mir.

    Das hätte auch das legendäre

    10000 IF .... GOTO 10000

    das sich von der 1. Zeile weg durch den Text zu Zeile 10000 hanteln muss, mildern können (indem GOTO/GOSUB prüft, ob die angesprugene Zeilennummer gleich die Zeilenummer ist, die wir anspringen und wenn ja, aus den besagten neue Zeilenadresse einfach laden). Das wurde wohl als seltener Fall eingestuft, der für eine Coder-Vergrößerung im ROM nicht dafür stand (meine Theorie).

  • Das wurde wohl als seltener Fall eingestuft, der für eine Coder-Vergrößerung im ROM nicht dafür stand (meine Theorie).

    Das ganze Basic war doch eine 3-Mann-Show, für die sich Studenten teure Rechenzeit am Uni-Rechner kaufen mussten.

    Die mussten als erste am Markt sein, und es durfte nicht viel kosten. Unter den Bedingungen macht man auch schon mal komische Kompromisse, so manche Falle bemerkt man ja erst beim Programmieren.


    Und davon ab ist das bei 4KB Hauptspeicher auch nicht sooo wild, da werden die Programme vielleicht eine Größe von 100 Zeilen erreichen.

  • Exakt das wollte ich auch schreiben. ;)


    Im nach hinein kann man das natürlich alles analysieren und kritisieren. Aber ich denke, die hatten damals nur ein sehr kleines Zeitfenster, in dem der Interpreter auf den Markt kommen musste. Außerdem waren ROMs teuer. Jede Optimierung, die den Interpreter-Code vergrößert hätte, hätte ihn uninteressanter gemacht. Performance war damals sicher nicht das oberste Ziel.

  • Eine Vergrößerung des ROM-Codes ist für viele Optimierungen nicht notwendig.

    Sieh z.B. RAM-Basic/1
    Version 2 hat natürlich noch mehr Optimierungen wie z.B.
    Kettenpoke, String-Adresse, Load.Adresse, usw. ohne Rom-Vergrößerung.

    Die Verbessung des ROM-Codes ist aber natürlich ein Zeitfrage und eine Frage die richtigen Ideen umzusetzen.

    Schönen Gruß.

  • Wäre es auch auf dem jetzigen C64-Prozessor möglich ein Maschinensprache-kompatibles Basic zu programmieren ?
    Meiner Meinung nach ja.

    Und zwar mit dem Break-Befehl/Vektor.


    Eine Basic-Zeile beginnt ja bekanntlich mit einem Null-Byte.
    Und der Null-Code in Maschinensprache ist bekanntlich der BRK-Befehl.
    Das heißt natürlich, daß man mit dem 0-BRK-Befehl den Basic-Programmzeiger mit dem Maschiensprache-ProgrammCounter synchronisieren kann.
    Und über den Break-Vektor dann zur Basic-Interpreterschleife verzweigt.
    So könnte man dann natürlich auch Basic-Zeilen/Befehle direkt in den Assemblercode einfügen.


    Schönen Gruß.