Wenn man mehr als reiner RISC OS Anwender sein möchte, wird man früher oder später programmieren wollen. Hier ein kurzer Einblick in die RISC OS Programmierung.
Wenn man unter RISC OS programmiert, möchte man sicherlich auch Desktopprogramme schreiben oder zumindestens Betriebssytemroutinen nutzen. Die Desktopprogrammierung fast man unter dem Begriff Wimp zusammen. Wimp bedeutet Windows, Icons, Mouse und Pointer, also Fenster, Symbole, Maus und Zeiger. Die Betriebssytemroutinen von RISC OS spricht man normalerweise über sogenannte Software Interrupts (SWI) auf. Die SWI haben alle eine eindeutige Nummer über die man sie aufruft. Damit sich Programmierer nicht nur Zahlen merken müssen, haben diese SWI Nummern einen Namen über die man sie auch aufrufen kann. Über ARM Register werden die benötigten Parameter übergeben und die Ergebnisse zurückgegeben. Ein Register ist eine Speicherstelle im Prozessor. Bevor man sich der Wimp Programmierung zuwendet, sollte man schon etwas Erfahrung mit einer Programmiersprache haben. Folgende Beispielprogramme drucken den Buchstaben "A" auf dem Bildschirm aus. In BASIC oder C würde man ein "A" natürlich mit PRINT bzw. printf() ausgeben und vermutlich wird dann intern auch der hier genutzte SWI OS_WriteC benutzt. Alle Beispielprogramme sind vollständig und können hier herunterladen (74,3 kByte) werden.
BASIC:
SYS "OS_WriteC", 65
C (GCC):
#include "kernel.h"
#include "swis.h"
int main(void) {
_kernel_swi_regs regs;
regs.r[0] = 65;
_kernel_swi(OS_WriteC, ®s, ®s);
return 0;
}
Assember (in BASIC eingebettet):
DIM code% 32 P% = code% [ OPT 2 MOV R0, #65 SWI "OS_WriteC" MOV PC, R14 ] CALL code%
Einen Buchstaben auszugeben ist natürlich ein extrem einfaches Beispiel. In allen Beispielprogrammen wird der Wert 65 in das Register R0 geschrieben. Der Wert 65 entspricht dem Zeichen "A". Dann wird der Software Interrupt OS_WriteC aufgerufen. Dieser SWI nimmt den Wert aus R0 und gibt das entsprechende Zeichen auf dem Bildschirm aus. Wenn man in C größere Programme schreibt, würde ich auf alle Fälle eine Wimp-Library wie OSLib oder DeskLib einsetzen, statt _kernel_swi() zu benutzen.
DIM blk% 256 blk%!0 = 999 $(blk%+4) = "Klick mal!" + CHR$(0) SYS "Wimp_ReportError", blk%, 19, "KlickMal" TO , result% PRINT result%
Dieses winzige BASIC Programm zeigt ein Fehlerfenster an und gibt je nach dem auf welche Schaltfläche man geklickt hat die Zahl zwei oder eins aus. Wimp_ReportError bekommt über Register R0 bis R2 einige Daten übergeben und gibt im Register R1 zurück welche Schaltfläche angeklickt wurde. Der Text, der im Fehlerfenster angezeigt werden soll, wird in einen Datenblock abgelegt. Ab dem vierten Byte dieses Blockes steht der Text und muß mit dem Wert Null beendet werden. Die Anfangsadresse dieses Datenblocks wird in Register R0 angegeben. In R1 wird angegeben wie das Fehlerfenster aussehen soll und in R2 steht der Title des Fensters. Der SWI Wimp_ReportError gibt dann im Register R1 an welche Schaltfläche geklickt wurde. Dieser Wert wird im BASIC Programm in die Variable result% geschrieben und ausgegeben. In diesen kleinen Programm werden drei Werte an den SWI übergeben und einer zurückgegeben.
Folgendes Beispiel ist etwas größer und für die besser Übersicht steht am Anfang jeder Zeile eine Zeilennummer. Im realen BASIC Programm sind keine Zeilennummern notwendig.
01: REM Multitasking Beispiel 02: : 03: REM Fehler anzeigen 04: ON ERROR PRINT "Fehler in Zeile "; ERL; ": "; REPORT$: END 05: : 06: REM Datenblock im Speicher reservieren 07: DIM blk% 256 08: : 09: REM Task anmelden 10: SYS "Wimp_Initialise", 200, &4b534154, "MultitaskBsp" TO , task% 11: : 12: REM Startzeit merken 13: start% = TIME 14: : 15: REM Oft wiederholen 16: i% = 1 17: WHILE(i% < 1000) 18: REM Schlafen gehen 19: SYS "Wimp_PollIdle", &1c9fffe, blk% TO event% 20: : 21: REM Ereignisse Auswerten 22: CASE event% OF 23: WHEN 0: REM Arbeiten! 24: PROCcalc(i%): 25: WHEN 17, 18: REM Beenden? 26: CASE blk%!16 OF 27: WHEN 0, 4: REM Ereignis ist Beenden 28: REM Abbruch der Schleife vorbereiten 29: i% = 99999999 30: ENDCASE 31: ENDCASE 32: : 33: REM Zaehler erhoehen 34: i% += 1 35: ENDWHILE 36: : 37: REM Laufzeit anzeigen 38: blk%!0 = 999 39: $(blk% + 4) = STR$((TIME - start%) / 100) + " Sekunden" + CHR$(0) 40: SYS "Wimp_ReportError", blk%, 17, "MultitaskBsp" 41: : 42: REM Task abmelden und beenden 43: SYS "Wimp_CloseDown", task% 44: END 45: : 46: REM Sinnlose Berechnung ausfuehren 47: DEF PROCcalc(i%) 48: LOCAL y, x, j% 49: : 50: x = SQR(i%) 51: y = 9.9 52: FOR j% = 1 TO 3000 53: x = ((x + SIN(ATN(COS(LOG(y / j%) * x))) / i%) / j%) 54: NEXT j% 55: ENDPROC
Ich gehe jetzt nicht auf jede Zeilen einzelnd ein, sondern konzentriere mich auf die Wimp Programmierung. Das Programm wird in Zeile 10 in RISC OS angemeldet und erscheint damit auch im Taskmanager. In R0 wird Wimp_Initialise mitgeteilt, welche RISC OS Version zumindestens benötigt wird. Hier ist das RISC OS 2.00. Im nächsten Register wird immer die Zeichenfolge "TASK" als Zahl angegeben. In Register R2 gibt man den Namen des Programmes bekannt. Wimp_Initialise gibt in R1 die Tasknummer zurück die später zum Abmelden des Programmes benötigt wird. Nun folgt die While-Schleife von Zeile 17 bis 35 in der mehrfach die eigentliche Arbeit des Programmes geleistet wird.
Da RISC OS nur kooperatives Multitasking unterstützt muß jedes Programm von Zeit zu Zeit den Prozessor freigeben, damit andere Programme ihre Arbeit nachkommen können. Wird dies nicht gemacht, müssen alle Programme warten bis das unkooperative Programm fertig ist. In der Zeit hat der Benutzer den Eindruck das der Rechner eingefroren ist und kann nichts anderes tuen als warten. Um das zu verhindern müssen sich Programme selbst von Zeit zu Zeit schlafen legen und warten bis es wieder an der Reihe ist. Das Programm wird über ein Ereignis benachrichtigt das es weiter arbeiten darf. Weitere Ereignisse sind z. B. ein Klick auf eine Schaltfläche, das Schliesen eines Fensters oder das Beenden des Programmes. RISC OS sorgt dafür das nur Ereignisse das Programm erreichen, die auch für das Programm gedacht sind. Mit einer Maske kann man zusätzlich verhindern das unerwünschte Ereignisse auftretten. All das passiert in der Zeile 19 des Programmes.
In R0 wird die Ereignisnummer zurückgegeben und hier in die Variable event% geschrieben. In der folgende Case-Anweisung wird das Ereignis ausgewertet. Wenn die Variablen event% den Wert Null hat (Zeile 23), dann wird unser Programm dazu aufgefordert zu arbeiten. Dies wird dann auch über die Prozedur PROCcalc gemacht. In dieser Prozedure wird hier einfach nur sinnlos Rechnenzeit verschwendet, es ist ja nur ein Beispiel. Im anderen When-Zweig (Zeile 25) wird auf die Aufforderung das Programm zu beenden reagiert und dafür gesorgt, daß die While-Schleife beendet wird. Hier wird nicht nur das Ereignis (17 oder 18) betrachtet, sondern auch der Datenblock (blk%) untersucht (Zeile 26). Ist das 16. Byte eine Null oder Vier soll das Programm beendet werden. Wenn die maximale Rundenzahl (rounds%) noch nicht erreicht wurde und das Programm nicht beendet werden soll, wird in der Zeile 19 wieder die CPU an ein anderes Programm übergeben usw.
Kurz bevor das Programm sich beendet, wird in einen Fehlerfenster die Laufzeit des Programmes angezeigt (38 bis 40). Direkt nachdem dieses Fenster geschlossen wurde, wird das Programm abgemeldet (43) und beendet (44).
Ich hoffe man hat einen Eindruck davon bekommen, wie man in RISC OS programmiert. Ich spaare mir eine C oder Assemberversion des Programmes, da es sich nicht wessentlich von dem BASIC Programm unterscheiden würde. Wie man ein Programm auf die Iconbar bringt, mit Fenster hantiert usw. sollte in einer tiefergehende Einführung nachgelesen werden.
Beispielprogramme herunterladen (74,3 kByte)
Weiter mit Programmierkurse