Basic und MaschinencodeMaschinencode im StringEher selten wird dabei die Möglichkeit benutzt, Mcode-Routinen in ein Datentypen: StringsString einzuladen. Der Grund ist, dass die Lage von Datentypen: StringsStrings nicht nur nicht vorhersehbar ist, sondern sich nach einer Strings: Garbage CollectionGarbage Collection auch ändern kann! Routinen in Datentypen: StringsStrings müssen deshalb ortsunabhängig sein, was bei Assembler-Programmen nur in den seltensten Fällen zu erreichen ist. Außerdem stehen noch einige andere Einschränkungen und Probleme im Weg: So ist beispielsweise die maximale Länge solcher Programme durch die maximale Stringlänge auf 255 Datentypen: Bytes Auch bereitet es zunächst einmal Schwierigkeiten, den Maschinencode überhaupt in den Datentypen: StringsString hineinzubekommen. Die folgende Methode ist leider in den meisten Fällen ungeeignet: OPENIN "mcode.dat" LINE INPUT#9, mcode$ CLOSEIN Das liegt daran, dass die ASCII-Zeichen mit dem Code 13 und 26 als Die Tastatur: Steuerzeichen des Key Managers und des ZeileneditorsSteuerzeichen aufgefasst und Real: NullNull ganz ignoriert und nicht eingelesen wird. Die Chance, dass eine Assemblerroutine rein zufällig diese Datentypen: Bytes Man muss deshalb einen Kunstgriff anwenden, um den Maschinencode doch noch in den Datentypen: StringsString zu bekommen. Eine Möglichkeit ist, ihn aus DATA-Zeilen auszulesen und in einen Datentypen: StringsString zu POKEn. Der Platzverbrauch für Data-Zeilen ist aber immer unverhältnismäßig hoch. Man kann die Programmdatei aber auch trotzdem von Diskette einladen: 10 adr=HIMEM-255:MEMORY adr-1 20 LOAD "mcode.bin",adr 30 mcode$="":POKE @mcode$ ,prog.länge <-- String-Länge POKE @mcode$+1,adr-256*Alle noch folgenden Anschlüsse fallen unter die Rubrik STEUER- oder auch CONTROLBUS:: INT - Interrupt In Zeile 10 wird zunächst über Die Aufteilung des RAM durch den Basic-Interpreter: Chaos über HIMEMHIMEM genügend Platz frei gemacht, um die Programmdatei aufzunehmen. Diese wird dann in Zeile 20 auch dorthin geladen. In Zeile 30 wird der Datentypen: StringsString dann eingerichtet, und der String-Descriptor, dessen Adresse man mit der Die Fließkomma-Routinen: FunktionenFunktion '@' erhält, so umgePOKEt, dass er auf den Maschinencode zeigt. Durch die Berechnung eines 'neuen' Mcode-Strings in Zeile 40 wird der Datentypen: StringsString im Memory Pool neu angelegt. Das ist wichtig, damit der Datentypen: StringsString die nächste Strings: Garbage CollectionGarbage Collection überlebt. In Zeile 50 wird zum Schluss der Puffer über Die Aufteilung des RAM durch den Basic-Interpreter: Chaos über HIMEMHIMEM wieder geschlossen. Man hat aber nicht nur Probleme, den Mcode in den Datentypen: StringsString hineinzubekommen, auch sein Aufruf erweist sich als problematisch. Wenn man nicht mit viel Aufwand eine Strings: Garbage CollectionGarbage Collection sicher ausschließen kann, muss man vor jedem Aufruf der String-Routine die Adresse neu berechnen. Das kann mit der folgenden Die Fließkomma-Routinen: FunktionenFunktion aber noch recht komfortabel erreicht werden: 60 DEF FNmcode=PEEK(@mcode$+1)+256*PEEK(@mcode$+2)
....
....
500 Maschinencode über HIMEM: CALLCALL FNmcode
Die Die Fließkomma-Routinen: FunktionenFunktion FNmcode PEEKt sich die aktuelle Adresse des Datentypen: StringsStrings immer aus dem String-Descriptor heraus. Hat man mehrere String-Routinen, so kann man für jede eine eigene Function definieren. Die String-Methode hat aber auch Vorteile. So kann man Überschneidungen zwischen verschiedenen Routinen sicher ausschließen und Routinen, die nicht mehr benötigt werden, können jederzeit aus dem Speicher gelöscht werden: 999 mcode$="" |