Новости
Описание
Текущая версия
История
Скриншоты
OS Menuet
Дистрибутивы
Загрузчики
Программы
Статьи
FAQ
Hardware List
Рассылки
Наша команда
Публикация
Конкурс
Форум
О Menuet
Другие OS
Программисту
|
|
|
|
Добавление новых функций прерывания 0x40 в ядро MeOS
|
Процесс написания новых функций для ядра MenuetOS настолько прост, что для этого даже не обязательно знать и понимать принципы функционирования самого ядра. Итак, попробуем написать новую функцию для прерывания 0x40. Сначала отыщем в коде ядра таблицу прерывания 0x40 - “servetable”, начинается она так:
servetable:
dd sys_drawwindow ; 0-DrawWindow
dd syscall_setpixel ; 1-SetPixel
. . .
Дописываем в конец таблицы новую процедуру:
. . .
dd sys_trace ; 59-System call trace
dd sys_ipc ; 60-Inter Process Communication
dd sys_gs ; 61-Direct graphics access
dd my_function ; 62-Имя нашей функции
ВНИМАНИЕ: Имя процедуры которое мы сейчас задали это имя подпрограммы которую мы опишем дальше!
Соответственно на данный момент это будет функция 62, вызывающаяся из программ прерыванием 0x40:
Если мы добавим еще одну запись, то это уже будет функция 63.
Теперь посмотрим как наша функция принимает значения регистров из программы. Все дело в том, что значения регистров смещаются следующим образом: EBX переходит в EAX, ECX в EBX, EDX в ECX, ESI в ECX, EDI в ESI. Рассмотрим на примере кода приложения:
mov eax,62
mov ebx,0x00202020
mov edi,0x00303030
int 0x40
Теперь при старте кода функции в регистре EAX окажется число 0x00202020, а в регистре ESI - число 0x00303030.
И наконец, посмотрим как функция передает значения регистров в приложение, и наконец напишем полноценную функцию прерывания. Найдем в коде место с телом последней функции и после него вставляем код нашей простейшей функции:
my_function:
mov eax,0x00101010
mov [esp+36],eax
mov ebx,0x00202020
mov [esp+24],ebx
mov ecx,0x00303030
mov [esp+32],ecx
mov edx,0x00404040
mov [esp+28],edx
ret
Что здесь что. В общем мы передаем значения регистров в приложение, пример достаточно прозрачен, и естественно что в приложении после исполнения нашей функции в регистре EAX окажется число 0x00101010.
Перекомпилируем ядро (см. приложение “Компиляция ядра”), и перезагружаем машину. Теперь немного изменим простейшее приложение EXAMPLE.ASM, и посмотрим как работает наша функция. Пусть, если после вызова мы получим в регистре EAX 0x00101010, то текст в окне приложения не напечатается, и так мы узнаем что наша новая функция работает:
;
; EXAMPLE APPLICATION
;
; Compile with FASM for Menuet
;
use32
org 0x0
db 'MENUET01' ; 8 byte id
dd 0x01 ; header version
dd START ; start of code
dd I_END ; size of image
dd 0x100000 ; memory for app
dd 0x7fff0 ; esp
dd 0x0 , 0x0 ; I_Param , I_Icon
START: ; start of execution
call draw_window
still:
mov eax,10 ; wait here for event
int 0x40
cmp eax,1 ; redraw request ?
je red
cmp eax,2 ; key in buffer ?
je key
cmp eax,3 ; button in buffer ?
je button
jmp still
red: ; redraw
call draw_window
jmp still
key: ; key
mov eax,2 ; just read it and ignore
int 0x40
jmp still
button: ; button
mov eax,17 ; get id
int 0x40
cmp ah,1 ; button id=1 ?
jne noclose
mov eax,-1 ; close this program
int 0x40
noclose:
jmp still
; *********************************************
; ******* WINDOW DEFINITIONS AND DRAW ********
; *********************************************
draw_window:
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,1 ; 1, start of draw
int 0x40
; 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+120 ; [y start] *65536 + [y size]
mov edx,0x02ffffff ; color of work area RRGGBB,8->color gl
mov esi,0x805080d0 ; color of grab bar RRGGBB,8->color gl
mov edi,0x005080d0 ; color of frames RRGGBB
int 0x40
; 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
int 0x40
; 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,0x6688dd ; button color RRGGBB
int 0x40
mov eax,62 ;Вызываем нашу функцию
int 0x40
cmp eax,0x00101010 ;Если функция исполнилась
je no_int ;нормально, то пропускаем печать в окно
;приложения
mov ebx,25*65536+35 ; draw info text with function 4
mov ecx,0x224466
mov edx,text
mov esi,40
newline:
mov eax,4
int 0x40
add ebx,10
add edx,40
cmp [edx],byte 'x'
jne newline
no_int:
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,2 ; 2, end of draw
int 0x40
ret
; DATA AREA
text:
db 'THIS IS AN EXAMPLE PROGRAM YOU COULD '
db 'USE, A:\EXAMPLE.ASM CODE IS COMMENTED '
db 'AND CLEAR. SYSTEM FUNCTIONS ARE IN FILE '
db 'SYSFUNCS.TXT AND COMMANDS IN CMD.TXT '
db 'x <- END MARKER, DONT DELETE '
labelt:
db 'EXAMPLE APPLICATION'
labellen:
I_END:
И в завершении этого раздела полезная примочка:
Для того что бы вычислить физический адрес приложения вызвавшего нашу функцию, следует проделать следующее:
mov esi,[0x3010] ; Помещаем в EAX адрес таблицы приложения
mov edi,[esi+0x10] ; Помещаем в EDI физический адрес начала
приложения в памяти
Это бывает нужно если мы передаем в приложение большой объем информации. Тогда просто выделяем в приложении свободное место под массив, и зная начало приложения в памяти, вычисляем адресс массива и записываем туда информацию.
Приложение. Компилляция ядра.
Как проходит компиляция ядра. Вы загружаете FASM. Указываете в
качестве входящего файла KERNEL.ASM, а в качестве исходящего KERNEL.MNT. Компилируете ядро. Теперь скидываете образ рамдиска на дискету: Выходим из Menuet штатным образом, и выбираем пункт 1) SAVE RAMDISK TO FLOPPY. После этого перезагружаем машину. Ядро перекомпилированно.
|
|