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.

TastaturWenn 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, &regs, &regs);

        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

BeispielprogrammIch 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


Startseite   Kontakt   Links   Inhalt