Writing applications for KolibriOS: Difference between revisions
No edit summary |
|||
(19 intermediate revisions by 5 users not shown) | |||
Line 1: | Line 1: | ||
= Structure of an application = | |||
KolibriOS's application structure is not specifically reserved for asm programming, the header can be produced with practically any other language. However, the overall application programming design is intended for easy 32 bit asm programming. The GUI is extremely easy to handle with especially asm language. | |||
Programming for KolibriOS is easy as you first learn the basic structure of an application. At this point I assume you have some experience in assembly language.<br> | |||
Programming for KolibriOS is easy as you first learn the basic structure of an application. At this point I assume you have some experience in assembly language. | The KolibriOS API (Application Programming Interface) is an easy-to-learn set of functions with practically no hierarchical accesses. | ||
The KolibriOS API (Application Programming Interface) is | The operating of an application is based on events. The application is notified by the OS with the event type and the application acts accordingly.<br> | ||
There are three event types an application is expected to handle by default: window redraw, keypress and buttonpress. | |||
The operating of an application is based on events. | |||
The application is notified by the OS with the event type and the application acts accordingly. There are three event types an application is expected to handle by default: window redraw, keypress and buttonpress. | |||
Flow chart and structure of an application with default events: | Flow chart and structure of an application with default events: | ||
<syntaxhighlight> | |||
;;;;;;;;;;;;;;;;;;;;;;;;; | |||
; ; | |||
; HEADER DATA ; | |||
; ; | |||
KolibriOS | ;;;;;;::;;;;;;;;;;;;;;;;; | ||
START: | |||
< | call draw_window | ||
;;;;;;;;;;;;;;;;;;;;;;;;; | |||
; ; | |||
; WAIT UNTIL EVENT ; <-----------------------------------------------I | |||
; ; I | |||
;;;;;;;;;;;;;;;;;;;;;;;;; I | |||
; I | |||
;;;;;;;;;;;;;;;;;;;;;;;;; I | |||
; ; redraw -> call draw_window -> I | |||
; READ EVENT TYPE ; -> key -> read keypress -> process -> I | |||
; ; button -> read buttonpress -> process -> I | |||
;;;;;;;;;;;;;;;;;;;;;;;;; | |||
draw_window: | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
; ; | |||
; DRAW STATIC WINDOW PARTS ; | |||
; ; | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
ret | |||
;;;;;;;;;;;;;;;;;;;;;;;; | |||
; ; | |||
; STATIC DATA ; | |||
; ; | |||
;;;;;;;;;;;;;;;;;;;;;;;; | |||
</syntaxhighlight> | |||
= The header = | |||
<syntaxhighlight> | |||
db 'MENUET01' | |||
</syntaxhighlight> | |||
Since KolibriOS still is more or less API compatible with MenuetOS, it has the same header. There is also an older version of the header which uses 'MENUET00', but it should not be used anymore. | |||
<syntaxhighlight> | |||
dd 0x01 ; header version | |||
</syntaxhighlight> | |||
Speaks for itself. | |||
<syntaxhighlight> | |||
dd START ; start of execution | |||
</syntaxhighlight> | |||
START is the label in your program where kernel will jump to after loading the program. You could use another name, but it's convenient to always use the same. | |||
<syntaxhighlight> | |||
dd I_END ; size of image | |||
</syntaxhighlight> | |||
This is the total size of the program code in bytes, its easy to use a label which you place at the end of the code. | |||
<syntaxhighlight> | |||
dd 0x100000 | |||
</syntaxhighlight> | |||
This is the amount of ram that will be reserved for your app. You could use a static value as shown here, or you could use I_END + xx bytes. There, I_END would be the label to the end of code + all static declarations you made after the code. The xx bytes then are the number of bytes you want to use for the stack. Also note, this value can later be changed by using system functions. | |||
<syntaxhighlight> | |||
dd 0x100000 ; stack position in memory area | |||
</syntaxhighlight> | |||
Where the end of stack is (the value of esp at start of program). Logically, this would be the same as the previous value. | |||
<syntaxhighlight> | |||
dd 0x0 ; Parameters | |||
</syntaxhighlight> | |||
If you want to use parameters, this should be a pointer to a 1024 byte buffer, in which those parameters will be written by the kernel. If you don't want to use them, set this dword to 0. | |||
<syntaxhighlight> | |||
dd 0x0 ; Path | |||
</syntaxhighlight> | |||
Path value, works the same as parameter. | |||
= System calls = | |||
The System calls (API) are explained in various sources. There is the file syscalls.txt which you can find in KolibriOS itself, but also in the zip file of the distribution.< If you understand russian, you can also find system calls on this wiki. | |||
To execute a system call, you first need to fill the registers with the correct value. Say we want to wait a couple of milliseconds, we need to use system function 5 and place the time we want to wait in ebx. | |||
<syntaxhighlight> | |||
mov eax, 5 | |||
mov ebx, 10 | |||
</syntaxhighlight> | |||
Now, we need to execute the function, this can be done with int 0x40: | |||
<syntaxhighlight> | |||
int 0x40 | |||
</syntaxhighlight> | |||
But also with more modern instructions such as syscall, sysenter etc. It's convenient to use the mcall macro from macros.inc, then you can choose to use int 0x40 or another method, at compile time. This macro also accepts parameters, first is eax, second is ebx, ...<br> Code for the above would be: | |||
<syntaxhighlight> | |||
mcall 5, 10 | |||
</syntaxhighlight> | |||
= Coding Style = | |||
It's advisable to use the coding style, as described here: [[Style]] | |||
= The API = | |||
You can find the latest API documentation in /kernel/docs/ in the SVN repository ([http://websvn.kolibrios.org/listing.php?repname=Kolibri+OS&path=%2Fkernel%2Ftrunk%2Fdocs%2F WebSVN])<br> | |||
Inside KolibriOS, you can find sysfuncs.txt (english version) or sysfuncr (russian version) in DOCKPACK program.<br> | |||
These files also come with the so called distribution kit, in documents folder. | |||
= Assembly examples = | |||
Some examples are listed on this page, more can be found on the SVN server in the folder /programs/develop/examples/ ([http://websvn.kolibrios.org/listing.php?repname=Kolibri+OS&path=%2Fprograms%2Fdevelop%2Fexamples%2F WebSVN]) | |||
== Simple example == | |||
<syntaxhighlight> | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
; ; | ; ; | ||
Line 73: | Line 146: | ||
; ; | ; ; | ||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
format binary as "" ; Binary file format without extenstion | |||
use32 ; Tell compiler to use 32 bit instructions | |||
org 0x0 ; the base address of code, always 0x0 | |||
; The header | ; The header | ||
db 'MENUET01' | |||
dd 0x01 | |||
dd START | |||
dd I_END | |||
dd 0x100000 | |||
dd 0x7fff0 | |||
dd 0, 0 | |||
; The code area | |||
include 'macros.inc' | |||
START: ; start of execution | START: ; start of execution | ||
call draw_window ; draw the window | call draw_window ; draw the window | ||
; After the window is drawn, it's practical to have the main loop. | ; After the window is drawn, it's practical to have the main loop. | ||
; Events are distributed from here. | ; Events are distributed from here. | ||
event_wait: | event_wait: | ||
mov eax, 10 ; function 10 : wait until event | mov eax, 10 ; function 10 : wait until event | ||
mcall | mcall ; event type is returned in eax | ||
cmp eax, 1 ; Event redraw request ? | cmp eax, 1 ; Event redraw request ? | ||
je red ; Expl.: there has been activity on screen and | je red ; Expl.: there has been activity on screen and | ||
Line 123: | Line 184: | ||
je key ; Expl.: User has pressed a key while the | je key ; Expl.: User has pressed a key while the | ||
; app is at the top of the window stack. | ; app is at the top of the window stack. | ||
cmp eax, 3 ; Event button in buffer ? | cmp eax, 3 ; Event button in buffer ? | ||
je button ; Expl.: User has pressed one of the | je button ; Expl.: User has pressed one of the | ||
; applications buttons. | ; applications buttons. | ||
jmp event_wait | jmp event_wait | ||
; The next section reads the event and processes data. | ; The next section reads the event and processes data. | ||
red: ; Redraw event handler | |||
call draw_window ; We call the window_draw function and | call draw_window ; We call the window_draw function and | ||
jmp event_wait ; jump back to event_wait | jmp event_wait ; jump back to event_wait | ||
mov eax,2 | key: ; Keypress event handler | ||
mov eax, 2 ; The key is returned in ah. The key must be | |||
mcall ; read and cleared from the system queue. | mcall ; read and cleared from the system queue. | ||
jmp event_wait ; Just read the key, ignore it and jump to event_wait. | jmp event_wait ; Just read the key, ignore it and jump to event_wait. | ||
button: ; Buttonpress event handler | |||
mov eax,17 ; The button number defined in window_draw | mov eax,17 ; The button number defined in window_draw | ||
mcall ; is returned to ah. | mcall ; is returned to ah. | ||
Line 156: | Line 211: | ||
mcall | mcall | ||
noclose: | |||
jmp event_wait ; This is for ignored events, useful at development | |||
jmp | |||
; ********************************************* | ; ********************************************* | ||
; ****** WINDOW DEFINITIONS AND DRAW ******** | ; ****** WINDOW DEFINITIONS AND DRAW ******** | ||
Line 171: | Line 223: | ||
; | ; | ||
; The static parts *must* be placed within the fn 12 , ebx = 1 and ebx = 2. | ; The static parts *must* be placed within the fn 12 , ebx = 1 and ebx = 2. | ||
draw_window: | draw_window: | ||
mov eax, 12 ; function 12: tell os about windowdraw | |||
mov ebx, 1 ; 1, start of draw | |||
mov | |||
mov | |||
mcall | mcall | ||
mov eax, 0 ; function 0 : define and draw window | |||
mov | mov ebx, 100 * 65536 + 300 ; [x start] *65536 + [x size] | ||
mov | mov ecx, 100 * 65536 + 120 ; [y start] *65536 + [y size] | ||
mov | mov edx, 0x14ffffff ; color of work area RRGGBB | ||
mov | |||
; 0x02000000 = window type 4 (fixed size, skinned window) | ; 0x02000000 = window type 4 (fixed size, skinned window) | ||
mov | mov esi, 0x808899ff ; color of grab bar RRGGBB | ||
; 0x80000000 = color glide | ; 0x80000000 = color glide | ||
mov | mov edi, title | ||
mcall | mcall | ||
mov ebx, 25 * 65536 + 35 ; draw info text with function 4 | |||
mov ecx, 0x224466 | |||
mov edx, text | |||
mov esi, 40 | |||
mov eax, 4 | |||
.newline: ; text from the DATA AREA | |||
mcall | mcall | ||
add | add ebx, 10 | ||
add | add edx, 40 | ||
cmp | cmp byte[edx], 0 | ||
jne | jne .newline | ||
mov | mov eax, 12 ; function 12:tell os about windowdraw | ||
mov | mov ebx, 2 ; 2, end of draw | ||
mcall | mcall | ||
ret | ret | ||
; ********************************************* | ; ********************************************* | ||
; ************* DATA AREA ***************** | ; ************* DATA AREA ***************** | ||
Line 217: | Line 264: | ||
; Data can be freely mixed with code to any parts of the image. | ; Data can be freely mixed with code to any parts of the image. | ||
; Only the header information is required at the beginning of the image. | ; Only the header information is required at the beginning of the image. | ||
text db "It look's like you have just compiled " | text db "It look's like you have just compiled " | ||
db "your first program for KolibriOS. " | db "your first program for KolibriOS. " | ||
Line 226: | Line 272: | ||
title db "Example application", 0 | title db "Example application", 0 | ||
I_END: | I_END: | ||
; The area after I_END is free for use as the application memory, | ; The area after I_END is free for use as the application memory, | ||
; just avoid the stack. | ; just avoid the stack. | ||
Line 249: | Line 294: | ||
; direct reference. | ; direct reference. | ||
; For example, mov [0x80000],byte 1 moves a byte above the stack area. | ; For example, mov [0x80000],byte 1 moves a byte above the stack area. | ||
</syntaxhighlight> | |||
It should look like this (perhaps with other skin): | |||
[[Image:Example_1.png]] | [[Image:Example_1.png]] | ||
== Using uniform system colours == | == Using uniform system colours == | ||
While previous example concentrated on creating a basic application, in this section more attention is paid on the outlook of the window. | |||
While previous example concentrated on creating a basic application, | |||
in this section more attention is paid on the outlook of the window. | |||
You can use uniform desktop colors defined by a colour setup application. | You can use uniform desktop colors defined by a colour setup application. | ||
New | New function in this example is get_system_colours. | ||
< | <syntaxhighlight> | ||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
; ; | ; ; | ||
Line 278: | Line 316: | ||
; ; | ; ; | ||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
format binary as "" | |||
use32 | |||
use32 | org 0x0 | ||
; The Header | |||
db 'MENUET01' | |||
dd 1, START, I_END, 0x100000, 0x7fff0, 0, 0 | |||
; The code area | ; The code area | ||
window_size_X equ 300 | |||
window_size_Y equ 150 | |||
include 'macros.inc' | |||
START: ; start of execution | START: ; start of execution | ||
call draw_window ; draw the window | |||
; After the window is drawn, it's practical to have the main loop. | ; After the window is drawn, it's practical to have the main loop. | ||
; Events are distributed from here. | ; Events are distributed from here. | ||
event_wait: | event_wait: | ||
mcall 10 ; function 10 : wait until event | |||
; event type is returned in eax | ; event type is returned in eax | ||
; How the 'dec' instruction in the following code works: | |||
; | |||
; example: If a window redraw is needed, eax will be 1 | |||
; So if we decrement eax, eax will become 0 | |||
; 'dec' instruction will set Zero-Flag because eax is now zero | |||
; So now we can use jz (jump if zero flag is set) to detect this.. | |||
; | |||
; If eax is 2, it will take 2 time 'dec eax' before zero flag will be set.. | |||
dec eax ; Event redraw request ? | |||
jz red ; Expl.: there has been activity on screen and | |||
; parts of the applications has to be redrawn. | ; parts of the applications has to be redrawn. | ||
dec eax ; Event key in buffer ? | |||
jz key ; Expl.: User has pressed a key while the | |||
; app is at the top of the window stack. | ; app is at the top of the window stack. | ||
dec eax ; Event button in buffer ? | |||
jz button ; Expl.: User has pressed one of the | |||
; applications buttons. | ; applications buttons. | ||
jmp event_wait | |||
; The next section reads the event and processes data. | ; The next section reads the event and processes data. | ||
red: ; Redraw event handler | |||
call draw_window ; We call the window_draw function and | |||
jmp event_wait ; jump back to event_wait | |||
key: ; Keypress event handler | |||
mcall 2 ; The key is returned in ah. The key must be read and cleared from the system queue. | |||
jmp event_wait ; Just read the key, ignore it and jump to event_wait. | |||
button: ; Buttonpress event handler | |||
mcall 17 ; The button number defined in window_draw is returned to ah. | |||
cmp ah, 1 ; button id=1 ? | |||
jne event_wait ; if not, go back and wait for other events | |||
mcall -1 ; Function -1 : close this program | |||
get_system_colours: | get_system_colours: | ||
pusha | |||
mov eax, 48 ; fn 48 system colours | |||
mov ebx, 3 ; subfn 3 : get | |||
mov ecx, app_colours ; pointer to return area | |||
mov edx, 10 * 4 ; number of bytes to return | |||
mcall | |||
popa | |||
ret | |||
;********************************************* | |||
;****** WINDOW DEFINITIONS AND DRAW ******** | |||
;********************************************* | |||
; | |||
; | |||
; | ; | ||
; The static window parts are drawn in this function. The window canvas can | ; The static window parts are drawn in this function. The window canvas can | ||
Line 400: | Line 410: | ||
; When using system colours, the window colours are read from the | ; When using system colours, the window colours are read from the | ||
; SYSTEM COLOURS TABLE | ; SYSTEM COLOURS TABLE | ||
draw_window: | draw_window: | ||
mcall 12, 1 ; Tell OS about start of redraw | |||
call get_system_colours ; fetches system colours from os | |||
mov eax, 0 ; function 0 : define and draw window | |||
mov ebx, 100 * 65536 + window_size_X ; [x start] *65536 + [x size] | |||
mov ecx, 100 * 65536 + window_size_Y ; [y start] *65536 + [y size] | |||
mov edx, [w_work] ; color of work area 0xRRGGBB | |||
or edx, 0x14000000 ; 0x14000000 = window type 4, with title | |||
mov esi, [w_grab] ; color of grab bar 0xRRGGBB | |||
or esi, 0x80000000 ; 0x80000000 = colour glide | |||
mov edi, title | |||
mcall | |||
mov ebx, 25 * 65536 + 35 ; draw info text with function 4 | |||
mov ecx, [w_work_text] | |||
mov edx, text ; text from the DATA AREA | |||
mov esi, 40 | |||
mcall | |||
mov eax, 4 | |||
.newline: | |||
mcall | |||
add ebx, 10 | |||
add edx, 40 | |||
cmp byte [edx], 0 | |||
jne .newline | |||
mcall 12, 2 ; end of redraw | |||
ret | |||
; ********************************************* | ; ********************************************* | ||
; ************* DATA AREA ***************** | ; ************* DATA AREA ***************** | ||
Line 452: | Line 452: | ||
; Data can be freely mixed with code to any parts of the image. | ; Data can be freely mixed with code to any parts of the image. | ||
; Only the header information is required at the beginning of the image. | ; Only the header information is required at the beginning of the image. | ||
text | text db 'THIS PROGRAM USES UNIFORM SYSTEM COLOURS' | ||
db 'RETURNED TO A TABLE ', 0 | |||
title db 'EXAMPLE APPLICATION', 0 | |||
title | |||
I_END: | I_END: | ||
</ | app_colours: ; SYSTEM COLOURS TABLE | ||
w_frames dd ? ; - frames | |||
w_grab dd ? ; - GRAB AREA | |||
w_grab_button dd ? ; grab area button | |||
w_grab_button_text dd ? ; grab area button text | |||
w_grab_text dd ? ; grab area text | |||
w_work dd ? ; - WORK AREA | |||
w_work_button dd ? ; work area button | |||
w_work_button_text dd ? ; work area button text | |||
w_work_text dd ? ; work area text | |||
w_work_graph dd ? ; work area graphics | |||
</syntaxhighlight> | |||
== Freeform window == | == Freeform window == | ||
In this example we concentrate on shaping the window from rectangle to any form desired by the programmer. New function in this example is shape_window. | |||
In this example we concentrate on shaping the window from rectangle | |||
to any form desired by the programmer. New | <syntaxhighlight> | ||
is shape_window. | |||
< | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
; ; | ; ; | ||
Line 480: | Line 485: | ||
; ; | ; ; | ||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
format binary as "" | |||
use32 | use32 | ||
org 0x0 | |||
; The Header | |||
db 'MENUET01' | |||
dd 1, START, I_END, 0x100000, 0x7fff0, 0x0, 0x0 | |||
include 'macros.inc' | |||
START: ; start of execution | START: ; start of execution | ||
call shape_window ; function for shaping | call shape_window ; function for shaping | ||
call draw_window ; at first, draw the window | call draw_window ; at first, draw the window | ||
still: | still: | ||
mcall 10 ; wait here for event | mcall 10 ; wait here for event | ||
Line 511: | Line 512: | ||
je key | je key | ||
dec | dec eax ; button in buffer ? | ||
je button | je button | ||
jmp still | jmp still | ||
red: ; redraw | |||
call draw_window | call draw_window | ||
jmp still | jmp still | ||
key: ; key | |||
mcall 2 ; just read it and ignore | mcall 2 ; just read it and ignore | ||
jmp still | jmp still | ||
button: ; button | |||
mcall 17 ; get id | mcall 17 ; get id | ||
cmp ah,1 | cmp ah, 1 ; button id=1 ? | ||
jne noclose | jne noclose | ||
mcall -1 ; close this program | mcall -1 ; close this program | ||
noclose: | |||
jmp still | jmp still | ||
shape_window: | shape_window: | ||
pusha | pusha | ||
; give the shape reference area | ; give the shape reference area | ||
mcall 50, 0, shape_reference | mcall 50, 0, shape_reference | ||
; give the shape scale 32 x 32 -> 128 x 128 | ; give the shape scale 32 x 32 -> 128 x 128 | ||
Line 551: | Line 547: | ||
; scale is set to 2^ecx | ; scale is set to 2^ecx | ||
mcall 50, 1, 2 | mcall 50, 1, 2 | ||
popa | popa | ||
ret | ret | ||
shape_reference: ; 32 x 32, ( window_size_X + 1 ) * ( window_size_Y + 1 ) | |||
shape_reference: | db 0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0 | ||
db 0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0 | |||
db 0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0 | |||
db 0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0 | |||
db 0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0 | |||
db 0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0 | |||
db 0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0 | |||
db 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0 | |||
db 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0 | |||
db 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0 | |||
db 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0 | |||
db 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0 | |||
db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0 | |||
db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0 | |||
db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0 | |||
db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0 | |||
db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0 | |||
db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0 | |||
db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0 | |||
db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0 | |||
db 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0 | |||
db 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0 | |||
db 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0 | |||
db 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0 | |||
db 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0 | |||
db 0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0 | |||
db 0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0 | |||
db 0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0 | |||
db 0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0 | |||
db 0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0 | |||
db 0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0 | |||
db 0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0 | |||
;********************************************* | |||
;******* WINDOW DEFINITIONS AND DRAW ******** | |||
;********************************************* | |||
; | |||
; | |||
; | |||
draw_window: | draw_window: | ||
mcall 12, 1 ; notice OS about start of redraw | |||
mcall 12, 1 ; notice | |||
mov eax, 0 ; function 0: define and draw window | |||
mov ebx, 100 * 65536 ; [x start] * 65536 + [x size] | |||
mov eax, 0 ; function 0 : define and draw window | mov ecx, 100 * 65536 ; [y start] * 65536 + [y size] | ||
mov ebx, 100*65536 | |||
mov ecx, 100*65536 | |||
mov bx , [x_size] | mov bx , [x_size] | ||
mov cx , [y_size] | mov cx , [y_size] | ||
Line 613: | Line 602: | ||
mov edi, 0x00cccc00 ; color of frames RRGGBB | mov edi, 0x00cccc00 ; color of frames RRGGBB | ||
mcall | mcall | ||
mov eax, 8 ; function 8: define and draw button | |||
mov eax, 8 ; function 8 : define and draw button | mov ebx, 78 * 65536 + 12 ; [x start] * 65536 + [x size] | ||
mov ebx, 78*65536+12 | mov ecx, 20 * 65536 + 12 ; [y start] * 65536 + [y size] | ||
mov ecx, 20*65536+12 | |||
mov edx, 1 ; button id | mov edx, 1 ; button id | ||
mov esi, 0x5599cc ; button color RRGGBB | mov esi, 0x5599cc ; button color RRGGBB | ||
mcall | mcall | ||
mcall 12, 2 ; end of redraw | mcall 12, 2 ; end of redraw | ||
ret | ret | ||
; DATA | ; DATA | ||
x_size | x_size dw 127 | ||
y_size | y_size dw 127 | ||
I_END: | I_END: | ||
</syntaxhighlight> | |||
</ | |||
== Threads == | == Threads == | ||
KolibriOS assembly threading has some great advantages over higher level languages. If you keep all the variables in registers, you can start as many threads as desired with the _same_ code, since no memory is affected and needs no saving. The registers are saved to Task Switch Segments by KolibriOS. All you have to do is to set a new stack. | |||
KolibriOS assembly threading has some great advantages over higher | |||
level languages. If you keep all the variables in registers, you can | Threads have no difference with the main process and use the same memory area as the process which starts it. They can have their own independent windows etc. In the closing of application, all threads have to be terminated with the default (eax = -1) system call. | ||
start as | |||
no memory is affected and needs no saving. The registers are saved | |||
to Task Switch Segments by KolibriOS. All you have to do is to | |||
set a new stack. | |||
Threads have no difference with the main process and use the same | |||
memory area as the process which starts it. They can have their own | |||
independent windows etc. In the closing of application, all threads | |||
have to be terminated with the default (eax = -1) system call. | |||
New function in this example is create_thread. | New function in this example is create_thread. | ||
< | <syntaxhighlight> | ||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
; ; | ; ; | ||
Line 662: | Line 638: | ||
; ; | ; ; | ||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
format binary as "" | |||
use32 | use32 | ||
org 0x0 | |||
db 'MENUET01' ; 8 byte id for application | |||
dd 1, START, I_END, 0x100000, 0x80000, 0x0, 0x0 | |||
include 'macros.inc' | |||
START: ; start of execution | |||
call draw_window ; at first, draw the window | |||
START: | |||
event_wait: | event_wait: | ||
mov eax, 10 ; wait here for event | |||
mcall | |||
cmp eax, 1 ; redraw request ? | |||
je red | |||
cmp eax, 2 ; key in buffer ? | |||
je key | |||
cmp eax, 3 ; button in buffer ? | |||
je button | |||
jmp event_wait | |||
red: ; redraw | |||
call draw_window | |||
jmp event_wait | |||
key: ; key | |||
mov eax, 2 ; just read it and ignore | |||
mcall | |||
jmp event_wait | |||
button: ; button | |||
mov eax, 17 ; get id | |||
mcall | |||
cmp ah, 1 ; button id=1 ? | |||
jne noclose | |||
mov eax, -1 ; close this program (thread) | |||
mcall | |||
noclose: | |||
cmp ah, 2 ; call create_thread | |||
jne no_thread | |||
call create_thread | |||
jmp event_wait | |||
no_thread: | |||
jmp event_wait | |||
; THREAD CREATION | ; THREAD CREATION | ||
; | ; | ||
; All we have to do is to give the thread entry address in ecx and | ; All we have to do is to give the thread entry address in ecx and | ||
; a new stack | ; a new stack position in edx with function eax=51, ebx=1 | ||
create_thread: | create_thread: | ||
cmp [thread_stack], 0xf0000 | |||
jge no_new_thread | |||
add [thread_stack], 0x1000 | |||
mov eax, 51 ; thread_create system call | |||
mov ebx, 1 | |||
mov ecx, START | |||
mov edx, [thread_stack] | |||
mcall | |||
no_new_thread: | |||
ret | |||
thread_stack dd 0x80000 | thread_stack dd 0x80000 | ||
;********************************************* | |||
; | ;******* WINDOW DEFINITIONS AND DRAW ******** | ||
; | ;********************************************* | ||
; | |||
draw_window: | draw_window: | ||
mov eax, 12 ; function 12: tell os about windowdraw | |||
mov ebx, 1 ; 1, start of draw | |||
mcall | |||
mov eax, 0 ; function 0: define and draw window | |||
mov ebx, 10 * 65536 + 300 ; [x start] * 65536 + [x size] | |||
mov ecx, 10 * 65536 + 140 ; [y start] * 65536 + [y size] | |||
mov esi, [thread_stack] | |||
sub esi, 0x80000 | |||
shr esi, 11 | |||
shl esi, 16 | |||
add ebx, esi | |||
add ecx, esi | |||
mov edx, 0x02ffffff ; color of work area RRGGBB,8->color glide | |||
mov esi, 0x808899ff ; color of grab bar RRGGBB,8->color glide | |||
mov edi, 0x008899ff ; color of frames RRGGBB | |||
mcall | |||
; WINDOW LABEL | |||
mov eax, 4 ; function 4: write text to window | |||
mov ebx, 8 * 65536 + 8 ; [x start] * 65536 + [y start] | |||
mov ecx, 0x00ddeeff ; color of text RRGGBB | |||
mov edx, labelt ; pointer to text beginning | |||
mov esi, labellen-labelt ; text length | |||
mcall | |||
; CLOSE BUTTON | |||
mov eax, 8 ; function 8: define and draw button | |||
mov ebx, (300 - 19) * 65536 + 12 ; [x start] * 65536 + [x size] | |||
mov ecx, 5 * 65536 + 12 ; [y start] * 65536 + [y size] | |||
mov edx, 1 ; button id | |||
mov esi, 0x6677cc ; button color RRGGBB | |||
mcall | |||
; NEW THREAD BUTTON | |||
mov eax, 8 | |||
mov ebx, 25 * 65536 + 128 | |||
mov | mov ecx, 88 * 65536 + 20 | ||
mov edx, 2 | |||
mov esi, 0x6677cc | |||
mcall | |||
mov ebx, 25 * 65536 + 35 ; draw info text with function 4 | |||
mov ecx, 0x224466 | |||
mov edx, text | |||
mov esi, 40 | |||
newline: | .newline: | ||
mov eax, 4 | |||
mcall | |||
add ebx, 10 | |||
add edx, 40 | |||
cmp byte[edx], 0 | |||
jne .newline | |||
mov eax, 12 ; function 12: tell os about windowdraw | |||
mov ebx, 2 ; 2, end of draw | |||
mcall | |||
ret | |||
; DATA AREA | ; DATA AREA | ||
text: | text: | ||
db 'THIS EXAMPLE CREATES THREADS BY RUNNING ' | db 'THIS EXAMPLE CREATES THREADS BY RUNNING ' | ||
Line 824: | Line 789: | ||
db ' ' | db ' ' | ||
db ' CREATE NEW THREAD ', 0 | db ' CREATE NEW THREAD ', 0 | ||
labelt: | labelt: | ||
db 'THREAD EXAMPLE' | |||
labellen: | labellen: | ||
I_END: | I_END: | ||
</syntaxhighlight> | |||
</ | |||
== Real-Time data == | == Real-Time data == | ||
The following example focuses on Real-Time data fetching and processing. Application informs the OS for all the ports and datatypes to read at a specific IRQ. | |||
The following example focuses on Real-Time data fetching and processing. | |||
Application informs the OS for all the ports and datatypes to read | |||
at a specific IRQ. | |||
Steps: | Steps: | ||
# reserve I/O port area | |||
# reserve IRQ | |||
# program IRQ | |||
# program EVENT list for wanted IRQ | |||
# runtime processing of the data | |||
# back to default events - free IRQ from EVENT list | |||
# free IRQ | |||
# free port area | |||
# terminate program | |||
When the application receives this event, the OS has recorded data | After IRQ's are programmed, the application has a new event for the main event loop, number (IRQ+16). When the application receives this event, the OS has recorded data ready for the application to process. | ||
ready for the application to process | |||
The table below shows the main structure of processing real time data. All the steps on the left of (A) are processed by the OS and the steps right from (A) are processed by the application. | |||
IRQ OWNER => REC DATA (A) SYS_EVENT => READ DATA => PROCESS | IRQ OWNER => REC DATA (A) SYS_EVENT => READ DATA => PROCESS | ||
Line 887: | Line 834: | ||
14 IDE SYS | 14 IDE SYS | ||
15 IDE SYS | 15 IDE SYS | ||
An example of processing Real-Time data: | An example of processing Real-Time data: | ||
< | <syntaxhighlight> | ||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
; ; | ; ; | ||
Line 900: | Line 845: | ||
; ; | ; ; | ||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
format binary as "" | |||
use32 | use32 | ||
org 0x0 | |||
db 'MENUET01' ; 8 byte id for application | |||
dd 1, START, I_END, 0x100000, 0x7fff0, 0x0, 0x0 | |||
include 'macros.inc' | |||
START: ; start of execution | |||
call draw_window ; at first, draw the window | |||
call program_real_time_data ; program the OS to receive real time data | |||
call program_com_port ; program the com port for specific device | |||
event_wait: | event_wait: | ||
mov eax, 10 ; wait here for event | |||
mcall | |||
cmp eax, 1 ; redraw request ? | |||
je red | |||
cmp eax, 2 ; key in buffer ? | |||
je key | |||
cmp eax, 3 ; button in buffer ? | |||
je button | |||
cmp eax, 16 + 4 ; RT: new event for wanted IRQ data (16+IRQ) | |||
je read_rt | |||
jmp event_wait | |||
; The next section reads the event and processes data. | ; The next section reads the event and processes data. | ||
read_rt: ; RT data | |||
mov eax, 42 ; Function 42 returns recorded data for IRQ 4 | |||
mov ebx, 4 ; | |||
mcall ; OS returns the recorded data. | |||
; eax number of bytes in buffer left | |||
; bl data | |||
; ecx 0 = success, other = no data in buf. | |||
call process_data | |||
jmp event_wait | |||
red: ; redraw | |||
call draw_window | |||
jmp event_wait | |||
key: ; key | |||
mov eax, 2 ; just read it and ignore | |||
mcall | |||
jmp event_wait | |||
button: ; button | |||
mov eax, 17 ; get id | |||
mcall | |||
cmp ah, 1 ; button id=1 ? | |||
jne noclose | |||
call free_real_time_data | |||
mov eax, -1 ; close this program | |||
mcall | |||
noclose: | |||
jmp event_wait | |||
program_real_time_data: | program_real_time_data: | ||
; Program the Real-Time data fetch | |||
; | |||
; 1) reserve I/O port area | |||
; 2) reserve IRQ | |||
; 3) program IRQ | |||
; 4) program EVENT list for wanted IRQ | |||
pusha | |||
mov eax, 46 ; reserve ports 0x3f0 - 0x3ff | |||
mov ebx, 0 | |||
mov ecx, 0x3f0 | |||
mov edx, 0x3ff | |||
mcall | |||
mov eax, 45 ; reserve irq 4 | |||
mov ebx, 0 | |||
mov ecx, 4 | |||
mcall | |||
mov eax, 44 ; set read ports for irq 4 | |||
mov ebx, irqtable | |||
mov ecx, 4 | |||
mcall | |||
mov eax, 40 ; get com 1 data with irq 4 | |||
mov ebx, 0000000000010000b shl 16 + 111b ; after this we have a new event (16+4) | |||
mcall | |||
popa | |||
ret | |||
irqtable: | irqtable: | ||
dd 0x3f8+0x01000000 ; 3f8 =port to read : 01 =read byte, 02 =read word | dd 0x3f8+0x01000000 ; 3f8 =port to read : 01 =read byte, 02 =read word | ||
dd 0x0 ; 0x0 = termintes read per IRQ event | dd 0x0 ; 0x0 = termintes read per IRQ event | ||
dd 0x0 | dd 0x0 | ||
Line 1,039: | Line 964: | ||
dd 0x0 | dd 0x0 | ||
dd 0x0 | dd 0x0 | ||
free_real_time_data: | free_real_time_data: | ||
; Free the used resources | |||
; | |||
; 1) get default events | |||
; 2) free irq with function 45,1 | |||
; 3) free port area with function 46,1 | |||
pusha | |||
mov eax, 40 ; default events - disable irq 4 event | |||
mov ebx, 111b | |||
mcall | |||
mov eax, 45 ; free irq | |||
mov ebx, 1 | |||
mov ecx, 4 | |||
mcall | |||
mov eax, 46 ; free ports 0x3f0-0x3ff | |||
mov ebx, 1 | |||
mov ecx, 0x3f0 | |||
mov edx, 0x3ff | |||
mcall | |||
popa | |||
ret | |||
; The following functions are for processing device specific data. | ; The following functions are for processing device specific data. | ||
process_data: | process_data: | ||
cmp ebx, 80 | |||
jne .nocd | |||
mov eax, 19 | |||
mov ebx, cdplayer | |||
mov ecx, 0 | |||
mcall | |||
.nocd: | |||
push ebx | |||
nocd: | mov eax, [pos] | ||
add eax, 1 | |||
cmp eax, 10 * 20 + 1 | |||
jb .noeaxz | |||
mov esi, text + 10 * 4 | |||
mov edi, text | |||
mov ecx, 10 * 21 * 4 | |||
cld | |||
rep movsb | |||
mov eax, 13 | |||
mov ebx, 20 * 65536 + 260 | |||
mov ecx, 22 * 65536 + 220 | |||
mov edx, [wcolor] | |||
mcall | |||
mov eax,10*19+1 | |||
.noeaxz: | |||
mov [pos],eax | |||
noeaxz: | pop ebx | ||
and ebx,0xff | |||
call draw_data | |||
ret | |||
draw_data: | draw_data: | ||
pusha | |||
xchg eax, ebx | |||
mov ecx, 10 | |||
shl ebx, 2 | |||
mov esi, 3 | |||
newnum: | .newnum: | ||
xor edx, edx | |||
div ecx | |||
add edx, 48 | |||
mov [ebx + text - 1], dl | |||
dec ebx | |||
dec esi | |||
jnz .newnum | |||
call draw_text | |||
popa | |||
ret | |||
draw_text: | draw_text: | ||
pusha | |||
mov ebx, 25 * 65536 + 35 ; draw info text with function 4 | |||
mov ecx, 0xffffff | |||
mov edx, text | |||
mov esi, 40 | |||
mov edi, 20 | |||
.newline: | |||
newline: | mov eax,4 | ||
mcall | |||
add ebx,10 | |||
add edx,40 | |||
dec edi | |||
jne .newline | |||
popa | |||
ret | |||
program_com_port: | program_com_port: | ||
; the following sequence programs COM port for infrared receiver | |||
mov cx, 0x3f3 + 8 | |||
mov bl, 0x80 | |||
mov eax, 43 | |||
mcall | |||
mov cx, 0x3f1 + 8 | |||
mov bl, 0 | |||
mov eax, 43 | |||
mcall | |||
mov cx, 0x3f0 + 8 | |||
mov bl, 0x30 / 4 | |||
mov eax, 43 | |||
mcall | |||
mov cx, 0x3f3 + 8 | |||
mov bl, 3 | |||
mov eax, 43 | |||
mcall | |||
mov cx, 0x3f4 + 8 | |||
mov bl, 0xB | |||
mov eax, 43 | |||
mcall | |||
mov cx, 0x3f1 + 8 | |||
mov bl, 1 | |||
mov eax, 43 | |||
mcall | |||
mov eax, 5 | |||
mov ebx, 100 | |||
mcall | |||
mov cx, 0x3f8 | |||
mov bl, 'I' | |||
mov eax, 43 | |||
mcall | |||
mov eax, 5 | |||
mov ebx, 10 | |||
mcall | |||
mov cx, 0x3f8 | |||
mov bl, 'R' | |||
mov eax, 43 | |||
mcall | |||
ret | |||
;********************************************* | |||
;******* WINDOW DEFINITIONS AND DRAW ******** | |||
;********************************************* | |||
draw_window: | draw_window: | ||
mov eax, 12 ; function 12:tell os about windowdraw | |||
mov ebx, 1 ; 1, start of draw | |||
mcall | |||
; DRAW WINDOW | |||
mov eax, 0 ; function 0 : define and draw window | |||
mcall | mov ebx, 100 * 65536 + 300 ; [x start] *65536 + [x size] | ||
mov ecx, 100 * 65536 + 250 ; [y start] *65536 + [y size] | |||
mov edx, [wcolor] ; color of work area RRGGBB,8->color | |||
mov esi, 0x8099bbff ; color of grab bar RRGGBB,8->color glide | |||
mov edi, 0x00ffffff ; color of frames RRGGBB | |||
mcall | |||
; WINDOW LABEL | |||
mov eax, 4 ; function 4 : write text to window | |||
mov ebx, 8 * 65536 + 8 ; [x start] *65536 + [y start] | |||
mov ecx, 0x00ffffff ; color of text RRGGBB | |||
mov edx, labelt ; pointer to text beginning | |||
mov esi, labellen - labelt ; text length | |||
mcall | |||
; CLOSE BUTTON | |||
mov eax, 8 ; function 8 : define and draw button | |||
mov ebx, (300 - 19) * 65536 + 12 ; [x start] *65536 + [x size] | |||
mov ecx, 5 * 65536 + 12 ; [y start] *65536 + [y size] | |||
mov edx, 1 ; button id | |||
mov esi, 0x5599cc ; button color RRGGBB | |||
mcall | |||
call draw_text | |||
mov eax, 12 | |||
mov ebx, 2 | |||
mcall | |||
ret | |||
; DATA AREA | |||
wcolor dd 0x0 | wcolor dd 0x0 | ||
pos dd 0x0 | pos dd 0x0 | ||
cdplayer db 'CDPLAY ' | cdplayer db 'CDPLAY ' | ||
labelt db 'INFRARED RECEIVER FOR IRMAN IN COM 1' | labelt db 'INFRARED RECEIVER FOR IRMAN IN COM 1' | ||
labellen: | labellen: | ||
text: | text: | ||
I_END: | I_END: | ||
</syntaxhighlight> | |||
[[Category:Coding]] |
Latest revision as of 20:07, 18 March 2014
Structure of an application
KolibriOS's application structure is not specifically reserved for asm programming, the header can be produced with practically any other language. However, the overall application programming design is intended for easy 32 bit asm programming. The GUI is extremely easy to handle with especially asm language.
Programming for KolibriOS is easy as you first learn the basic structure of an application. At this point I assume you have some experience in assembly language.
The KolibriOS API (Application Programming Interface) is an easy-to-learn set of functions with practically no hierarchical accesses.
The operating of an application is based on events. The application is notified by the OS with the event type and the application acts accordingly.
There are three event types an application is expected to handle by default: window redraw, keypress and buttonpress.
Flow chart and structure of an application with default events:
;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; HEADER DATA ;
; ;
;;;;;;::;;;;;;;;;;;;;;;;;
START:
call draw_window
;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; WAIT UNTIL EVENT ; <-----------------------------------------------I
; ; I
;;;;;;;;;;;;;;;;;;;;;;;;; I
; I
;;;;;;;;;;;;;;;;;;;;;;;;; I
; ; redraw -> call draw_window -> I
; READ EVENT TYPE ; -> key -> read keypress -> process -> I
; ; button -> read buttonpress -> process -> I
;;;;;;;;;;;;;;;;;;;;;;;;;
draw_window:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; DRAW STATIC WINDOW PARTS ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ret
;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; STATIC DATA ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;
The header
db 'MENUET01'
Since KolibriOS still is more or less API compatible with MenuetOS, it has the same header. There is also an older version of the header which uses 'MENUET00', but it should not be used anymore.
dd 0x01 ; header version
Speaks for itself.
dd START ; start of execution
START is the label in your program where kernel will jump to after loading the program. You could use another name, but it's convenient to always use the same.
dd I_END ; size of image
This is the total size of the program code in bytes, its easy to use a label which you place at the end of the code.
dd 0x100000
This is the amount of ram that will be reserved for your app. You could use a static value as shown here, or you could use I_END + xx bytes. There, I_END would be the label to the end of code + all static declarations you made after the code. The xx bytes then are the number of bytes you want to use for the stack. Also note, this value can later be changed by using system functions.
dd 0x100000 ; stack position in memory area
Where the end of stack is (the value of esp at start of program). Logically, this would be the same as the previous value.
dd 0x0 ; Parameters
If you want to use parameters, this should be a pointer to a 1024 byte buffer, in which those parameters will be written by the kernel. If you don't want to use them, set this dword to 0.
dd 0x0 ; Path
Path value, works the same as parameter.
System calls
The System calls (API) are explained in various sources. There is the file syscalls.txt which you can find in KolibriOS itself, but also in the zip file of the distribution.< If you understand russian, you can also find system calls on this wiki.
To execute a system call, you first need to fill the registers with the correct value. Say we want to wait a couple of milliseconds, we need to use system function 5 and place the time we want to wait in ebx.
mov eax, 5
mov ebx, 10
Now, we need to execute the function, this can be done with int 0x40:
int 0x40
But also with more modern instructions such as syscall, sysenter etc. It's convenient to use the mcall macro from macros.inc, then you can choose to use int 0x40 or another method, at compile time. This macro also accepts parameters, first is eax, second is ebx, ...
Code for the above would be:
mcall 5, 10
Coding Style
It's advisable to use the coding style, as described here: Style
The API
You can find the latest API documentation in /kernel/docs/ in the SVN repository (WebSVN)
Inside KolibriOS, you can find sysfuncs.txt (english version) or sysfuncr (russian version) in DOCKPACK program.
These files also come with the so called distribution kit, in documents folder.
Assembly examples
Some examples are listed on this page, more can be found on the SVN server in the folder /programs/develop/examples/ (WebSVN)
Simple example
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; EXAMPLE APPLICATION ;
; ;
; Compile with FASM ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
format binary as "" ; Binary file format without extenstion
use32 ; Tell compiler to use 32 bit instructions
org 0x0 ; the base address of code, always 0x0
; The header
db 'MENUET01'
dd 0x01
dd START
dd I_END
dd 0x100000
dd 0x7fff0
dd 0, 0
; The code area
include 'macros.inc'
START: ; start of execution
call draw_window ; draw the window
; After the window is drawn, it's practical to have the main loop.
; Events are distributed from here.
event_wait:
mov eax, 10 ; function 10 : wait until event
mcall ; event type is returned in eax
cmp eax, 1 ; Event redraw request ?
je red ; Expl.: there has been activity on screen and
; parts of the applications has to be redrawn.
cmp eax, 2 ; Event key in buffer ?
je key ; Expl.: User has pressed a key while the
; app is at the top of the window stack.
cmp eax, 3 ; Event button in buffer ?
je button ; Expl.: User has pressed one of the
; applications buttons.
jmp event_wait
; The next section reads the event and processes data.
red: ; Redraw event handler
call draw_window ; We call the window_draw function and
jmp event_wait ; jump back to event_wait
key: ; Keypress event handler
mov eax, 2 ; The key is returned in ah. The key must be
mcall ; read and cleared from the system queue.
jmp event_wait ; Just read the key, ignore it and jump to event_wait.
button: ; Buttonpress event handler
mov eax,17 ; The button number defined in window_draw
mcall ; is returned to ah.
cmp ah,1 ; button id=1 ?
jne noclose
mov eax,-1 ; Function -1 : close this program
mcall
noclose:
jmp event_wait ; This is for ignored events, useful at development
; *********************************************
; ****** WINDOW DEFINITIONS AND DRAW ********
; *********************************************
;
; The static window parts are drawn in this function. The window canvas can
; be accessed later from any parts of this code (thread) for displaying
; processes or recorded data, for example.
;
; The static parts *must* be placed within the fn 12 , ebx = 1 and ebx = 2.
draw_window:
mov eax, 12 ; function 12: tell os about windowdraw
mov ebx, 1 ; 1, start of draw
mcall
mov eax, 0 ; function 0 : define and draw window
mov ebx, 100 * 65536 + 300 ; [x start] *65536 + [x size]
mov ecx, 100 * 65536 + 120 ; [y start] *65536 + [y size]
mov edx, 0x14ffffff ; color of work area RRGGBB
; 0x02000000 = window type 4 (fixed size, skinned window)
mov esi, 0x808899ff ; color of grab bar RRGGBB
; 0x80000000 = color glide
mov edi, title
mcall
mov ebx, 25 * 65536 + 35 ; draw info text with function 4
mov ecx, 0x224466
mov edx, text
mov esi, 40
mov eax, 4
.newline: ; text from the DATA AREA
mcall
add ebx, 10
add edx, 40
cmp byte[edx], 0
jne .newline
mov eax, 12 ; function 12:tell os about windowdraw
mov ebx, 2 ; 2, end of draw
mcall
ret
; *********************************************
; ************* DATA AREA *****************
; *********************************************
;
; Data can be freely mixed with code to any parts of the image.
; Only the header information is required at the beginning of the image.
text db "It look's like you have just compiled "
db "your first program for KolibriOS. "
db " "
db "Congratulations! ", 0
title db "Example application", 0
I_END:
; The area after I_END is free for use as the application memory,
; just avoid the stack.
;
; Application memory structure, according to the used header, 1 Mb.
;
; 0x00000 - Start of compiled image
; I_END - End of compiled image
;
; + Free for use in the application
;
; 0x7ff00 - Start of stack area
; 0x7fff0 - End of stack area - defined in the header
;
; + Free for use in the application
;
; 0xFFFFF - End of freely useable memory - defined in the header
;
; All of the the areas can be modified within the application with a
; direct reference.
; For example, mov [0x80000],byte 1 moves a byte above the stack area.
It should look like this (perhaps with other skin):
Using uniform system colours
While previous example concentrated on creating a basic application, in this section more attention is paid on the outlook of the window.
You can use uniform desktop colors defined by a colour setup application.
New function in this example is get_system_colours.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; UNIFORM SYSTEM COLOURS EXAMPLE ;
; ;
; Compile with FASM ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
format binary as ""
use32
org 0x0
; The Header
db 'MENUET01'
dd 1, START, I_END, 0x100000, 0x7fff0, 0, 0
; The code area
window_size_X equ 300
window_size_Y equ 150
include 'macros.inc'
START: ; start of execution
call draw_window ; draw the window
; After the window is drawn, it's practical to have the main loop.
; Events are distributed from here.
event_wait:
mcall 10 ; function 10 : wait until event
; event type is returned in eax
; How the 'dec' instruction in the following code works:
;
; example: If a window redraw is needed, eax will be 1
; So if we decrement eax, eax will become 0
; 'dec' instruction will set Zero-Flag because eax is now zero
; So now we can use jz (jump if zero flag is set) to detect this..
;
; If eax is 2, it will take 2 time 'dec eax' before zero flag will be set..
dec eax ; Event redraw request ?
jz red ; Expl.: there has been activity on screen and
; parts of the applications has to be redrawn.
dec eax ; Event key in buffer ?
jz key ; Expl.: User has pressed a key while the
; app is at the top of the window stack.
dec eax ; Event button in buffer ?
jz button ; Expl.: User has pressed one of the
; applications buttons.
jmp event_wait
; The next section reads the event and processes data.
red: ; Redraw event handler
call draw_window ; We call the window_draw function and
jmp event_wait ; jump back to event_wait
key: ; Keypress event handler
mcall 2 ; The key is returned in ah. The key must be read and cleared from the system queue.
jmp event_wait ; Just read the key, ignore it and jump to event_wait.
button: ; Buttonpress event handler
mcall 17 ; The button number defined in window_draw is returned to ah.
cmp ah, 1 ; button id=1 ?
jne event_wait ; if not, go back and wait for other events
mcall -1 ; Function -1 : close this program
get_system_colours:
pusha
mov eax, 48 ; fn 48 system colours
mov ebx, 3 ; subfn 3 : get
mov ecx, app_colours ; pointer to return area
mov edx, 10 * 4 ; number of bytes to return
mcall
popa
ret
;*********************************************
;****** WINDOW DEFINITIONS AND DRAW ********
;*********************************************
;
; The static window parts are drawn in this function. The window canvas can
; be accessed later from any parts of this code (thread) for displaying
; processed or recorded data, for example.
;
; The static parts *must* be placed within the fn 12 , ebx = 1 and ebx = 2.
;
;
; When using system colours, the window colours are read from the
; SYSTEM COLOURS TABLE
draw_window:
mcall 12, 1 ; Tell OS about start of redraw
call get_system_colours ; fetches system colours from os
mov eax, 0 ; function 0 : define and draw window
mov ebx, 100 * 65536 + window_size_X ; [x start] *65536 + [x size]
mov ecx, 100 * 65536 + window_size_Y ; [y start] *65536 + [y size]
mov edx, [w_work] ; color of work area 0xRRGGBB
or edx, 0x14000000 ; 0x14000000 = window type 4, with title
mov esi, [w_grab] ; color of grab bar 0xRRGGBB
or esi, 0x80000000 ; 0x80000000 = colour glide
mov edi, title
mcall
mov ebx, 25 * 65536 + 35 ; draw info text with function 4
mov ecx, [w_work_text]
mov edx, text ; text from the DATA AREA
mov esi, 40
mov eax, 4
.newline:
mcall
add ebx, 10
add edx, 40
cmp byte [edx], 0
jne .newline
mcall 12, 2 ; end of redraw
ret
; *********************************************
; ************* DATA AREA *****************
; *********************************************
;
; Data can be freely mixed with code to any parts of the image.
; Only the header information is required at the beginning of the image.
text db 'THIS PROGRAM USES UNIFORM SYSTEM COLOURS'
db 'RETURNED TO A TABLE ', 0
title db 'EXAMPLE APPLICATION', 0
I_END:
app_colours: ; SYSTEM COLOURS TABLE
w_frames dd ? ; - frames
w_grab dd ? ; - GRAB AREA
w_grab_button dd ? ; grab area button
w_grab_button_text dd ? ; grab area button text
w_grab_text dd ? ; grab area text
w_work dd ? ; - WORK AREA
w_work_button dd ? ; work area button
w_work_button_text dd ? ; work area button text
w_work_text dd ? ; work area text
w_work_graph dd ? ; work area graphics
Freeform window
In this example we concentrate on shaping the window from rectangle to any form desired by the programmer. New function in this example is shape_window.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; FREEFORM EXAMPLE APPLICATION ;
; ;
; Compile with FASM ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
format binary as ""
use32
org 0x0
; The Header
db 'MENUET01'
dd 1, START, I_END, 0x100000, 0x7fff0, 0x0, 0x0
include 'macros.inc'
START: ; start of execution
call shape_window ; function for shaping
call draw_window ; at first, draw the window
still:
mcall 10 ; wait here for event
dec eax ; redraw request ?
jz red
dec eax ; key in buffer ?
je key
dec eax ; button in buffer ?
je button
jmp still
red: ; redraw
call draw_window
jmp still
key: ; key
mcall 2 ; just read it and ignore
jmp still
button: ; button
mcall 17 ; get id
cmp ah, 1 ; button id=1 ?
jne noclose
mcall -1 ; close this program
noclose:
jmp still
shape_window:
pusha
; give the shape reference area
mcall 50, 0, shape_reference
; give the shape scale 32 x 32 -> 128 x 128
; you dont have to give this, scale is 1:1 by default
; scale is set to 2^ecx
mcall 50, 1, 2
popa
ret
shape_reference: ; 32 x 32, ( window_size_X + 1 ) * ( window_size_Y + 1 )
db 0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0
db 0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0
db 0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0
db 0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0
db 0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0
db 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0
db 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0
db 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0
db 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0
db 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0
db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0
db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0
db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0
db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0
db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0
db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0
db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0
db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0
db 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0
db 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0
db 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0
db 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0
db 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0
db 0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0
db 0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0
db 0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0
db 0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0
db 0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0
;*********************************************
;******* WINDOW DEFINITIONS AND DRAW ********
;*********************************************
draw_window:
mcall 12, 1 ; notice OS about start of redraw
mov eax, 0 ; function 0: define and draw window
mov ebx, 100 * 65536 ; [x start] * 65536 + [x size]
mov ecx, 100 * 65536 ; [y start] * 65536 + [y size]
mov bx , [x_size]
mov cx , [y_size]
mov edx, 0x00cccc00 ; color of work area RRGGBB,8->color glide
mov esi, 0x00cccc00 ; color of grab bar RRGGBB,8->color glide
mov edi, 0x00cccc00 ; color of frames RRGGBB
mcall
mov eax, 8 ; function 8: define and draw button
mov ebx, 78 * 65536 + 12 ; [x start] * 65536 + [x size]
mov ecx, 20 * 65536 + 12 ; [y start] * 65536 + [y size]
mov edx, 1 ; button id
mov esi, 0x5599cc ; button color RRGGBB
mcall
mcall 12, 2 ; end of redraw
ret
; DATA
x_size dw 127
y_size dw 127
I_END:
Threads
KolibriOS assembly threading has some great advantages over higher level languages. If you keep all the variables in registers, you can start as many threads as desired with the _same_ code, since no memory is affected and needs no saving. The registers are saved to Task Switch Segments by KolibriOS. All you have to do is to set a new stack.
Threads have no difference with the main process and use the same memory area as the process which starts it. They can have their own independent windows etc. In the closing of application, all threads have to be terminated with the default (eax = -1) system call.
New function in this example is create_thread.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; THREAD EXAMPLE ;
; ;
; Compile with FASM for Menuet ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
format binary as ""
use32
org 0x0
db 'MENUET01' ; 8 byte id for application
dd 1, START, I_END, 0x100000, 0x80000, 0x0, 0x0
include 'macros.inc'
START: ; start of execution
call draw_window ; at first, draw the window
event_wait:
mov eax, 10 ; wait here for event
mcall
cmp eax, 1 ; redraw request ?
je red
cmp eax, 2 ; key in buffer ?
je key
cmp eax, 3 ; button in buffer ?
je button
jmp event_wait
red: ; redraw
call draw_window
jmp event_wait
key: ; key
mov eax, 2 ; just read it and ignore
mcall
jmp event_wait
button: ; button
mov eax, 17 ; get id
mcall
cmp ah, 1 ; button id=1 ?
jne noclose
mov eax, -1 ; close this program (thread)
mcall
noclose:
cmp ah, 2 ; call create_thread
jne no_thread
call create_thread
jmp event_wait
no_thread:
jmp event_wait
; THREAD CREATION
;
; All we have to do is to give the thread entry address in ecx and
; a new stack position in edx with function eax=51, ebx=1
create_thread:
cmp [thread_stack], 0xf0000
jge no_new_thread
add [thread_stack], 0x1000
mov eax, 51 ; thread_create system call
mov ebx, 1
mov ecx, START
mov edx, [thread_stack]
mcall
no_new_thread:
ret
thread_stack dd 0x80000
;*********************************************
;******* WINDOW DEFINITIONS AND DRAW ********
;*********************************************
draw_window:
mov eax, 12 ; function 12: tell os about windowdraw
mov ebx, 1 ; 1, start of draw
mcall
mov eax, 0 ; function 0: define and draw window
mov ebx, 10 * 65536 + 300 ; [x start] * 65536 + [x size]
mov ecx, 10 * 65536 + 140 ; [y start] * 65536 + [y size]
mov esi, [thread_stack]
sub esi, 0x80000
shr esi, 11
shl esi, 16
add ebx, esi
add ecx, esi
mov edx, 0x02ffffff ; color of work area RRGGBB,8->color glide
mov esi, 0x808899ff ; color of grab bar RRGGBB,8->color glide
mov edi, 0x008899ff ; color of frames RRGGBB
mcall
; WINDOW LABEL
mov eax, 4 ; function 4: write text to window
mov ebx, 8 * 65536 + 8 ; [x start] * 65536 + [y start]
mov ecx, 0x00ddeeff ; color of text RRGGBB
mov edx, labelt ; pointer to text beginning
mov esi, labellen-labelt ; text length
mcall
; CLOSE BUTTON
mov eax, 8 ; function 8: define and draw button
mov ebx, (300 - 19) * 65536 + 12 ; [x start] * 65536 + [x size]
mov ecx, 5 * 65536 + 12 ; [y start] * 65536 + [y size]
mov edx, 1 ; button id
mov esi, 0x6677cc ; button color RRGGBB
mcall
; NEW THREAD BUTTON
mov eax, 8
mov ebx, 25 * 65536 + 128
mov ecx, 88 * 65536 + 20
mov edx, 2
mov esi, 0x6677cc
mcall
mov ebx, 25 * 65536 + 35 ; draw info text with function 4
mov ecx, 0x224466
mov edx, text
mov esi, 40
.newline:
mov eax, 4
mcall
add ebx, 10
add edx, 40
cmp byte[edx], 0
jne .newline
mov eax, 12 ; function 12: tell os about windowdraw
mov ebx, 2 ; 2, end of draw
mcall
ret
; DATA AREA
text:
db 'THIS EXAMPLE CREATES THREADS BY RUNNING '
db 'THE SAME CODE MULTIPLE TIMES. ALL WE '
db 'NEED IS A NEW STACK FOR EACH THREAD. '
db 'ALL THREADS SHARE THE SAME MEMORY. '
db ' '
db ' '
db ' CREATE NEW THREAD ', 0
labelt:
db 'THREAD EXAMPLE'
labellen:
I_END:
Real-Time data
The following example focuses on Real-Time data fetching and processing. Application informs the OS for all the ports and datatypes to read at a specific IRQ.
Steps:
- reserve I/O port area
- reserve IRQ
- program IRQ
- program EVENT list for wanted IRQ
- runtime processing of the data
- back to default events - free IRQ from EVENT list
- free IRQ
- free port area
- terminate program
After IRQ's are programmed, the application has a new event for the main event loop, number (IRQ+16). When the application receives this event, the OS has recorded data ready for the application to process.
The table below shows the main structure of processing real time data. All the steps on the left of (A) are processed by the OS and the steps right from (A) are processed by the application.
IRQ OWNER => REC DATA (A) SYS_EVENT => READ DATA => PROCESS 0 TIMER SYS 1 KEYBOARD SYS 2 free -> 3 COM MOUSE SYS/free ?> 4 COM MOUSE SYS/free ?> 5 SOUND BL. SYS 6 FLOPPY SYS 7 free -> 8 free -> 9 free -> 10 free -> 11 free -> 12 PS2 MOUSE SYS/free ?> 13 MATH PR. SYS 14 IDE SYS 15 IDE SYS
An example of processing Real-Time data:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; REAL-TIME DATA ;
; ;
; Compile with FASM for Menuet ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
format binary as ""
use32
org 0x0
db 'MENUET01' ; 8 byte id for application
dd 1, START, I_END, 0x100000, 0x7fff0, 0x0, 0x0
include 'macros.inc'
START: ; start of execution
call draw_window ; at first, draw the window
call program_real_time_data ; program the OS to receive real time data
call program_com_port ; program the com port for specific device
event_wait:
mov eax, 10 ; wait here for event
mcall
cmp eax, 1 ; redraw request ?
je red
cmp eax, 2 ; key in buffer ?
je key
cmp eax, 3 ; button in buffer ?
je button
cmp eax, 16 + 4 ; RT: new event for wanted IRQ data (16+IRQ)
je read_rt
jmp event_wait
; The next section reads the event and processes data.
read_rt: ; RT data
mov eax, 42 ; Function 42 returns recorded data for IRQ 4
mov ebx, 4 ;
mcall ; OS returns the recorded data.
; eax number of bytes in buffer left
; bl data
; ecx 0 = success, other = no data in buf.
call process_data
jmp event_wait
red: ; redraw
call draw_window
jmp event_wait
key: ; key
mov eax, 2 ; just read it and ignore
mcall
jmp event_wait
button: ; button
mov eax, 17 ; get id
mcall
cmp ah, 1 ; button id=1 ?
jne noclose
call free_real_time_data
mov eax, -1 ; close this program
mcall
noclose:
jmp event_wait
program_real_time_data:
; Program the Real-Time data fetch
;
; 1) reserve I/O port area
; 2) reserve IRQ
; 3) program IRQ
; 4) program EVENT list for wanted IRQ
pusha
mov eax, 46 ; reserve ports 0x3f0 - 0x3ff
mov ebx, 0
mov ecx, 0x3f0
mov edx, 0x3ff
mcall
mov eax, 45 ; reserve irq 4
mov ebx, 0
mov ecx, 4
mcall
mov eax, 44 ; set read ports for irq 4
mov ebx, irqtable
mov ecx, 4
mcall
mov eax, 40 ; get com 1 data with irq 4
mov ebx, 0000000000010000b shl 16 + 111b ; after this we have a new event (16+4)
mcall
popa
ret
irqtable:
dd 0x3f8+0x01000000 ; 3f8 =port to read : 01 =read byte, 02 =read word
dd 0x0 ; 0x0 = termintes read per IRQ event
dd 0x0
dd 0x0
dd 0x0
dd 0x0
dd 0x0
dd 0x0
dd 0x0
dd 0x0
dd 0x0
dd 0x0
dd 0x0
dd 0x0
dd 0x0
dd 0x0
free_real_time_data:
; Free the used resources
;
; 1) get default events
; 2) free irq with function 45,1
; 3) free port area with function 46,1
pusha
mov eax, 40 ; default events - disable irq 4 event
mov ebx, 111b
mcall
mov eax, 45 ; free irq
mov ebx, 1
mov ecx, 4
mcall
mov eax, 46 ; free ports 0x3f0-0x3ff
mov ebx, 1
mov ecx, 0x3f0
mov edx, 0x3ff
mcall
popa
ret
; The following functions are for processing device specific data.
process_data:
cmp ebx, 80
jne .nocd
mov eax, 19
mov ebx, cdplayer
mov ecx, 0
mcall
.nocd:
push ebx
mov eax, [pos]
add eax, 1
cmp eax, 10 * 20 + 1
jb .noeaxz
mov esi, text + 10 * 4
mov edi, text
mov ecx, 10 * 21 * 4
cld
rep movsb
mov eax, 13
mov ebx, 20 * 65536 + 260
mov ecx, 22 * 65536 + 220
mov edx, [wcolor]
mcall
mov eax,10*19+1
.noeaxz:
mov [pos],eax
pop ebx
and ebx,0xff
call draw_data
ret
draw_data:
pusha
xchg eax, ebx
mov ecx, 10
shl ebx, 2
mov esi, 3
.newnum:
xor edx, edx
div ecx
add edx, 48
mov [ebx + text - 1], dl
dec ebx
dec esi
jnz .newnum
call draw_text
popa
ret
draw_text:
pusha
mov ebx, 25 * 65536 + 35 ; draw info text with function 4
mov ecx, 0xffffff
mov edx, text
mov esi, 40
mov edi, 20
.newline:
mov eax,4
mcall
add ebx,10
add edx,40
dec edi
jne .newline
popa
ret
program_com_port:
; the following sequence programs COM port for infrared receiver
mov cx, 0x3f3 + 8
mov bl, 0x80
mov eax, 43
mcall
mov cx, 0x3f1 + 8
mov bl, 0
mov eax, 43
mcall
mov cx, 0x3f0 + 8
mov bl, 0x30 / 4
mov eax, 43
mcall
mov cx, 0x3f3 + 8
mov bl, 3
mov eax, 43
mcall
mov cx, 0x3f4 + 8
mov bl, 0xB
mov eax, 43
mcall
mov cx, 0x3f1 + 8
mov bl, 1
mov eax, 43
mcall
mov eax, 5
mov ebx, 100
mcall
mov cx, 0x3f8
mov bl, 'I'
mov eax, 43
mcall
mov eax, 5
mov ebx, 10
mcall
mov cx, 0x3f8
mov bl, 'R'
mov eax, 43
mcall
ret
;*********************************************
;******* WINDOW DEFINITIONS AND DRAW ********
;*********************************************
draw_window:
mov eax, 12 ; function 12:tell os about windowdraw
mov ebx, 1 ; 1, start of draw
mcall
; DRAW WINDOW
mov eax, 0 ; function 0 : define and draw window
mov ebx, 100 * 65536 + 300 ; [x start] *65536 + [x size]
mov ecx, 100 * 65536 + 250 ; [y start] *65536 + [y size]
mov edx, [wcolor] ; color of work area RRGGBB,8->color
mov esi, 0x8099bbff ; color of grab bar RRGGBB,8->color glide
mov edi, 0x00ffffff ; color of frames RRGGBB
mcall
; WINDOW LABEL
mov eax, 4 ; function 4 : write text to window
mov ebx, 8 * 65536 + 8 ; [x start] *65536 + [y start]
mov ecx, 0x00ffffff ; color of text RRGGBB
mov edx, labelt ; pointer to text beginning
mov esi, labellen - labelt ; text length
mcall
; CLOSE BUTTON
mov eax, 8 ; function 8 : define and draw button
mov ebx, (300 - 19) * 65536 + 12 ; [x start] *65536 + [x size]
mov ecx, 5 * 65536 + 12 ; [y start] *65536 + [y size]
mov edx, 1 ; button id
mov esi, 0x5599cc ; button color RRGGBB
mcall
call draw_text
mov eax, 12
mov ebx, 2
mcall
ret
; DATA AREA
wcolor dd 0x0
pos dd 0x0
cdplayer db 'CDPLAY '
labelt db 'INFRARED RECEIVER FOR IRMAN IN COM 1'
labellen:
text:
I_END: