OS Menuet
 Новости
 Описание
 Текущая версия
 История
 Скриншоты

Скачать
 OS Menuet
 Дистрибутивы
 Загрузчики
 Русификация
 Программы
 Разное

Документация
 Статьи
 FAQ
 Hardware List
 Рассылки

О нашем сайте
 Публикация
 Конкурс
 Форум
 Старый форум
 Тестовые форумы

Ссылки
 О Menuet
 Другие OS
 Программисту

Официальный сайт/Official site MenuetOS>>



Rambler's Top100
Каталог "ПИНГВИН" - чуткий и душевный каталог!
Программирование в MenuetOS

Программирование в MenuetOS - v0.3
Для версии 0.67 pre-5 и выше
V.Turjanmaa

Программирование в MenuetOS

MenuetOS — это полностью написанная на 32-битном языке ассемблера операционная система, которая имеет многозадачную/многопотоковую конструкцию и обеспечивает графический интерфейс пользователя (GUI) для программирования на языке ассемблера.

Menuet владеет эффективным прикладным интерфейсом программирования (API), который быстро и легко освоить.

1) Программирование приложений

2) Программирование ядра

1) Программирование приложений для MenuetOS

1a) Структура приложения

Программирование в Menuet является довольно легкой и нетривиальной задачей даже если вы только начинаете изучать основную структуру приложений. В таком случае от вас требуется лишь немного опыта программирования на языке ассемблера.

MenuetOS API — это легкий для освоения набор функций с не иерархическим доступом.

Работа приложений основана на событиях.

Приложение извещается операционной системой (далее сокращенно ОС) типом события и работает соответственно. В приложении по-умолчанию существует три типа событий: window redraw (перерисовка окна), keypress (нажатие клавиши) и buttonpress (нажатие кнопки).

Ниже представлена диаграмма потока и структура приложения с событиями по-умолчанию:




  ;;;;;;;;;;;;;;;;;;;;;;;;;

  ;                       ;

  ;  ЗАГОЛОВОЧНЫЕ ДАННЫЕ  ;

  ;                       ;

  ;;;;;;::;;;;;;;;;;;;;;;;;



START:



  call draw_window



  ;;;;;;;;;;;;;;;;::;;;;;;;

  ;                       ;

  ;   ОЖИДАНИЕ СОБЫТИЯ    ;  <----------------------------------------------------------I

  ;                       ;                                                             I

  ;;;;;::;;;;;;;;;;;;;;;;;;                                                             I

            I                                                                           I

  ;;;;;;;::;;;;;;;;;;;;;;;;                                                             I

  ;                       ;     перерисовка   ->  вызов draw_window             ->      I

  ;СЧИТЫВАНИЕ ТИПА СОБЫТИЯ; ->  ключ      ->  считать нажатие клавиши   -> обработка  ->I

  ;                       ;     кнопка   ->  считать нажатие кнопки -> обработка  ->    I

  ;;;;;::;;;;;;;;;;;;;;;;;;





draw_window:



  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

  ;                            ;

  ;   ПРОРИСОВКА СТАТИЧЕСКИХ   ;

  ;       ЭЛЕМЕНТОВ ОКНА       ;

  ;                            ;

  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



  ret





DATA AREA:



  ;;;;;;;;;;;;;;;;;;;;;;;;

  ;                      ;

  ;  СТАТИЧЕСКИЕ ДАННЫЕ  ;

  ;                      ;

  ;;;;;;;;;;;;;;;;;;;;;;;;



1b) Пример на ассемблере

Реализация на ассемблере вышеуказанной структуры (1a) с множеством комментариев.

Системные вызовы Menuet выполняются с помощью команды 'int 0x40' с номером функции в регистре eax и других регистрах, используемых при необходимости.

Детали всех доступных системных вызовов описаны в разделе (1g) Системные вызовы.


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;                                                  ;

;      ПРИМЕР ПРИЛОЖЕНИЯ                           ;

;                                                  ;

;      Компилируется с помощью FASM для Menuet     ;

;                                                  ;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



; Заголовок



use32                                 ; директива компилятора - генерировать 32-битный код



               org    0x0             ; директива с аргументом 0x0 - адресом,

                                      ; с которого код будет начинаться в памяти



               db     'MENUET01'      ; 8-байтовый идентификатор для приложения

               dd     0x01            ; версия заголовка

               dd     START           ; указывает начало программы

               dd     I_END           ; метка в конце кода, указывает размер программы

               dd     0x100000        ; требуемое количество оперативной памяти

                                      ; Вы можете получить доступ к памяти с 0x0 до

                                      ; значения, указанного здесь. Перемещение

                                      ; кода выполнено с помощью набора селекторов ОС.

               dd     0x7fff0         ; позиция стэка в области памяти

               dd     0x0             ; Параметр, передающий величину,

                                      ; если установлено не нулевое значение,

                                      ; возможные параметры передаются на старте.

               dd     0x0             ; Зарезервировано для иконки







; Код





START:                          ; начало выполнения программы



    call draw_window            ; первым делом прорисовка окна





; После того, как окно прорисовано, обязанностью функции является организация основного цикла.

; События распределяются отсюда.



event_wait:





    mov  eax,10                 ; функция 10 : ожидание события

    int  0x40

                                ; тип события возвращается в eax



    cmp  eax,1                  ; Запрос события redraw ?

    je   red                    ; объяснение: на экране должна быть активность, тогда

                                ; части приложения перерисовываются.



    cmp  eax,2                  ; Ключ события в буфере ?

    je   key                    ; объяснение: пользователь нажимает клавишу пока

                                ; приложение находится в верхней части оконного стэка.



    cmp  eax,3                  ; Событие button в буфере ?

    je   button                 ; объяснение: пользователь нажал одну из

                                ; кнопок приложения.



    jmp  event_wait







; Следующая секция считывает событие и обрабатывает данные.





  red:                          ; Переключатель события redraw

    call draw_window            ; Мы вызываем функцию window_draw и

    jmp  event_wait             ; переходим назад к event_wait



  key:                          ; Переключатель события keypress

    mov  eax,2                  ; Ключ возвращается в ah. Ключ должен быть

    int  0x40                   ; считан и очищен из системной очереди.

    jmp  event_wait             ; Простое считывание ключа, игнорирование его и

                                ; и переход к функции event_wait.



  button:                       ; Переключатель события buttonpress

    mov  eax,17                 ; Номер кнопки определяется в window_draw и

    int  0x40                   ; возвращается в ах.



    cmp  ah,1                   ; идентификатор кнопки =1 ?

    jne  noclose

    mov  eax,-1                 ; Функция -1 : закрытие программы

    int  0x40

  noclose:



    jmp  event_wait             ; Эта команда для проигнорированных событий,

                                ; полезна при разработке.





;  *********************************************

;  *****  ОКОННЫЕ ОПРЕДЕЛЕНИЯ И ПРОРИСОВКА *****

;  *********************************************

;

;  Статические части окна прорисовываются в этой функции. Доступ к оконному холсту

;  можно будет получить позже из любой части этого кода (потока), к примеру, для отображения

;  процессов или записанных данных.

;

;  Статические части *должны* быть размещены вместе с функцией 12, ebx = 1 и ebx = 2.



draw_window:





    mov  eax,12                    ; функция 12:уведомляет ОС о прорисовке окна

    mov  ebx,1                     ; 1, запуск прорисовки

    int  0x40



                                   ; ПРОРИСОВКА ОКНА

    mov  eax,0                     ; функция 0 : определение и прорисовка окна

    mov  ebx,100*65536+300         ; [начало по x] *65536 + [ширина]

    mov  ecx,100*65536+120         ; [начало по y] *65536 + [высота]

    mov  edx,0x02ffffff            ; цвет рабочей области окна RRGGBB

                                   ; 0x02000000 = окно 2-го типа

    mov  esi,0x808899ff            ; цвет полосы заголовка RRGGBB

                                   ; 0x80000000 = цвет плана

    mov  edi,0x008899ff            ; цвет рамки RRGGBB

    int  0x40



                                   ; МЕТКА ОКНА

    mov  eax,4                     ; функция 4 : написать в окне текст

    mov  ebx,8*65536+8             ; [начало по x] *65536 + [начало по y]

    mov  ecx,0x00ddeeff            ; цвет текста RRGGBB

    mov  edx,labelt                ; указатель начала текста

    mov  esi,labellen-labelt       ; длина текста

    int  0x40



                                   ; КНОПКА ЗАКРЫТИЯ (CLOSE BUTTON)

    mov  eax,8                     ; функция 8 : определение и прорисовка кнопки

    mov  ebx,(300-19)*65536+12     ; [начало по x] *65536 + [ширина]

    mov  ecx,5*65536+12            ; [начало по y] *65536 + [высота]

    mov  edx,1                     ; идентификатор кнопки

    mov  esi,0x6677cc              ; цвет кнопки RRGGBB

    int  0x40





    mov  ebx,25*65536+35           ; прорисовка информационного текста с функцией 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



    mov  eax,12                    ; функция 12:уведомляет ОС о прорисовке окна

    mov  ebx,2                     ; 2, конец прорисовки

    int  0x40



    ret







;  *********************************************

;  ************   ОБЛАСТЬ ДАННЫХ   *************

;  *********************************************

;

; Данные могут быть свободно смешаны с кодом в любых частях программы.

; Заголовочная информация требуется лишь в начале программы.





text:       db  'ЭТО ПРИМЕР ПРОГРАММЫ, КОТОРЫЙ ВЫ МОЖЕТЕ       		'

            db  'ИСПОЛЬЗОВАТЬ, КОД A:\EXAMPLE.ASM ПРОКОММЕНТИРОВАН  	'

            db  'И ЧИСТ(Т.Е. БЕЗ ОШИБОК). СИСТЕМНЫЕ ФУНКЦИИ НАХОДЯТСЯ 	'

            db  'В ФАЙЛЕ SYSFUNCS.TXT А КОМАНДЫ В CMD.TXT    		'

            db  'x <- МАРКЕР КОНЦА, НЕ УДАЛЯЙТЕ            		'



labelt:     db  'ПРИМЕР ПРИЛОЖЕНИЯ'

labellen:





I_END:

Структура приложений ОС Menuet не ограничивается программированием на ассемблере, заголовок может быть написан практически на любом языке программирования. Тем не менее, общая конструкция программирования приложений предназначена для легкого 32-битного ассемблерного программирования. GUI крайне легок в управлении, особенно на ассемблере.

1c) Использование однородных системных цветов

В отличие от предыдущего примера, здесь мы сосредоточимся на создании основного приложения. В этом разделе больше внимания уделяется внешнему виду окна.

Вы можете использовать однородные системные цвета, определенные цветовой установкой приложения.

В данном примере появляется новая функция под названием get_system_colours


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;                                                  ;

;      ПРИМЕР ОДНОРОДНЫХ СИСТЕМНЫХ ЦВЕТОВ          ;

;                                                  ;

;      Компилируется с помощью FASM для Menuet     ;

;                                                  ;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



; Заголовок



use32                                 ; директива компилятора - генерировать 32-битный код



               org    0x0             ; директива с аргументом 0x0 - адресом,

                                      ; с которого код будет начинаться в памяти



               db     'MENUET01'      ; 8-байтовый идентификатор для приложения

               dd     0x01            ; версия заголовка

               dd     START           ; указывает начало программы

               dd     I_END           ; метка в конце кода, указывает размер программы

               dd     0x100000        ; требуемое количество оперативной памяти

                                      ; Вы можете получить доступ к памяти с 0x0 до

                                      ; значения, указанного здесь. Перемещение

                                      ; кода выполнено с помощью набора селекторов ОС.

               dd     0x7fff0         ; позиция стэка в области памяти

               dd     0x0             ; Параметр, передающий величину,

                                      ; если установлено не нулевое значение,

                                      ; возможные параметры передаются на старте.

               dd     0x0             ; Зарезервировано для иконки









window_size_X  equ  300

window_size_Y  equ  150





START:                          ; начало выполнения программы



    call draw_window            ; первым делом прорисовка окна





; После того, как окно прорисовано, обязанностью функции является организация основного цикла.

; События распределяются отсюда.



event_wait:





    mov  eax,10                 ; функция 10 : ожидание события

    int  0x40

                                ; тип события возвращается в eax



    cmp  eax,1                  ; Запрос события redraw ?

    je   red                    ; объяснение: на экране должна быть активность, тогда

                                ; части приложения перерисовываются.



    cmp  eax,2                  ; Ключ события в буфере ?

    je   key                    ; объяснение: пользователь нажимает клавишу пока

                                ; приложение находится в верхней части оконного стэка.



    cmp  eax,3                  ; Событие button в буфере ?

    je   button                 ; объяснение: пользователь нажал одну из

                                ; кнопок приложения.



    jmp  event_wait



; Следующая секция считывает событие и обрабатывает данные.





  red:                          ; Переключатель события redraw

    call draw_window            ; Мы вызываем функцию window_draw и

    jmp  event_wait             ; переходим назад к event_wait



  key:                          ; Переключатель события keypress

    mov  eax,2                  ; Ключ возвращается в ah. Ключ должен быть

    int  0x40                   ; считан и очищен из системной очереди.

    jmp  event_wait             ; Простое считывание ключа, игнорирование его и

                                ; и переход к функции event_wait.



  button:                       ; Переключатель события buttonpress

    mov  eax,17                 ; Номер кнопки определяется в window_draw и

    int  0x40                   ; возвращается в ах.



    cmp  ah,1                   ; идентификатор кнопки =1 ?

    jne  noclose

    mov  eax,-1                 ; Функция -1 : закрытие программы

    int  0x40

  noclose:



    jmp  event_wait             ; Эта команда для проигнорированных событий,

                                ; полезна при разработке.



get_system_colours:



    pusha



    mov  eax,48                       ; функция 48, системные цвета

    mov  ebx,3                        ; подфункция 3 : получить

    mov  ecx,app_colours              ; указатель на область возврата

    mov  edx,10*4                     ; номера байтов для возврата

    int  0x40



    popa



    ret





app_colours:                          ; ТАБЛИЦА СИСТЕМНЫХ ЦВЕТОВ



w_frames             dd 0x0           ; - РАМКА

w_grab               dd 0x0           ; - ПОЛОСА ЗАГОЛОВКА

w_grab_button        dd 0x0           ;   кнопка полосы заголовка

w_grab_button_text   dd 0x0           ;   текст кнопки полосы заголовка

w_grab_text          dd 0x0           ;   текст полосы заголовка

w_work               dd 0x0           ; - РАБОЧАЯ ОБЛАСТЬ

w_work_button        dd 0x0           ;   кнопка рабочей области

w_work_button_text   dd 0x0           ;   текст кнопки рабочей области

w_work_text          dd 0x0           ;   текст рабочей области

w_work_graph         dd 0x0           ;   графика рабочей области







;  *********************************************

;  *****  ОКОННЫЕ ОПРЕДЕЛЕНИЯ И ПРОРИСОВКА *****

;  *********************************************

;

;  Статические части окна прорисовываются в этой функции. Доступ к оконному холсту

;  можно будет получить позже из любой части этого кода (потока), к примеру, для отображения

;  процессов или записанных данных.

;

;  Статические части *должны* быть размещены вместе с функцией 12, ebx = 1 и ebx = 2.

;

;  При использовании системных цветов, оконные цвета считываются из

;  ТАБЛИЦЫ СИСТЕМНЫХ ЦВЕТОВ

;





draw_window:





    mov  eax,12                    ; функция 12:уведомляет ОС о прорисовке окна

    mov  ebx,1                     ; 1, запуск прорисовки

    int  0x40



    call get_system_colours        ; выборка системных цветов из ОС




                                   ; ПРОРИСОВКА ОКНА

    mov  eax,0                     ; функция 0 : определение и прорисовка окна



    mov  ebx,100*65536+window_size_X   ; [начало по x] *65536 + [ширина]

    mov  ecx,100*65536+window_size_Y   ; [начало по y] *65536 + [высота]



    mov  edx,[w_work]              ; цвет рабочей области 0xRRGGBB

    or   edx,0x02000000            ; 0x02000000 = окно 2-го типа

    mov  esi,[w_grab]              ; цвет полосы заголовка 0xRRGGBB

    or   esi,0x80000000            ; 0x80000000 = цвет плана

    mov  edi,[w_frames]            ; цвет рамки 0xRRGGBB

    int  0x40

                                   ; МЕТКА ОКНА

    mov  eax,4                     ; функция 4 : написать в окне текст

    mov  ebx,8*65536+8             ; [начало по x] *65536 + [начало по y]

    mov  ecx,0x00ddeeff            ; цвет текста RRGGBB

    mov  edx,labelt                ; указатель начала текста

    mov  esi,labellen-labelt       ; длина текста

    int  0x40





    mov  ebx,25*65536+35           ; прорисовка информационного текста с функцией 4

    mov  ecx,[w_work_text]

    mov  edx,text

    mov  esi,40

   newline:                         ; текст из ОБЛАСТИ ДАННЫХ

    mov  eax,4

    int  0x40

    add  ebx,10

    add  edx,40

    cmp  [edx],byte 'x'

    jne  newline



                                   ; КНОПКА ЗАКРЫТИЯ

    mov  eax,8                     ; функция 8 : определение и прорисовка кнопки

    mov  ebx,window_size_X

    sub  ebx,19

    shl  ebx,16

    mov  bx,12                     ; ebx = [начало по x] *65536 + [ширина]

    mov  ecx,5*65536+12            ; [начало по y] *65536 + [высота]

    mov  edx,1                     ; идентификатор кнопки

    mov  esi,[w_grab_button]       ; цвет кнопки RRGGBB

    int  0x40



    mov  eax,12                    ; функция 12:уведомляет ОС о прорисовке окна

    mov  ebx,2                     ; 2, конец прорисовки

    int  0x40



    ret





;  *********************************************

;  ************   ОБЛАСТЬ ДАННЫХ   *************

;  *********************************************

;

; Данные могут быть свободно смешаны с кодом в любых частях программы.

; Заголовочная информация требуется лишь в начале программы.



text:       db  'В ЭТОЙ ПРОГРАММЕ ИСПОЛЬЗУЮТСЯ ОДНОРОДНЫЕ СИСТЕМНЫЕ ЦВЕТА'

            db  'ВОЗВРАЩЕННЫЕ В ТАБЛИЦУ                     		'



            db  'x <- МАРКЕР КОНЦА, НЕ УДАЛЯЙТЕ                    	'





labelt:     db  'ПРИМЕР ПРИЛОЖЕНИЯ'

labellen:



I_END:

1d) Окно произвольной формы

В данном разделе мы рассмотрим пример изменения прямоугольной формы окна на любую другую. Новая функция здесь: shape_window.


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;                                                  ;

;      ПРИМЕР ПРИЛОЖЕНИЯ ИЗМЕНЕНИЯ ФОРМЫ           ;

;                                                  ;

;      Компилируется с помощью FASM для Menuet     ;

;                                                  ;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



; Заголовок



use32                                 ; директива компилятора - генерировать 32-битный код



               org    0x0             ; директива с аргументом 0x0 - адресом,

                                      ; с которого код будет начинаться в памяти



               db     'MENUET01'      ; 8-байтовый идентификатор для приложения

               dd     0x01            ; версия заголовка

               dd     START           ; указывает начало программы

               dd     I_END           ; метка в конце кода, указывает размер программы

               dd     0x100000        ; требуемое количество оперативной памяти

                                      ; Вы можете получить доступ к памяти с 0x0 до

                                      ; значения, указанного здесь. Перемещение

                                      ; кода выполнено с помощью набора селекторов ОС.

               dd     0x7fff0         ; позиция стэка в области памяти

               dd     0x0             ; Параметр, передающий величину,

                                      ; если установлено не нулевое значение,

                                      ; возможные параметры передаются на старте.

               dd     0x0             ; Зарезервировано для иконки





; Код



START:                          ; начало выполнения программы



    call shape_window           ; функция для формирования



    call draw_window            ; сначала прорисовка окна



still:



    mov  eax,10                 ; ожидание события

    int  0x40



    cmp  eax,1                  ; запрос события redraw ?

    je   red

    cmp  eax,2                  ; ключ в буфере ?

    je   key

    cmp  eax,3                  ; кнопка в буфере ?

    je   button



    jmp  still



  red:                          ; перерисовка

    call draw_window

    jmp  still



  key:                          ; ключ

    mov  eax,2                  ; считывание ключа и игнорирование его

    int  0x40

    jmp  still



  button:                       ; кнопка

    mov  eax,17                 ; получить идентификатор

    int  0x40



    cmp  ah,1                   ; идентификатор кнопки =1 ?

    jne  noclose

    mov  eax,-1                 ; закрытие этой программы

    int  0x40

  noclose:



    jmp  still



shape_window:



    pusha



    mov  eax,50       ; представление ссылки на область формы

    mov  ebx,0

    mov  ecx,shape_reference

    int  0x40



    mov  eax,50       ; представление масштаба формы  32 x 32  ->  128 x 128

    mov  ebx,1        ; нет необходимости давать эту команду, масштаб по-умолчанию 1:1

    mov  ecx,2        ; установка масштаба в 2^ecx

    int  0x40



    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





;  *********************************************

;  *****  ОКОННЫЕ ОПРЕДЕЛЕНИЯ И ПРОРИСОВКА *****

;  *********************************************





draw_window:



    mov  eax,12                    ; функция 12:уведомляет ОС о прорисовке окна

    mov  ebx,1                     ; 1, запуск прорисовки

    int  0x40



                                   ; ПРОРИСОВКА ОКНА

    mov  eax,0                     ; функция 0 : определение и прорисовка окна

    mov  ebx,100*65536+300         ; [начало по x] *65536 + [ширина]

    mov  ecx,100*65536+120         ; [начало по y] *65536 + [высота]

    mov  bx,word [x_size]

    mov  cx,word [y_size]

    mov  edx,0x00cccc00            ; цвет рабочей области RRGGBB,8->цвет плана

    mov  esi,0x00cccc00            ; цвет полосы заголовка RRGGBB,8->цвет плана

    mov  edi,0x00cccc00            ; цвет рамки    RRGGBB

    int  0x40



                                   ; КНОПКА ЗАКРЫТИЯ (CLOSE BUTTON)

    mov  eax,8                     ; функция 8 : определение и прорисовка кнопки

    mov  ebx,(300-19)*65536+12     ; [начало по x] *65536 + [ширина]

    mov  ecx,5*65536+12            ; [начало по y] *65536 + [высота]

    mov  edx,1                     ; идентификатор кнопки

    mov  esi,0x6677cc              ; цвет кнопки RRGGBB

    int  0x40





    mov  eax,12                    ; функция 12:уведомляет ОС о прорисовке окна

    mov  ebx,2                     ; 2, конец прорисовки

    int  0x40



    ret



; DATA



x_size  dd  127

y_size  dd  127



I_END:

1e) Потоки

Ассемблерная поточность MenuetOS имеет большие преимущества перед языками высокого уровня. Если вы сохраняете все переменные в регистрах, то у вас есть возможность запустить сколько угодно потоков из того же кода, так как память не используется и не требуется сохранение. Регистры сохраняются в сегментах переключения задач (Task Switch Segments) MenuetOS. Все, что вам нужно сделать, это установить новый стэк.

Потоки не отличаются от главного процесса и используют ту же область памяти, что и процесс, запустивший их. Они могут иметь свои собственные независимые окна и т.п. При закрытии приложения все потоки завершают свою работу посредством системного вызова по-умолчанию (eax = -1). Новая функция в данном примере: create_thread.


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;                                                      ;

;   ПРИМЕР ИСПОЛЬЗОВАНИЯ ПОТОКОВ                       ;

;                                                      ;

;   Компилируется с помощью FASM для Menuet            ;

;                                                      ;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



use32



               org    0x0



               db     'MENUET01'              ; 8-байтовый идентификатор

               dd     0x01                    ; версия заголовка

               dd     START                   ; указывает начало программы

               dd     I_END                   ; метка в конце кода, указывает размер программы

               dd     0x100000                ; требуемое количество оперативной памяти

               dd     0x80000                 ; esp

               dd     0x0 , 0x0               ; I_Param , I_Icon









START:                          ; начало выполнения программы



    call draw_window            ; сначала прорисовка окна



event_wait:



    mov  eax,10                 ; ожидание события

    int  0x40



    cmp  eax,1                  ; Запрос события redraw ?

    je   red

    cmp  eax,2                  ; ключ в буфере ?

    je   key

    cmp  eax,3                  ; кнопка в буфере ?

    je   button



    jmp  event_wait



  red:                          ; перерисовка

    call draw_window

    jmp  event_wait



  key:                          ; ключ

    mov  eax,2                  ; считывание и игнорирование

    int  0x40

    jmp  event_wait



  button:                       ; кнопка

    mov  eax,17                 ; получение идентификатора

    int  0x40



    cmp  ah,1                   ; идентификатор кнопки =1 ?

    jne  noclose

    mov  eax,-1                 ; закрытие программы (потока)

    int  0x40

  noclose:



    cmp  ah,2                   ; вызов create_thread

    jne  no_thread

    call create_thread

    jmp  event_wait

  no_thread:



    jmp  event_wait





; СОЗДАНИЕ ПОТОКА

;

; Все, что нам нужно сделать - это отправить потоковый адрес входа в ecx и

; позицию нового стэка в edx с функцией eax=51, ebx=1



create_thread:



    cmp  [thread_stack],0xf0000

    jge  no_new_thread



    add  [thread_stack],0x1000



    mov  eax,51                   ; системный вызов thread_create

    mov  ebx,1

    mov  ecx,START

    mov  edx,[thread_stack]

    int  0x40



  no_new_thread:



    ret



thread_stack dd 0x80000





;  *********************************************

;  *****  ОКОННЫЕ ОПРЕДЕЛЕНИЯ И ПРОРИСОВКА *****

;  *********************************************





draw_window:



    mov  eax,12                    ; функция 12:уведомляет ОС о прорисовке окна

    mov  ebx,1                     ; 1, запуск прорисовки

    int  0x40



                                   ; ПРОРИСОВКА ОКНА

    mov  eax,0                     ; функция 0 : определение и прорисовка окна

    mov  ebx,100*65536+300         ; [начало по x] *65536 + [ширина]

    mov  ecx,100*65536+120         ; [начало по y] *65536 + [высота]

    mov  esi,[thread_stack]

    sub  esi,0x80000

    shr  esi,11

    shl  esi,16

    add  ebx,esi

    add  ecx,esi

    mov  edx,0x02ffffff            ; цвет рабочей области RRGGBB,8->цвет плана

    mov  esi,0x808899ff            ; цвет полосы заголовка  RRGGBB,8->цвет плана

    mov  edi,0x008899ff            ; цвет рамки    RRGGBB

    int  0x40



                                   ; МЕТКА ОКНА

    mov  eax,4                     ; функция 4 : написать в окне текст

    mov  ebx,8*65536+8             ; [начало по x] *65536 + [начало по y]

    mov  ecx,0x00ddeeff            ; цвет текста RRGGBB

    mov  edx,labelt                ; указатель на начало текста

    mov  esi,labellen-labelt       ; длина текста

    int  0x40



                                   ; КНОПКА ЗАКРЫТИЯ

    mov  eax,8                     ; функция 8 : определение и прорисовка окна

    mov  ebx,(300-19)*65536+12     ; [начало по x] *65536 + [ширина]

    mov  ecx,5*65536+12            ; [начало по y] *65536 + [высота]

    mov  edx,1                     ; идентификатор кнопки

    mov  esi,0x6677cc              ; цвет кнопки RRGGBB

    int  0x40



    mov  eax,8                     ; КНОПКА НОВОГО ПОТОКА

    mov  ebx,25*65536+128

    mov  ecx,88*65536+20

    mov  edx,2

    mov  esi,0x6677cc

    int  0x40



    mov  ebx,25*65536+35           ; прорисовка информационного текста с функцией 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



    mov  eax,12                    ; функция 12:уведомляет ОС о прорисовке окна

    mov  ebx,2                     ; 2, конец прорисовки

    int  0x40



    ret





; ОБЛАСТЬ ДАННЫХ





text:

    db 'ЭТОТ ПРИМЕР СОЗДАЕТ ПОТОКИ ПУТЕМ ЗАПУСКА	'

    db 'ОДНОГО И ТОГО ЖЕ КОДА МНОГО РАЗ. ВСЕ, ЧТО	'

    db 'НАМ НУЖНО, ЭТО НОВЫЙ СТЕК ДЛЯ КАЖДОГО ПОТОКА.	'

    db 'ВСЕ ПОТОКИ ИСПОЛЬЗУЮТ ОДИНАКОВУЮ ПАМЯТЬ.	'

    db '                                        	'

    db '                                        	'

    db '  СОЗДАНИЕ НОВОГО ПОТОКА			'



    db 'x <- МАРКЕР КОНЦА, НЕ УДАЛЯЙТЕ		'





labelt:

     db   'ПРИМЕР ИСПОЛЬЗОВАНИЯ ПОТОКОВ'

labellen:



I_END:

1f) Данные реального времени

Следующий пример сфокусирован на формировании данных реального времени и их обработке. Приложение информирует ОС о всех портах и типах данных для считывания по специфическому номеру прерывания IRQ.

Шаги:

  1. резервирование области порта Ввода/Вывода;
  2. резервирование номера IRQ;
  3. программирование IRQ;
  4. программирование списка СОБЫТИЙ для нужного IRQ;
  5. временная обработка данных;
  6. возвращение к событиям по-умолчанию — освобождение IRQ из списка СОБЫТИЙ;
  7. освобождение IRQ;
  8. освобождение области порта;
  9. завершение работы программы.

После того, как IRQ спрограммирован, приложение получает новое событие для организации главного цикла событий, номер (IRQ+16). Когда приложение получает это событие, ОС записывает данные, готовые для обработки приложением.

Основная структура обработки данных реального времени показана ниже в таблице.

Все шаги слева от (A) — обрабатываются ОС, справа от (A) — приложением.


IRQ          ВЛАДЕЛЕЦ    =>  ЗАПИСЬ ДАННЫХ  (A) SYS_EVENT => СЧИТЫВАНИЕ ДАННЫХ => ОБРАБОТКА



 0 ТАЙМЕР      SYS

 1 КЛАВИАТУРА  SYS

 2             free      ->

 3 COM МЫШЬ    SYS/free  ?>

 4 COM МЫШЬ    SYS/free  ?>

 5 ЗВ. КАРТА   SYS

 6 ФЛОППИ      SYS

 7             free      ->

 8             free      ->

 9             free      ->

10             free      ->

11             free      ->

12 PS2 МЫШЬ    SYS/free  ?>

13 МАТ. ПРОЦ   SYS

14 IDE         SYS

15 IDE         SYS

Пример обработки данных реального времени:


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;                                                ;


;    ДАННЫЕ РЕАЛЬНОГО ВРЕМЕНИ                    ;

;                                                ;

;    Компилируется с помощью FASM для Menuet     ;

;                                                ;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;





use32



                org     0x0



                db      'MENUET00'              ; 8-байтовый идентификатор

                dd      56                      ; требуемая версия ОС

                dd      START                   ; указывает начало программы

                dd      I_END                   ; метка в конце кода, указывает размер программы

                dd      0x100000                ; требуемое количество оперативной памяти

                                                ; esp = 0x7FFF0

                dd      0x00000000              ; зарезервировано=отсутствует расширенный заголовок







START:                          ; начало выполнения программы



    call draw_window            ; сначала прорисовка окна



    call program_real_time_data ; программирование ОС для получения данных реального времени



    call program_com_port       ; программирование com-порта для специфических устройств



event_wait:



    mov  eax,10                 ; ожидание события

    int  0x40



    cmp  eax,1                  ; Запрос события redraw ?

    je   red

    cmp  eax,2                  ; ключ в буфере ?

    je   key

    cmp  eax,3                  ; кнопка в буфере ?

    je   button



    cmp  eax,16+4               ; РВ: новое событие для требуемых IRQ данных (16+IRQ)

    je   read_rt



    jmp  event_wait





;  Следующая секция считывает событие и обрабатывает данные.





  read_rt:                      ; данные реального времени (РВ)

    mov  eax,42                 ; Функция 42 возвращает данные для IRQ 4

    mov  ebx,4                  ;

    int  0x40                   ; ОС возвращает записанные данные

                                ; eax  номер байтов в буфере слева

                                ; bl   данные

                                ; ecx  0 =  успешно, другое значение = нет данных в буфере.



    call process_data

    jmp  event_wait



  red:                          ; перерисовка

    call draw_window

    jmp  event_wait



  key:                          ; ключ

    mov  eax,2                  ; считывание и игнорирование

    int  0x40

    jmp  event_wait



  button:                       ; кнопка

    mov  eax,17                 ; получить идентификатор

    int  0x40





    cmp  ah,1                   ; идентификатор кнопки =1 ?

    jne  noclose



    call free_real_time_data



    mov  eax,-1                 ; закрытие программы

    int  0x40

  noclose:



    jmp  event_wait







program_real_time_data:





    ;   Программирование выборки данных реального времени

    ;

    ;   1) резервирование области порта Ввода/Вывода

    ;   2) резервирование IRQ

    ;   3) программирование IRQ

    ;   4) программирование списка СОБЫТИЙ для требуемого IRQ

    ;





    pusha



    mov  eax,46           ; резервирование портов 0x3f0 - 0x3ff

    mov  ebx,0

    mov  ecx,0x3f0

    mov  edx,0x3ff

    int  0x40



    mov  eax,45           ; резервирование irq 4

    mov  ebx,0

    mov  ecx,4

    int  0x40



    mov  eax,44           ; установка считывающих портов для 4

    mov  ebx,irqtable

    mov  ecx,4

    int  0x40



    mov  eax,40                                 ; получение данных из com 1 с irq 4

    mov  ebx,0000000000010000b shl 16 + 111b    ; после этого у нас появляется новое

                                                ; событие (16+4)

    int  0x40



    popa



    ret







irqtable:



    dd  0x3f8+0x01000000 ; 3f8 =port to read  : 01 =считан байт, 02 =считано слово



    dd  0x0              ; 0x0 = завершает работу считывания через число IRQ событий

    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:



    ;  Освобождение использованных ресурсов

    ;

    ;  1) получение событий по-умолчанию

    ;  2) освобождение irq посредством функции 45,1

    ;  3) освобождение области порта посредством функции 46,1

    ;





    pusha



    mov  eax,40                 ; события по-умолчанию - блокировка irq 4 события

    mov  ebx,111b

    int  0x40



    mov  eax,45                 ; освобождение irq

    mov  ebx,1

    mov  ecx,4

    int  0x40



    mov  eax,46                 ; освобождение портов 0x3f0-0x3ff

    mov  ebx,1

    mov  ecx,0x3f0

    mov  edx,0x3ff

    int  0x40



    popa



    ret







; Следующие функции предназначены для обработки специфических данных устройств





process_data:



    cmp  ebx,80

    jne  nocd



    mov  eax,19

    mov  ebx,cdplayer

    mov  ecx,0

    int  0x40





  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]

    int  0x40

    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           ; прорисовка информационного текста с помощью функции 4

    mov  ecx,0xffffff

    mov  edx,text

    mov  esi,40

    mov  edi,20

  newline:

    mov  eax,4

    int  0x40

    add  ebx,10

    add  edx,40

    dec  edi

    jne  newline



    popa



    ret







program_com_port:



    ; Следующая последовательность программирует COM-порт для инфракрасного получателя



    mov  cx,0x3f3+8

    mov  bl,0x80

    mov  eax,43

    int  0x40



    mov  cx,0x3f1+8

    mov  bl,0

    mov  eax,43

    int  0x40



    mov  cx,0x3f0+8

    mov  bl,0x30 / 4

    mov  eax,43

    int  0x40



    mov  cx,0x3f3+8

    mov  bl,3

    mov  eax,43

    int  0x40



    mov  cx,0x3f4+8

    mov  bl,0xB

    mov  eax,43

    int  0x40



    mov  cx,0x3f1+8

    mov  bl,1

    mov  eax,43

    int  0x40



    mov  eax,5

    mov  ebx,100

    int  0x40



    mov  cx,0x3f8

    mov  bl,'I'

    mov  eax,43

    int  0x40



    mov  eax,5

    mov  ebx,10

    int  0x40



    mov  cx,0x3f8

    mov  bl,'R'

    mov  eax,43

    int  0x40



    ret











;  *********************************************

;  *****  ОКОННЫЕ ОПРЕДЕЛЕНИЯ И ПРОРИСОВКА *****

;  *********************************************





draw_window:



    mov  eax,12                    ; функция 12:уведомляет ОС о прорисовке окна

    mov  ebx,2                     ; 2, конец прорисовки

    int  0x40



                                   ; ПРОРИСОВКА ОКНА

    mov  eax,0                     ; функция 0 : определение и прорисовка окна

    mov  ebx,100*65536+300         ; [начало по x] *65536 + [ширина]

    mov  ecx,100*65536+120         ; [начало по y] *65536 + [высота]

    mov  edx,[wcolor]              ; цвет рабочей области RRGGBB,8->цвет

    mov  esi,0x8099bbff            ; цвет полосы заголовка  RRGGBB,8->цвет плана

    mov  edi,0x00ffffff            ; цвет рамки    RRGGBB

    int  0x40



                                   ; МЕТКА ОКНА

    mov  eax,4                     ; функция 4 : написать в окне текст

    mov  ebx,8*65536+8             ; [начало по x] *65536 + [начало по y]

    mov  ecx,0x00ddeeff            ; цвет текста RRGGBB

    mov  edx,labelt                ; указатель на начало текста

    mov  esi,labellen-labelt       ; длина текста

    int  0x40



                                   ; КНОПКА ЗАКРЫТИЯ

    mov  eax,8                     ; функция 8 : определение и прорисовка окна

    mov  ebx,(300-19)*65536+12     ; [начало по x] *65536 + [ширина]

    mov  ecx,5*65536+12            ; [начало по y] *65536 + [высота]

    mov  edx,1                     ; идентификатор кнопки

    mov  esi,0x6677cc              ; цвет кнопки RRGGBB

    int  0x40



    call draw_text



    mov  eax,12

    mov  ebx,2

    int  0x40



    ret









; ОБЛАСТЬ ДАННЫХ



wcolor   dd  0x0

pos      dd  0x0



cdplayer db  'CDPLAY     '

labelt   db  'ИНФРАКРАСНЫЙ ПОЛУЧАТЕЛЬ ДЛЯ IRMAN В COM 1'

labellen:



text:



I_END:

1g) Системные функции

Номер функции сохраняется в регистре eax, а команда INT 0x40 выполняет ее.

00 = ОПРЕДЕЛЕНИЕ И ПРОРИСОВКА ОКНА


     ebx [начало по x]*65536 + [ширина]

     ecx [начало по y]*65536 + [высота]

     edx цвет тела      0xXYRRGGBB  если X=8 -> цвет плана

                                    если Y=0 -> окно 1-го типа

                                    если Y=1 -> резервирование области, без прорисовки

                                    если Y=2 -> окно 2-го типа

                                    если Y=3 -> пустое окно,

                                              кнопка закрытия идентификатор=1 добавлена автоматически

     esi цвет полосы заголовка 0xX0RRGGBB  если X=8 -> негативный цвет плана

                                       если X=4 -> позитивный цвет плана

     edi цвет рамки    0x00RRGGBB

     ret: никаких изменений

01 = ПИКСЕЛЬНАЯ УСТАНОВКА


     ebx [x]

     ecx [y]

     edx цвет пикселя 0x0XRRGGBB

                        ^ 0 нормальная установка, 1 негативная

     ret: никаких изменений

02 = ПОЛУЧЕНИЕ КЛЮЧА


     ret: al 0 удачно -> ah = ключ

          al 1 ключ в буфере отсутствует

03 = ПОЛУЧЕНИЕ СИСТЕМНЫХ ЧАСОВ


     ret: eax 0x00SSMMHH сек,мин,часы

04 = ЗАПИСЬ ТЕКСТА В ОКНО


     ebx [начало по x]*65536 + [начало по y]

     ecx цвет текста 0x00RRGGBB

     edx указатель на начало текста

     esi длина текста

     ret: никаких изменений

05 = ЗАДЕРЖКА X/100 СЕКУНД


     ebx задержка в 1/100 секундах

     ret: никаких изменений

06 = ОТКРЫТИЕ ФАЙЛА С ДИСКЕТЫ


     ebx указатель на файл -> 11 заглавных букв

     ecx множество 0x00000000 - зарезервировано

     edx множество 0xffffffff - зарезервировано

     esi считывание в позицию памяти

     ret: никаких изменений

07 = ВСТАВКА ИЗОБРАЖЕНИЯ


     ebx указатель на изображение в памяти - RRGGBBRRGGBB..

     ecx размер окна [x]*65536+[y]

     edx позиция изображения в окне [x]*65536+[y]

     ret: eax 0 удачно, 1 перекрытие

08 = ОПРЕДЕЛЕНИЕ КНОПКИ


     ebx [начало по x]*65536 + [ширина]

     ecx [начало по y]*65536 + [высота]

     edx номер идентификатора кнопки

     esi цвет кнопки 0x 00 RR GG BB

     ret: никаких изменений

09 = ИНФОРМАЦИЯ О ПРОЦЕССАХ


     ebx указатель на 1024-байтовую таблицу

     ecx номер процесса

     ret: eax номера процессов

          table :  +00  dword   использование процессора

                   +04   word   позиция процессов в оконном стэке

                   +06   word   значение оконного стэка в регистре ecx

                   +10  12 db   имя процесса

                   +22  dword   начало памяти процессов

                   +26  dword   использование памяти процессами

                   +30  dword   идентификатор процесса (PID)

10 = ОЖИДАНИЕ СОБЫТИЯ


     ret: eax тип события, 1 перерисовка окна, 2 ключ в буфере, 3 нажата кнопка

11 = ПРОВЕРКА СОБЫТИЯ, БЕЗ ОЖИДАНИЯ


     ret: eax 0 нет события, 1 перерисовка окна, 2 ключ в буфере, 3 нажата кнопка

12 = СТАТУС ПЕРЕРИСОВКИ ОКНА


     ebx  1 начало перерисовки, 2 конец перерисовки

     ret: никаких изменений

13 = ЗОНА ПРОРИСОВКИ


     ebx [начало по x]*65536 + [ширина]

     ecx [начало по y]*65536 + [высота]

     edx цвет 0x00RRGGBB

     ret: никаких изменений

14 = ПОЛУЧЕНИЕ ЭКРАНА МАКСИМУМА


     ret: eax [экран x макс]*65536 + [экран y макс]

15 = ФОН


	ebx 1 : установка размера фона

				ecx x размер

				edx y размер

	ebx 2 : запись в фоновую память - макс (0x100000-16)

				ecx позиция в памяти в байтах

				edx цвет 0x00RRGGBB

	ebx 3 : прорисовка фона

	ebx 4 : тип прорисовки фона

				ecx 1 - размножение

  				ecx 2 - растягивание ebx

	ebx 5 : перемещение изображения в фоновую память ОС

             ecx - откуда

             edx - куда в фоновую память ОС

             esi - количество байтов для перемещения

16 = [ не готова - запись кэша на дискету ]

17 = ПОЛУЧЕНИЕ ИДЕНТИФИКАТОРА НАЖАТОЙ КЛАВИШИ


     ret: al 0 удачный -> ah = номер идентификатора

          al 1 ключ в буфере отсутствует

18 = СИСТЕМНЫЙ СЕРВИС


     ebx 1 - системная загрузка

     ebx 2 - завершение, ecx нет обработки

     ebx 4 - холостые циклы часов / секунды

     ebx 5 - счетчик отметки времени / секунды - скорость процессора

19 = ЗАПУСК ПРОГРАММ


     ebx указатель на 11-и символьное имя файла

     ecx 0, или указатель на начальные параметры ASCIIZ - макс 256 байт

     ret: eax 0       удачно

          eax прочее  код ошибки

20 = MIDI ИНТЕРФЕЙС - MPU401


     ebx  1 - сброс устройства

     ebx  2 - данные cl midi для вывода

21 = НАСТРОЙКА ДЛЯ УСТРОЙСТВ


     ebx 1=roland mpu midi base, базовый адрес Ввода/Вывода

     ebx 2=клавиатура 1 базовая раскладка  2 раскладка shift (ecx указатель на раскладку)

                    9 страна 1eng 2fr 3ger 4rus

     ebx 3=cd база  1 pri.master  2 pri slave,

                    3 sec master  4 sec slave

     ebx 4=sb16 база, базовый адрес Ввода/Вывода

     ebx 5=системный язык, 1eng 2fi 3ger 4rus

     ebx 6=wss база, базовый адрес Ввода/Вывода

     ebx 7=hd база, 1 pri.master  2 pri slave

                    3 sec master  4 sec slave

     ebx 8=fat32 раздел на жестком диске

22 = НЕ ИСПОЛЬЗУЕТСЯ

23 = ОЖИДАНИЕ СОБЫТИЯ С ТАЙМ-АУТОМ


     ebx время задержки в часах

     ret: eax тип события: 0 нет события, 1 перерисовка окна,

                           2 ключ в буфере, 3 кнопка

24 = CD AUDIO


     ebx 1 - проигрывание из ecx 00 FR SS MM

     ebx 2 - отправка размера списка песен ecx в [edx]

     ebx 3 - stop/pause play

25 = SB16 - mixer I


     ebx 1 - установка громкости в cl [L]*16+[R]

     ebx 2 - установка громкости cd в cl [L]*16+[R]

26 = ПОЛУЧЕНИЕ НАСТРОЙКИ ДЛЯ УСТРОЙСТВ


     ebx 1=roland mpu midi base, базовый адрес Ввода/Вывода

     ebx 2=клавиатура 1 базовая раскладка  2 раскладка shift

                    9 страна 1eng 2fi 3ger 4rus

     ebx 3=cd база  1 pri.master  2 pri slave,

                    3 sec master  4 sec slave

     ebx 4=sb16 база, базовый адрес Ввода/Вывода

     ebx 5=системный язык, 1eng 2fi 3ger 4rus

     ebx 6=wss база, базовый адрес Ввода/Вывода

     ebx 7=hd база, 1 pri.master  2 pri slave

                    3 sec master  4 sec slave

     ebx 8=fat32 раздел на жестком диске

     ebx 9=1/100 таймер stard-> eax

     возвращение значения в eax

27 = ЗВУКОВАЯ СИСТЕМА ОКОН


     ebx 1 - установка громкости в cl 0-255

     ebx 2 - установка громкости cd в cl 0-255

28 = SB16 - mixer II


     ebx 1 - установка громкости в cl 0-255

     ebx 2 - установка громкости cd в cl 0-255

29 = ПОЛУЧЕНИЕ ДАТЫ


     ret: eax 0x00YYDDMM год день месяц

30 = ЧТЕНИЕ ДАННЫХ С ЖЕСТКОГО ДИСКА


     ebx  указатель на файл

     ecx  длина файла

     edx  блок для считывания, начинается с 1, размер блока = 512 байт

     esi  зарезервирован, установлен как 1

     edi  указатель на область возврата/работы (как минимум 20 000 байт)



     return: work_area+1024 <- запрошенный блок 512 байт

31 = ЗАПУСК ПРИЛОЖЕНИЯ ИЗ ЖЕСТКОГО ДИСКА


     ebx  указатель на файл

     ecx  длина файла

     edx  указатель на область возврата/работы (как минимум 20 000 байт)

     ret  eax=0 удачно, eax<>0 код ошибки

32 = УДАЛЕНИЕ ФАЙЛА ИЗ ОБРАЗА ДИСКЕТЫ В ПАМЯТИ


     ebx  указатель на файл

33 = СОХРАНЕНИЕ ФАЙЛА В ОБРАЗ ДИСКЕТЫ В ПАМЯТИ


     ebx  указатель на имя файл

     ecx  указатель на дату

     edx  количество для записи в байтах

     esi  0 создание нового, ( 1 добавление - еще не реализовано )

34 = СЧИТЫВАНИЕ КАТАЛОГА С ДИСКЕТЫ


     ebx  зарезервирован : установлен как 0

     ecx  зарезервирован : установлен как 0

     edx  начинает считывать блок 512

     esi  зарезервирован : установлен как 1

     edi  указатель на область возврата

35 = СЧИТЫВАНИЕ ЭКРАННОГО ПИКСЕЛЯ


     ebx = количество пикселей по диагонали (от верхней левой части экрана)



     возвращает : eax = 0x00RRGGBB

36 = СЧИТЫВАНИЕ СТРОКИ (не закончена)

37 = СЧИТЫВАНИЕ ПОЗИЦИИ МЫШИ


     ebx=0 родительский экран

     ebx=1 родительское окно

     ebx=2 нажаты кнопки

     возвращает в eax

38 = ПРОРИСОВКА ЛИНИИ


     ebx  [начало по x] shl 16 + [x конец]

     ecx  [начало по y] shl 16 + [y конец]

     edx  цвет 0x00RRGGBB



     ret: никаких изменений

39 = ПОЛУЧИТЬ ФОН


     ebx=1 -> eax=[фон x размер] shl 16 + [фон y размер]

     ebx=2

       ecx= позиция фоновой карты памяти для возвращения в eax

     ebx=4 -> eax=1 размноженный, eax=2 растянутый

40 = УСТАНОВКА ПОЛЯ БИТОВ ДЛЯ ТРЕБУЕМЫХ СОБЫТИЙ


     as default:

     ebx = 00000000 00000000 00000000 00000111b  события:

                                             I   оконная прорисовка

                                            I    ключ в буфере

                                           I     кнопка в буфере

                                          I      (конец запроса)

                                         I       прорисовка настольного фона

                                        I        (изменение мыши)

           I---------------I                     получение данных о прерываниях

41 = ПОЛУЧЕНИЕ ВЛАДЕЛЬЦА IRQ


     ebx = irq



     возвращает: идентификатор процесса

42 = СЧИТЫВАНИЕ ДАННЫХ ПОСРЕДСТВОМ IRQ


     ebx  номер IRQ

     return :  eax  номер байтов в буфере

                bl  данные

               ecx  0 = удачное считывание данных

                    1 = данные отсутствуют в буфере

                    2 = некорректный владелец IRQ

43 = ОТПРАВЛЕНИЕ ДАННЫХ В УСТРОЙСТВА


     bx  : порт

     cl  : данные

     возвращает : eax = если 0 удачно, other = ошибка

44 = ПРОГРАММИРОВАНИЕ IRQ


     ebx  указатель на таблицу

     ecx  номер irq

45 = РЕЗЕРВИРОВАНИЕ/ОСВОБОЖДЕНИЕ IRQ


     ebx  0 зарезервировано  1 освобождено

     ecx  номер IRQ

     ret  eax 0 удачно,  1 ошибка

46 = РЕЗЕРВИРОВАНИЕ/ОСВОБОЖДЕНИЕ ОБЛАСТИ ПОРТА


     ebx  0 зарезервировано  1 освобождено

     ecx  начало области порта

     edx  конец области порта

     ret  eax 0 удачно,  1 ошибка

47 = ОТОБРАЖЕНИЕ ЧИСЕЛ В ОКНЕ


     ebx = тип вывода, bl=0 -> ecx - номер

                       bl=1 -> ecx - указатель

                       bh=0 -> отображение в десятичном виде

                       bh=1 -> отображение в шестнадцатиричном виде

                       bh=2 -> отображение в двоичном виде

           bits 16-21 = номер цифр для вывода (0-32)

           bits 22-31 = зарезервировано

     ecx = номер или указатель

     edx = x shl 16 + y

     esi = цвет

48 = ОПРЕДЕЛЕНИЕ ОБЩИХ СВОЙСТВ ОКНА


     ebx = 0      применить/перерисовать

        ecx = 0 , применить/перерисовать desktop

     ebx = 1      определение стиля кнопки

        ecx = 0 , установка плоских кнопок

        ecx = 1 , установка трехмерных кнопок

     ebx = 2      определение оконных цветов

        ecx = указатель на таблицу

        edx = номер определенных байтов

     ebx = 3      получение определенных оконных цветов

        ecx = указатель на таблицу

        edx = номер байтов для получения

49 = ОПРЕДЕЛЕНИЕ ВНУТРЕННИХ ПРЕРЫВАНИЙ ПРИЛОЖЕНИЯ


     ebx = 0

      ecx  указатель на таблицу данных прерываний dword x 256

           внутри приложения



     ret : никаких изменений

50 = ОКНА ПРОИЗВОЛЬНОЙ ФОРМЫ И МАСШТАБА


     ebx = 0 ; формирование ссылочной области

       ecx = указатель на ссылочную область

             байт на пиксель, 0 не используется, 1=используется, другие = зарезервированы

     ebx = 1 ; масштаб ссылочной области (по-умолчанию 1:1)

       ecx : установка масштаба в 2^ecx



     ret : никаких изменений

51 = СОЗДАНИЕ ПОТОКА


     ebx = 1  ; создание

       ecx    ; = точка входа потока

       edx    ; = позиция стэка потока



     ret : никаких изменений

52 = СТАТУС СТЭКОВОГО ДРАЙВЕРА


     - еще не готова

53 = ИНТЕРФЕЙС СОКЕТОВ


     - еще не готова

54 = ПОЛЬЗОВАТЕЛЬСКИЕ СОБЫТИЯ


     - еще не готова

55 = ЗВУКОВОЙ ИНТЕРФЕЙС


     ebx = 0     ; загрузка 44 кГц 8 бит моно звукового блока

       ecx       ; = указатель на 65536-байтовый звуковой блок



     ebx = 1     ; проигрывание 44 кГц 8 бит моно звукового блока

56 = ЗАПИСЬ ФАЙЛА НА ЖЕСТКИЙ ДИСК


     ebx  указатель на 12-ти символьное имя файла

     ecx  байты для записи

     edx  указатель на данные для записи

     esi  указатель на путь

          path db 0

57 = УДАЛЕНИЕ ФАЙЛА С ЖЕСТКОГО ДИСКА


     ebx   указатель на имя файла : 11 заглавных букв

     edx   указатель на путь : path db 0

58 = ДОСТУП К СИСТЕМНОМУ ДЕРЕВУ


     ebx    указатель на блок файловой информации



     fileinfo:



     dd   0x0                            ; 0=чтение (/запись/удаление/добавление)

     dd   0x0                            ; 512 блок для чтения 0+

     dd   0x1                            ; блоки для чтения (/байты для записи/добавление)

     dd   0x20000                        ; возвращение указателя данных

     dd   0x10000                        ; рабочая область для ОС - 16384 байт

     db   '/RAMDISK/FIRST/KERNEL.ASM',0  ; ASCIIZ каталог & имя файла

59 = ТРАССИРОВКА СИСТЕМНЫХ ВЫЗОВОВ ИЗ ПРОЦЕССОВ


     ebx = 0   ; получение системных событий

       ecx     ; указатель на таблицу  -> ; дескриптор 64 байты/системные вызовы

                                      ; +00 PID

                                      ; +32 EDI

                                      ; +36 ESI

                                      ; +40 EBP

                                      ; +44 ESP

                                      ; +48 EBX

                                      ; +52 EDX

                                      ; +56 ECX

                                      ; +60 EAX



       edx     ; номер байтов для возвращения в таблицу (к настоящему времени макс 16*64)



     ret:  eax = номер системных вызовов с начала

                    данные последнего системного вызова сохраняются

                    (eax mod 16)*64 в таблице

              ebx = 0 : вышеописанный формат







-1 = КОНЕЦ ПРИЛОЖЕНИЯ

Программирование ядра MenuetOS

2a) Файлы ядра


 KERNEL.ASM  -  KERNEL16.INC - BOOTCODE.INC    загрузочная информация

                             - BOOTENG.INC     язык загрузки



             -  KERNEL32.INC - ДИСПЛЕЙНЫЕ ФАЙЛЫ

                             - ЗВУКОВЫЕ ФАЙЛЫ

                             - ФАЙЛЫ ЖЕСТКОГО ДИСКА

Главный код ядра находится в файле KERNEL.ASM. Файлы Kernel16.inc и Kernel32.inc содержат драйверы устройств.

В будущем появится отдельная установочная программа для выбора нужных драйверов. Для точной настройки компьютера у пользователя будет скомпилированное ядро.

Ассемблер Fasm 1.30+ используется при компиляции ядра. На данный момент Fasm запускается на таких платформах: Menuet, Dos, Windows и Wine/dosemu в Linux.

2b) Последовательность загрузки

После включении питания компьютера системный bios загружает загрузочный сектор bootmosf.asm, который, в свою очередь, загружает файл ядра KERNEL.MNT с дискеты. Для обозначения загрузки ядра, на экране отображается несколько точек. В случае, если ваш компьютер зависает на этом этапе, значит, ваша дискета повреждена и у загрузочного сектора возникают трудности при получении доступе к ней.

При удачной загрузке вы должны увидеть синий экран установки с надписью версии MenuetOS. На этом этапе ядро выводит версию bios vesa и выдает запрос пользователю сделать выбор видеорежима. Почти все современные карты поддерживают стандарт VESA 3.0. Для работы в Menuet вполне хватает поддержки стандарта VESA 2.0 или VESA 1.2. Для современных карт вы можете смело выбирать видеорежимы с поддержкой VESA 2.0. Режимы работы некоторых видеокарт вы можете посмотреть в HardWare-листе. Далее идут вопросы о подключении мыши, использовании MTRR и LFB. Ну с мышью все понятно, просто выбираем интерфейс по которому она подсоеденина к компьютеру. MTRR — это регистры определяющие тип кеширования памяти для процессоров Intel Pentium Pro и выше (а также K6-2 и выше). Если у вас более поздний процессор, чем Pentium Pro или K6-2, то выберите единичку. LFB — этот тип выбора определяет по какому принципу (прямой/постраничный) будет происходить обмен с памятью вашей видеокарты (только для VESA 2.0). Некоторые карты требуют постраничного обращения к своей памяти.

Если вы загружаете Menuet в первый раз и вы не уверены, что настройки Menuet подходят вам, первым делом отключите их. После отключения некоторых настроек Menuet может работать медленнее, но при этом она будет полностью функциональной.

После того, как ваши выборы были переданы ОС, ядро загружается с дискеты и переходит в графический режим, выбранный пользователем. На этом этапе ОС загружает и устанавливает множество таблиц защищенных режимов и структуры, необходимые для выполнения ОС.

'Fonts loaded'

Загружает набор шрифтов по-умолчанию для использования в приложениях.

'Reprogramming IRQs'

Перепрограммирует PIC для IRQ.

'Setting TSSs'

Устанавливает по-умолчанию сегменты переключения задач и указатели.

'Setting IDTs'

Создает IDT таблицу для прерываний.

'Reading CPUIDs'

Читает CPUID информацию для процессоров семейства pentium.

'Detecting devices'

Для определения жестких дисков и разделов в будущем.

'Setting timer'

Перепрограммирование таймера на 100 Гц.

'Setting mouse'

Программирование портов ps/2 / com для мыши.

'Setting window defaults'

Создание двух оконных стэков по-умолчанию.

'Calculating background'

По-умолчанию черный фон.

'Reserving IRQs & ports'

Резервирование IRQ и портов для использования операционной системой.

'Setting addresses for IRQs'

Считывание портов для IRQ.

'Setting OS task'

Определение задачи ОС TSS.

'Unmasking all IRQs'

Демаскировка всех IRQ вместе с CLI

'Reading TSC'

Чтение TSC / сек.

'Setting EGA/CGA 320x200 palette'

Установка палитры для режима 320x200.

'Setting VGA 640x480 palette'

Установка палитры для режима 640x480.

'Setting MTRR'

Программирование MTRR для более быстрой графики.

'All set - press ESC to start'

2c) Многозадачность

Menuet использует карусельную, вытесняющую многозадачность и многопотоковость переключения задач с возможностью выборки данных жесткого реального времени.

Первой задачей списка процессов является задача ОС. Задача ОС отвечает за все общие системные функции, такие как мышь, перемещение окон и завершение работы процессов. Так как задача ОС является процессом, она не имеет преимуществ перед другими процессами. Так что если вы замечаете, что ваша мышь начала двигаться медленно — это результат высокой загрузки процессора.

Приложения загружаются в память начиная с 16 Mб (может изменяться). Системные вызовы реализованы в прерывании 0x40 и номере функции, сохраненном в eax и возможных других параметрах в других регистрах или таблице памяти. Так как Menuet имеет монолитное ядро, задача, выполняемая на стороне ОС не отличается от задачи, выполняемой на стороне приложения. Сегменты данных установлены в ноль, но стэковый сегмент остается таким же, как при использования системных функций. Таким образом приложение должно получить 1024 байт для использования стэка системных функций.

Структура выполнения процессов:


-------------------------           ---------------------------

I  Код ядра Menuet      I           I   Загруженные задачи    I

I  -------------------  I           I  ---------------------  I

I                       I           I                         I

I  Планировщик по       I           I  Задачи 2, 3 ..         I

I  номеру IRQ 0         I           I  Любой аппаратный       I

I  Выделение времени    I           I  доступ к ядру.         I

I  1/100 для задачи     I           I                         I

I  если время вышло -   I           I                         I

I  change_task          I           I                         I

I  Задача 1 : цикл ОС   I   ------- I  Системные функции с    I

I  мышь, оконный стэк   I   I       I  вызовом int 0x40       I

I                       I   I       I                         I

I                       I   I   --> I  возвращение к          I

I  INT 0x40             I <--   I   I  приложению             I

I  Системные функции    I       I   I                         I

I                       I -------   I                         I

-------------------------           ---------------------------

Планировщик на irq0 запрограммирован так, что запускается каждые 1/100 секунды. Единственное исключение — вызов функции change_task. Например, вызов из приложения delay или event_wait приводит к этому, и приложение не захватывает больше процессорного времени, чем ему нужно.

Первое запущенное приложение сохраняется в 'firstapp' файла kernel.asm.

2d) Информация о процессах

Menuet использует сегменты переключения задач для сохранения содержимого процессов. TSS сохраняются в памяти, начиная с 0x40000. Информация о работающих приложениях сохраняется также по адресам:


004 dword номер процесса

3000 dword счетчик процессов

2000 -> 2FFF информация об окне (фрагментами по 32 байта)



; Первое окно по смещению 0x20



+00 dword Начало по x (Левый край)

+04 dword Начало по y (Верхний край)

+08 dword Размер по x (Ширина)

+0C dword Размер по y (Высота)

+10 dword Цвет рабочей области окна

+14 dword Цвет заголовка окна

+18 dword Цвет рамки окна



3000 -> 3FFF список задач (фрагментами по 32 байта)



; Первая задача по смещению 0x20



+00 dword маска событий приложения

+04 dword номер процесса

+0a word 0=запущенный, состояние 3=зомби, 4=завершенный

+0e byte номер окна на экране

+0f byte позиция в памяти

+10 dword точная позиция в памяти

+14 dword встречная сумма

+18 dword временная отметка счетчика

+1c dword использование процессора



8000 -> 8FFFF различная информация (фрагментами по 256 байт)



; Первый фрагмент по смещению 0x100



00 имя приложения

Планировщики используют команду jmp для переключения задач, их структура:


JMP -> TSS           указатели в порядке запущенных приложений в GDT

       (0x40000+)    (gdts + app_data / app_code 2.->)



    -> 1         ------------>  селекторы данные / код

    -> 2         --+ |------->

    -> 3         --+ |  ----->

    -> 4         --+ |  ----->

    -> 5         --+ |  ----->

    -> 6         ----|  ----->

       .

       .

Системное ядро занимает память с 0x0 до 8Мб, далее идет линейный рамочный буфер экрана. Пространство между 12 и 16 Mб не используется, так как некоторые современные компьютеры используют эту область для передач между устройствами. Таким образом приложения загружаются в память, начиная с 16M. Тем не менее эти установки могут изменяться, смотрите файл kernel.asm, set_variables.

За более детальной информацией об использовании памяти смотрите файл MEMMAP.INC.

2e) Графический интерфейс пользователя

Основы работы GUI выглядят следующим образом: каждое приложение на экране имеет собственный идентификационный номер. Это позволяет располагать окна произвольным образом.

Ссылки на GUI начинаются по адресу 0x400000 и каждый пиксель кодируется одним байтом.

Допустим, у нас запущены ОС и два приложения: os=1, app1=2, app2=3.

В памяти это будет выглядеть так:


11111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111

11112222222222222222221111111111111111111111111

11112222222222222222221111111111111111111111111

11112222222222222222221111111111111111111111111

11112222222222333333333333333333333333311111111

11112222222222333333333333333333333333311111111

11112222222222333333333333333333333333311111111

11112222222222333333333333333333333333311111111

11112222222222333333333333333333333333311111111

11111111111111333333333333333333333333311111111

11111111111111333333333333333333333333311111111

11111111111111333333333333333333333333311111111

11111111111111333333333333333333333333311111111

11111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111

Почти всякий раз, когда приложение рисует что-нибудь на экране, оно сверяется с данным участком в памяти. Такая техника работает быстрее, чем может показаться. Узким местом текущей реализации GUI является система кэширования, которая еще не оптимизирована. Графический интерфейс расположен по адресу 0x1C00000 (28Mб) и отображается на видеобуфер графической карты.

2f) Добавление системных вызовов

Когда прерывание 0x40 получает номер функции в eax, i40 вызывает функцию, определенную в таблице ядра servetable.

Значения регистров смещаются следующим образом: EBX переходит в EAX, ECX в EBX, EDX в ECX, ESI в ECX, EDI в ESI.

Все параметры возвращаются приложению путем модификации стэка, например:


mov   [esp+36],eax    ; возврат eax для приложения

mov   [esp+24],ebx    ; ebx

mov   [esp+32],ecx    ; ecx

mov   [esp+28],edx    ; edx

ret                   ; возвращение в сохраненное приложение

Заметьте также, что выполнение команды ret следует сразу после того, как возвращенные данные сохраняются в стэке.

Для того, что бы вычислить физический адрес приложения, вызвавшего функцию, следует проделать следующее:


mov  esi,[0x3010]     ; Помещаем в eax адрес таблицы приложения

mov  edi,[esi+0x10]   ; Помещаем в edi физический адрес начала

                      ; приложения в памяти

Это бывает необходимо при передачи в приложение большого объема информации. Тогда просто нужно выделить для приложения свободное место под массив, и зная начало приложения в памяти, вычислить адрес массива и записать туда информацию.

Copyright © 2003 Перевод Андрей С. Кухар.

Наверх / Up mailto:Webmaster
Хостинг от uCoz