Basic und MaschinencodeParameterWird eine Assembler-Routine aufgerufen, so können an sie bis zu 32 Basic und Maschinencode: ParameterParameter übergeben werden. Dabei ist es egal, ob der Aufruf via Maschinencode über HIMEM: RSXRSX oder mit Maschinencode über HIMEM: CALLCALL erfolgte: Maschinencode über HIMEM: CALLCALL box, 100,200,300,400
|BOX, 100,200,300,400
Als Basic und Maschinencode: ParameterParameter kommen allerdings nur Integer-Werte in Frage, und die Parameter: Parameter-ÜbergabeParameter-Übergabe funktioniert auch nur in die eine Richtung: Von Einleitung: BASIC Jeder Basic und Maschinencode: ParameterParameter kann im Bereich -32768 bis +65535 liegen (Im Die Firmware des Schneider CPCFirmware Manual wird als Obergrenze +32767 angegeben, was aber nicht stimmt). Diese werden als 16-Bit-Words an die Mcode-Routine übergeben. Integer-Variablen sind 16-Bit-Words mit Vorzeichen und können Zahlenwerte von -32768 bis +32767 darstellen. Es ist aber auch möglich, Datenbreite: WordsWords ohne Vorzeichen im Bereich von 0 bis 65535 zu übergeben. Dabei ist auf die Doppeldeutigkeit der negativen Zahlen zu achten: Integer (mit VZ): 0 --- 32767 /-32768 --- -1 ohne Vorzeichen: 0 --- 32767 / 32768 --- 65535 Die Übergabe an die Maschinencode-Routine wird vom Schneider-Basic wie folgt realisiert. Diese Methode ist zwar nicht verbindlich und, wegen ihrer Einschränkungen, auch nicht besonders galant. Trotzdem sollte sie, um die Kompatibilität zu wahren, auch von anderen Vordergrund-Programmen so gehandhabt werden: Parameter-ÜbergabeIm A-Register wird der Routine die Anzahl der übergebenen Basic und Maschinencode: ParameterParameter mitgeteilt. Die Basic und Maschinencode: ParameterParameter befinden sich auf einem Stapel (und zwar auf dem Hardware-Stack, was für den Anwender aber uninteressant ist). Der erste Basic und Maschinencode: ParameterParameter liegt dabei an der obersten Adresse und das IX-Register zeigt auf das LSB (unterstes Datentypen: Bytes Die Tonausgabe: Das Kontrollregister (Reg. 7) Parameter-ÜbernahmeDie Mcode-Routine kann nun über das IX-Register auf die übergebenen Basic und Maschinencode: ParameterParameter zugreifen: ROUT1: CP 2 ; Erklärung der Anschlussbelegung: TestTest, ob Anzahl Basic und Maschinencode: ParameterParameter stimmt (hier 2) RET NZ ; Nein: Der Linien-Algorithmus: Fehler 3Fehler. LD L,(IX+0) LD H,(IX+1) ; HL = letzter ( = zweiter) Basic und Maschinencode: ParameterParameter LD LOW KERNEL JUMPBLOCK: 000E: LOW PCBC INSTRUCTION Dass das IX-Register immer auf den letzten übergebenen Basic und Maschinencode: ParameterParameter zeigt, ist für all diejenigen Routinen ungünstig, die eine veränderliche Anzahl an Argumenten übernehmen können. Dabei sind nämlich in aller Regel die hinteren Basic und Maschinencode: ParameterParameter optional. Der Zugriff auf die tatsächlich im Aufruf angegebenen Basic und Maschinencode: ParameterParameter ist dann erschwert, weil hier zum IX-Register ein anderer Erklärungen zu den Anschlussbezeichnungen: INDEXIndex addiert werden müsste. Das Problem kann man wie folgt angehen: ; Beispiel: Routine nimmt 2 oder 3 Basic und Maschinencode: ParameterParameter: ; ROUT2: CP 2 ; Erklärung der Anschlussbelegung: TestTest, ob mind. 2 Argumente RET C ; Nein: Der Linien-Algorithmus: Fehler 3Fehler ; LD BC,#0001 ; Default-Annahme für dritten Basic und Maschinencode: ParameterParameter machen CP 3 ; Erklärung der Anschlussbelegung: TestTest, ob dritter Basic und Maschinencode: ParameterParameter angegeben ist. JR C,ROUT2A ; Nein, nur zwei -> Default übernehmen. ; RET NZ ; Der Linien-Algorithmus: Fehler 3Fehler, falls nicht 3 (also mehr als 3) Basic und Maschinencode: ParameterParameter ; LD C,(IX+0) LD LOW KERNEL JUMPBLOCK: 000B: LOW KL LOW PCHL Übergabe von FließkommazahlenObwohl man an Mcode-Routinen eigentlich nur Integerzahlen übergeben kann, ist es mit einem kleinen Trick trotzdem möglich, auch Real-Zahlen oder Datentypen: StringsStrings zu übergeben. Man speichert den Wert einfach in einer Unterprogramme: VariablenVariablen und übergibt dann deren Adresse an das aufgerufene Programm: 100 Operationen: BD5B / 349A / 349A: FLO SUBa!=123.45 110 LOW KERNEL JUMPBLOCK: 000B: LOW KL LOW PCHL Da die Rechenroutinen der Fließkomma-Arithmetik sowieso immer die Zeiger auf die zu bearbeitenden Zahlen benötigen, ist das geradezu ideal. Man muss nur beachten, dass die Unterprogramme: VariablenVariablen möglicherweise (und bei kurzen Basic-Programmen ziemlich sicher) im untersten Speicherviertel liegen. Die Rechenroutinen blenden aber das untere RAM aus, weil sie selbst im Betriebssystems-ROM liegen. Die Routinen der Fließkomma-Arithmetik funktionieren nicht im unteren RAM-Viertel. Hier muss man die Zahlen zunächst immer in Zwischenspeicher über &4000 kopieren, bevor man mit ihnen rechnen kann. Übergabe von StringsBei Datentypen: StringsStrings funktioniert es genauso. Nur dass man jetzt die Adresse des Descriptors einer String-Variablen übergeben muss. Dabei wurde beim 664/6128-Einleitung: BASIC 100 Operationen: BD5B / 349A / 349A: FLO SUBa$="TESTTESTTEST" 110 |Maschinencode über HIMEM: RSXRSX,@Operationen: BD5B / 349A / 349A: FLO SUBa$ <-- CPC 464 110 |Maschinencode über HIMEM: RSXRSX, Operationen: BD5B / 349A / 349A: FLO SUBa$ <-- CPC 664/6128 -----> ROUT4: CP 1 RET NZ ; Parameterzahl Erklärung der Anschlussbelegung: Testtesten ; LD L,(IX+0) LD H,(IX+1) ; HL = @Operationen: BD5B / 349A / 349A: FLO SUBa$ = Adresse des Descriptors ; LD Operationen: BD5B / 349A / 349A: FLO SUBA,(HL) ; Operationen: BD5B / 349A / 349A: FLO SUBA = Länge des Datentypen: StringsStrings INC HL LD LOW KERNEL JUMPBLOCK: 000E: LOW PCBC INSTRUCTION Übernahme von ErgebnissenMit Hilfe des Variablenpointers '@' ist es auch möglich, wieder Ergebnisse von einer Assembler-Routine zurückzubekommen. Man übergibt, eventuell zusätzlich zu den Parametern für die Routine, die Adresse einer Rücknahme-Variable. Diese kann von jedem beliebigen Typ sein. Der Typ muss nur mit dem Grundlagen: UnterprogrammeUnterprogramm eindeutig vereinbart werden, weil man in der Mcode-Routine keine Möglichkeit hat, zu überprüfen, was man da an Parametern übergeben bekommen hat: |Maschinencode über HIMEM: RSXRSX ,100 ,@i% ,@Operationen: BD5B / 349A / 349A: FLO SUBa! ,@s$ ---> einen Zahlenwert oder die Adresse einer Integer-Variablen oder die Adresse einer Real-Variablen oder die Adresse einer String-Variablen. Das ist besonders kritisch, wenn das Maschinencode-Programm die adressierte Unterprogramme: VariablenVariable ändern will. Stimmt da der Typ nicht, oder ist es noch nicht einmal die Adresse einer Unterprogramme: VariablenVariable, kann die Speicher-Organisation des Basic-Interpreters recht schnell und recht gründlich durcheinander geraten. Übernahme eines Integer-Ergebnisses100 i%=0 110 |Maschinencode über HIMEM: RSXRSX,100,200,@i% 120 PRINT i% ----> RSX5: CP 3 RET NZ ; Parameterzahl überprüfen. ; LD L,(IX+2) LD H,(IX+3) ; zweitletzter = zweiter Basic und Maschinencode: ParameterParameter LD LOW KERNEL JUMPBLOCK: 000E: LOW PCBC INSTRUCTION Bei Fließkommazahlen und Datentypen: StringsStrings funktioniert es entsprechend, nur dass man hier 5 bzw. 3 Datentypen: Bytes 100 LET Operationen: BD5B / 349A / 349A: FLO SUBa$="abcde" ' <-- Descriptor zeigt in den Programmtext!! 100 LET Operationen: BD5B / 349A / 349A: FLO SUBa$="abcde"+"" ' <-- Einleitung: BASIC |