Unbekannten Compiler entdeckt

Es gibt 191 Antworten in diesem Thema, welches 31.064 mal aufgerufen wurde. Der letzte Beitrag (23. Mai 2024 um 20:54) ist von muffi.

  • Kompatibilität und Geschwindigkeit scheinen sich auszuschließen. Wollen wir ein schnelles BASIC oder wollen wir, dass der Compiler alles bestehende frisst. Alles Bestehende haben wir ja: Austro Compiler

    Mir schwebt eher etwas vor, das eine erweitertes v2 BASIC Syntax kann. Wenn man wirklich schnell werden will, muss man halt "speziell" in BASIC coden.

    ...

    Vorschläge für die erste Version:

    optimierter P-Code für alle BASIC Befehle

    P-Code und Geschwindigkeit schließen sich ja auch aus. Deshalb wäre es doch konsequenter reinen Maschinencode zu generieren.

  • P-Code und Geschwindigkeit schließen sich ja auch aus. Deshalb wäre es doch konsequenter reinen Maschinencode zu generieren.

    Da würde ich ganz klar "Jein" dazu sagen - siehe dazu meine Compiler-Benchmarks. Der P-Code ist teilweise gar nicht so viel langsamer, spart in der Regel aber Platz. Nicht jeder berechnet Apfelmännchen, aber da muss man komplett selber ran, so dramatisch kann ein Compiler die Berechnung gar nicht beschleunigen, dass es auch nur ansatzweise an selbst programmierten Code ran kommt.

    Früher waren 64k unglaublich viel, heute reicht es nicht mal mehr für "Hello, world!".

  • Da würde ich ganz klar "Jein" dazu sagen - siehe dazu meine Compiler-Benchmarks. Der P-Code ist teilweise gar nicht so viel langsamer, spart in der Regel aber Platz. Nicht jeder berechnet Apfelmännchen, aber da muss man komplett selber ran, so dramatisch kann ein Compiler die Berechnung gar nicht beschleunigen, dass es auch nur ansatzweise an selbst programmierten Code ran kommt.

    Ohne mich jetzt im Detail mit Basic-Compilern auseinander gesetzt zu haben, vermute ich, dass bei einem Assembler-Kompilat einfach JSR hintereinander stehen. Und vorher irgendwelche Zeiger auf Parameter geladen werden. Während bei einem P-Code-Kompilat Bytecodes hintereinander stehen und vermutlich dahinter die Parameter. Über den Bytecode die Sprungadresse für den Befehl zu ermitteln und auszuführen. dürfte nicht so entscheidend langsamer sein. Jedenfalls im Verhältnis zur Ausführung der Befehle.

    Also wenn bei beiden Verfahren die Parameter gleich gut aufbereitet und optimiert sind, würde ich keinen großen Geschwindigkeitsunterschied erwarten.

    Bei beiden Verfahren braucht man eine Library für die Befehle, deren größe davon abhängt, in wie weit ROM-Routinen verwendet werden.

    Also so stelle ich mir die Funktionsweise vor. Korrigiert mich bitte, wenn ich falsch liege.

  • Also so stelle ich mir die Funktionsweise vor. Korrigiert mich bitte, wenn ich falsch liege.

    Im Großen und Ganzen kann man es schon darauf herunter brechen (wobei im M-Code nicht nur JSR aneinander stehen). Compilerbau ist natürlich eine deutlich kompliziertere Disziplin, EgonOlsen71 kann da mit Sicherheit ein Lied davon singen ;) Auch Deine Ausführung über die Runtime ist logisch hergeleitet und auch richtig so.

    Der einzige, mir bekannte Compiler, den man umstellen kann zwischen P- und M-Code ist der Basic64/128.

    Früher waren 64k unglaublich viel, heute reicht es nicht mal mehr für "Hello, world!".

  • P-Code und Geschwindigkeit schließen sich ja auch aus. Deshalb wäre es doch konsequenter reinen Maschinencode zu generieren.

    Naja, reiner Maschinencode, da wird das Kompilat ziemlich groß.

    Dann kann das BASIC Programm nicht mehr sehr groß sein, wenn das Ergebnis in 64K laufen soll ...

    Es sei denn, man hat fast unbegrenzt Platz.

    Eine Cartridge mit 512K die den Code enthält, dann spielt Größe keine Rolle mehr.


    Ansonsten sollte man wählen können ob M oder P-Code.

    In vielen Fällen reicht die Geschwindigkeit von P-Code leicht.

    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.

  • Ohne mich jetzt im Detail mit Basic-Compilern auseinander gesetzt zu haben, vermute ich, dass bei einem Assembler-Kompilat einfach JSR hintereinander stehen. Und vorher irgendwelche Zeiger auf Parameter geladen werden. Während bei einem P-Code-Kompilat Bytecodes hintereinander stehen und vermutlich dahinter die Parameter.

    Ein JSR nach dem anderen, da ist P-Code wirklich fast gleich schnell.

    Aber der Platz ist enorm bei m-Code:

    LDA #<PARxxx

    LDX #>PARxxx

    JSR Fxxx

    Macht 7 Bytes bei einem 16 Bit Argument.

    In P-Code nur 3 Bytes:

    .byte TOKENxxx

    .word PARxxx

    ====

    Geschwindigkeit holt man, wenn man direkt etwas errechnet, vor allem dann wenn man 8 Bit Operationen zu lässt.

    Die 16 Bit Operationen brauchen in M-Code wiederum viel Platz, auch da hat P-Code die Nase vorn.

    Das Problem ist halt, in Standard BASIC v2 kann man dem Compiler nicht sehr gut "helfen".

    Bei C gibt es Byte Variable, und wenn man die nutzt kann man das auch sehr gut in M-Code umwandeln.

    Man müsste halt das BASIC v2 ein bisschen erweitern.

    Dann könnte man manche Teile gut in M-Code übersetzen lassen.

    Ein Compiler könnte natürlich auch selbsttätig eine Mischung aus P und M-Code generieren.

    Je nach Abschnitt mag es da oder dort Vorteile geben.


    Ich denke BASIC ist halt speziell sehr gut geeignet für P-Code.

    Und man kann auch gut leben mit P-Code, wenn man da und dort etwas M-Code dazu mischt.


    Aber andere Sprachen würde man sicher gut bei einem 8 Bitter laufen, zB. Forth

    Und bei FORTH (wie bei allen Stack orientierten Sprachen) könnte man auch ganz gut beide Varianten unterstützen, P- und M-Code.

    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.

  • Das Problem ist halt, in Standard BASIC v2 kann man dem Compiler nicht sehr gut "helfen". ... Man müsste halt das BASIC v2 ein bisschen erweitern.

    Hattest weiter oben ja auch vorgeschlagen, die vollständige Kompatibilität zu Basic V2 aufzugeben. Welche alten Zöpfe müssten dann dran glauben? Die neue Syntax wäre ja strikter, damit sie kompilierfreundlicher wird

  • Hattest weiter oben ja auch vorgeschlagen, die vollständige Kompatibilität zu Basic V2 aufzugeben. Welche alten Zöpfe müssten dann dran glauben? Die neue Syntax wäre ja strikter, damit sie kompilierfreundlicher wird

    Naja ich denke "aufgeben" müsste man die Kompatibilität gar nicht.

    Da denke ich mehr an einer "Erweiterung" des BASIC v2 Sprachumfang.

    Es ist halt so, dass man dann zwar jedes v2 BASIC kompilieren könnte.

    Aber das Ergebnis ist dann halt auch nicht besonders gut.


    Wenn man A = B *2 schreibt, dann führt das halt unweigerlich zu einer FLOAT Multiplikation die halt natürlich langsam ist.

    Wenn man A% = B% *2 schreibt, dann kann ein guter Compiler schon mal eine 16 Bit Integer Multiplikation machen.

    Ein sehr guter Compiler wandelt das vielleicht schon in zwei ROL Befehle um.

    Wenn man 8 Bit Variable einführt, zb. mit dem Zeichen "!", dann wird es vielleicht sogar mit einem einzigen Befehl umgesetzt: ROL variable

    Die 8 Bit Variable wären ein entscheidender Vorteil.

    Der Compiler könnte Addition, Subtraktion direkt durchführen, Byte oder Char Arrays könnten über Y indizierte Befehle zugegriffen werden.


    Der BASIC Programmierer muss dazu nicht viel wissen.

    Er muss nur wissen, welche Zahlen in der Variable gespeichert werden.

    Ob Ganzzahl ausreicht oder nicht.

    Ob Werte von -32768 bis 32758 reichen.

    Ob Werte eh innerhalb von 0 bis 255 bleiben werden.

    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.

  • Wenn man A% = B% *2 schreibt, dann kann ein guter Compiler schon mal eine 16 Bit Integer Multiplikation machen.

    Was passiert dann bei A% = B% * C ?

    Da habe ich jetzt Float und Integer in einem Ausdruck. Verbieten? Oder die gesamte Formalauswertung neu schreiben. Das wird allerdings einigen Platz brauchen. Und das ist nicht trivial.

    Oder gibt es schon Basic-Compiler, die die Formelauswertung sowieso selber machen, damit sie z. B. Konstanten optimiert ablegen können?

    Bitte melde dich an, um diesen Link zu sehen.

    Einmal editiert, zuletzt von detlef (27. Dezember 2021 um 16:21)

  • Wenn man A = B *2 schreibt, dann führt das halt unweigerlich zu einer FLOAT Multiplikation die halt natürlich langsam ist.

    Nein, nicht zwangsläufig. Du kannst auch mit Floats Multiplikationen mit Zweierpotenzen eleganter behandeln, indem du einfach den Exponenten modifizierts. MOSpeed macht aus:

    Code
    a%=10:c%=a%*2

    z.B. das hier:

    Das ist natürlich nicht so effizient wie ein Integer-Shift, aber besser als eine richtige Multiplikation. Das macht er auch für populäre Multiplikationen wie z.B. mit *40 oder *320. Ersetzt durch die Addition zweier solcher "Pseduoshifts" ist das immer noch schneller als eine Multiplikation. Aber eben auch länger...

    Was passiert dann bei A% = B% * C ?

    Da habe ich jetzt Float und Integer in einem Ausdruck. Verbieten? Oder die gesamte Formalauswertung neu schreiben. Das wird allerdings einigen Platz brauchen. Und das ist nicht trivial.

    Es ist nicht nur das. Man könnte ja sagen, dann müssen eben alle Elemente Integer sein und gut ist. Aber selbst dann stimmt die Annahme nicht, man könne dann immer komplett mit Integer rechnen. Zumindest dann nicht, wenn man zum Interpreter kompatibel sein will. Beispiel:

    Code
    b%=4000:c%=20:d%=30:a%=(b%*c%)/d%

    Das liefert im Interpreter 2666, weil er intern mit Floats rechnet. Rechnet man hier durchgehend mit Integer, dann überschreitet das temporär den gültigen Zahlenbereich und es kommt Quatsch heraus. Wenn einem das egal ist, kann man das natürlich so machen. Ich persönlich frage mich dann aber immer, wieso man das arme BASIC so verschwurbeln will und nicht einfach gleich eine andere Sprache nimmt.

    Zitat

    Oder gibt es schon Basic-Compiler, die die Formelauswertung sowieso selber machen, damit sie z. B. Konstanten optimiert ablegen können?

    Natürlich, meinen...;) Wenn du da dieses Programm reinkippst:

    Code
    10 a%=10:c%=a%*2:print c%

    ...dann kommt das hier heraus:

    Da ist gar keine Berechnung mehr drin, auch kein A oder C. Nur noch eine Konstante 20, die ausgegeben wird. Das ist aber natürlich ein sehr einfaches Beispiel. Aber das heißt eben auch, dass aus sowas:

    Code
    10 v=53248:poke v+21,35:poke v+18,45

    Dann sowas wird:

    Code
    LINE_10:
    ;
    LDY #35
    STY 53269
    LDY #45
    STY 53266
    JSR END
    RTS

    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.

  • Da habe ich jetzt Float und Integer in einem Ausdruck. Verbieten?

    Das Ergebnis ist Integer.

    Insofern ist es sinnvoll, alle Teilwerte auf Integer zu reduzieren.

    C macht das so, wenn man keine Cast verwendet.

    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.

  • Das Ergebnis ist Integer.

    Insofern ist es sinnvoll, alle Teilwerte auf Integer zu reduzieren.

    C macht das so, wenn man keine Cast verwendet.

    Nein, C würde diese Rechnung als float machen.

    Yes, I'm the guy responsible for the Bitte melde dich an, um diesen Link zu sehen. cross assembler. And some Bitte melde dich an, um diesen Link zu sehen..

  • Das Ergebnis ist Integer.

    Insofern ist es sinnvoll, alle Teilwerte auf Integer zu reduzieren.

    C macht das so, wenn man keine Cast verwendet.

    Nein, C würde diese Rechnung als float machen.

    Genau. Und dann bei der Zuweisung in Integer umwandeln. ;)

    Und das war noch ein ganz einfaches Beispiel ohne Klammern. :D

    Natürlich ist es sinnvoll, Float aus den Formeln ganz rauszulassen, wenn es schnell gehen soll. Aber beim Mischen von 8 und 16 Bit Integern hat man wieder das gleiche Problem.

  • Naja ich denke "aufgeben" müsste man die Kompatibilität gar nicht.

    Da denke ich mehr an einer "Erweiterung" des BASIC v2 Sprachumfang.

    EInige Compiler wie z.B. BASIC64 und Basic Boss haben dafür Hinting. D.h. man schreibt sowas in Richtung "0 REM BYTE=I" vorne dran, und der Compiler weiß dann, dass die Variable I überall als Byte behandelt werden kann. So läuft das auch unter normalem Basic, und man muss nicht großflächig "%" hinzufügen, die Platz fressen, hässlich aussehen, ungenau sind (da Int16, aber man will ja auch UInt8=Byte und UInt16=Unsigned Word) und in normalem Basic V2 nicht immer gehen (z.B. als Laufvariable in FOR).

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

  • Ich persönlich frage mich dann aber immer, wieso man das arme BASIC so verschwurbeln will und nicht einfach gleich eine andere Sprache nimmt.

    Weil der Sinn von insbesondere Basic-Compilern (auch) ist, existierende Software auf "Best Effort"-Basis schnell zu bekommen. Ich würde sogar fast dazu neigen, dass das der ausschließliche Sinn von Basic-Compilern ist, denn tatsächlich geschwindigkeitskritische Software wird man tatsächlich nicht in Basic anfangen.

    Davon ab ist Basic an sich schon ein ziemlicher Hack, da macht noch ein Hack obendrauf wie das Ranbasteln von weiteren Typen den Braten auch nicht mehr fett, bzw. ich persönlich finde das sogar ganz nett. Hacks über Hacks sind doch genau das, was den (Reiz des) C64 ausmacht.

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

  • Weil der Sinn von insbesondere Basic-Compilern (auch) ist, existierende Software auf "Best Effort"-Basis schnell zu bekommen. Ich würde sogar fast dazu neigen, dass das der ausschließliche Sinn von Basic-Compilern ist, denn tatsächlich geschwindigkeitskritische Software wird man tatsächlich nicht in Basic anfangen.

    Genau so habe ich Basic-Compiler auch immer genutzt. Das Basic-Programm im Quelltext geschrieben und debuggt. Und wenn es lief, habe ich es durch den Compiler gejagt, damit es schneller wurde. Wenn's wirklich schnell werden sollte, habe ich von vorne herein in Assembler programmiert.

    Ich kann mir nicht vorstellen, wie ich auf dem 64er ein Programm entwickeln soll, dass ich jedes mal durch den Compiler jagen muss, damit ich es testen kann (kommt jetzt bitte nicht mit Vice. Dann nehme ich gleich eine Cross-Entwicklungsumgebung nehmen).

    So ein Compiler mit Basic-Erweiterung ist eine nette Herausforderung und es ist toll, wenn der in den Benchmarks nachher ganz oben steht. Aber wirklich benutzen wird ihn dann wohl kaum jemand. Befürchte ich jedenfalls.

  • Hier nur mal nebenbei ein D64 von der VC-20 Version des Tiny Basic Compiler. Benötigt entweder +3 KB oder +8 KB und höher.

    Vom cbm-warrior habe ich eine Kopie der Anleitung bekommen. Die Qualität war dermaßen grottenschlecht, dass wir uns entschlossen haben, das Handbuch für die Nachwelt mal abzutippen und damit zu erhalten. Viel Spaß damit :smile:

    Kann natürlich sein, dass ich noch Tippfehler drin habe. Wer welche findet, kann sie behalten :thumbsup:

  • Ich habe hier ein pdf gefunden, dass einen weiteren, zumindest für mich unbekannten Compiler enthält. Er heißt Insta-Speed und ist von Drive Technology ltd. Ein Image habe ich in meinem Softwarearchiv dafür leider nicht gefunden. Vielleicht hat jemand ein D64 davon? Könnte allerdings sein, dass das ein Spezial-Compiler für das DTL-Basic 64 ist, denn das wird im Manual explizit erwähnt. Somit dürfte eine Verwandschaft mit dem DTL-Compiler bestehen.

    Früher waren 64k unglaublich viel, heute reicht es nicht mal mehr für "Hello, world!".

  • muffi Vielleicht das hier was Du suchst :

    Bitte melde dich an, um diesen Link zu sehen.

    Bitte melde dich an, um diesen Link zu sehen.

  • @1Byte Auf csdb hatte ich tatsächlich nicht nachgesehen (da ist er anscheinend aber auch nicht), aber Deine Links sind zum DTL-Basic. Der Insta-Compiler scheint aber der Compiler dafür zu sein. Wahrscheinlich nicht zu verwechseln mit dem DTL-Compiler.

    Früher waren 64k unglaublich viel, heute reicht es nicht mal mehr für "Hello, world!".