Операционная система MenuetOS - Пример приложения под MenuetOS на примере файла EXAMPLE.ASM (original) (raw)

Статья немного устарела и скоро будет заменена, хотя все нижеизложенное работает. [Webmaster]

На дискете с Menuet'ом находится файл EXAMPLE.ASM. Это обычный пример - простое приложение в духе Hello World, для ознакомления с реальным, работающим кодом. Единственное, что оно делает - выводит в окно текстовое сообщение. Единственная кнопка - закрывает окно и заканчивает программу.
Этот пример можно использовать, как шаблон для написания собственных программ. Ниже код программы приведен целиком с комментариями на русском (комментарии располагаются в коде после символа точки с запятой - ';').

; EXAMPLE APPLICATION

; (пример приложения)

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

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

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

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

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

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

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

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

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

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

START: ; Начинаем исполнение программы здесь

call draw_window    ;Для начала нарисуем окно.

      ;Инструкция call - вызывает подпрограмму, расположенную

      ;после метки draw_window

      ;Сама метка, когда она появляется в коде,

      ;заканчивается двоеточием (см. выше метку START, например)

still: ;Здесь начало кода для обработки событий

mov  eax,10 ;10 - номер системной фунции "ждать события"

            ;Записываем этот аргумент в регистр eax

int  0x40   ;А теперь вызываем саму эту функцию. 

     ;Поскольку она системная, то и выполняется системой. 

     ;Она вызывается с помощью прерывания (инструкция int)

     ;С помощью этого прерывания (0x40) выполняются все системные

     ;функции (их список есть в файле SYSFUNCS.TXT

     ;Когда произойдет событие (нажатие клавиши,

     ;запрос на перерисовку и т.п.)  

     ;код продолжит исполняться с этого самого места, а в регистр eax

     ;будет записано значение, указывающее на тип произошедшего события.
                                

;Начинаем определять, какое произошло событие:


cmp  eax,1   ;Запрос ли на перерисовку?

je   red     ;Если так, то переходим к метке red

cmp  eax,2   ;Или нажата клавиша?

je   key     ;Тогда  идем к метке key

cmp  eax,3   ;или же нажата кнопка (нарисованная в окне приложения)?

je   button  ;Тогда - к метке button


jmp  still   ;Других вариантов нет - возварщаемся к still,

             ;чтобы ожидать новых событий
            

red: ;Перерисовка окна...

call draw_window ;просто вызываем функцию перерисовки окна...

jmp  still       ;и возвращаемся ждать событий 

key: ;Нажата клавиша

mov  eax,2    ;Cистемная функция номер 2 - прочитать код нажатой клавиши... 

int  0x40     ;Вызываем эту фунцию, а  ее ответ игнорируем.

jmp  still    ;И возвращаемся ждать событий

button: ;Нажата кнопка в окне программы.

mov  eax,17     ;Функция номер 17 - спрашиваем систему, 

                ;какая именно кнопка нажата;

int  0x40       ;она вернет идентефикатор кнопки в регистре ah


cmp  ah,1       ;Сравним содержимое ah со значением "1" 

jne  noclose    ;Если НЕ нажата кнопка с id равным 1,

                ;то идем к метке nonclose

mov  eax,-1     ;иначе - завершаем программу вызовом функции "-1"...

int  0x40       ;вот этот вызов

noclose: ;Кнопка "выход" не нажата:

jmp  still  ;просто возвращаемся ждать события

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

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

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

draw_window: ;Здесь мы начинаем подпрограмму рисования окна

mov  eax,12  ;Функция 12: сообщить ОС об отрисовке окна

mov  ebx,1   ;Параметр функции  (1) в регистре ebx - начинаем рисовать

int  0x40    ;Вызов функции


                               ;НАЧИНАЕМ СОБСТВЕННО РИСОВАНИЕ

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

mov  ebx,100*65536+300  ;Координата начала окна по оси x *65536

                        ;+ ширина окна,

       ; то есть окно шириной 300 (пикселей) начинается на сотом

mov  ecx,100*65536+120  ;Аналогично - начало по y (*65536) + высота окна 

mov  edx,0x001111cc     ;Цвет рабочей области окна 

mov  esi,0x8099bbff     ;Цвет полосы заголовка  RRGGBB,8->color glide (?)

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

      ;RRGGBB означает, что два байта RR кодируют красный (Red) цвет

      ;и еще по два байта на зеленый (Green) и синий (Blue)

int  0x40               ;Параметры функии подготовили и вызываем ее.


                               ;ЗАГОЛОВОК ОКНА

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

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

mov  ecx,0x00ffffff ;Цвет текста  RRGGBB (про RGB - см.выше)

mov  edx,labelt     ;Пишем в регистр edx указатель на начало текста,

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

int  0x40           ;вызываем систему (т.е. системную функцию)


                               ; КНОПКА ДЛЯ ВЫХОДА

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

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

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

mov  edx,1                 ;Идентефикатор (id) данной кнопки

mov  esi,0x5599cc          ;Цвет кнопки RRGGBB

int  0x40     ;Вызываем функцию 8, параметры которой уже в регистрах...

; Выводим сообщение с помощью функции 4

mov  ebx,25*65536+35    ;координаты точки, начиная с которой выводить текст

                        ;25 по оси x и 35 по оси y

mov  ecx,0xffffff       ;Цвет текста

mov  edx,text           ;Указатель на текст (сам текст см. ниже)

mov  esi,40             ;длина текста - 40 байт

newline: ;...см.ниже

mov  eax,4         ;Функция 4 - вывод текста в окно

int  0x40          ;Вызываем функцию = пишем одну строку

add  ebx,10        ;Добавляем к ebx,10, чтобы в следующую строку

                   ;рисовать на 10 пикселей ниже

add  edx,40        ;Добавляем к edx 40, чтобы брать символы 

                   ;очередной строки

                   ;начиная с адреса, который уже в edx (указатель text), 

                   ;но еще на 40 символов (байт) дальше.

                   ;Таким образом мы выводим

                   ;ровно строки по 40 символов.

cmp  [edx],byte 'x'   ;Обращаемся по получившемуся адресу (регистр edx)...

                      ; и смотрим, что там за байт.

jne  newline ; Если это НЕ байт со значенем 'x', то продолжаем

    ;цикл вывода строк,

    ;то есть мы узнали, что это не последняя строка, и переходим к 

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

    ;в регистрах edx, ebx и т.д.

    ;То есть подразумеваем договоренность о том, что встретившийся

    ;в начале строки символ 'x' скажет нам закончить печать


mov  eax,12      ;Функция 12 :сообщить ОС об отрисовке окна

mov  ebx,2       ;Параметр этой функции равный 2... заканчили рисование

int  0x40        ;вызываем 12-ую функцию


ret           ;от англ. return - возвращаться. То есть мы возвращаемся 

              ;из подпрограммы рисования окна, которая была вызвана

              ;инструкцией call

; ЗДЕСЬ НАЧИНАЕТСЯ РАЗДЕЛ ДАННЫХ

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 <- НЕ УДАЛЯТЬ! МАРКЕР КОНЦА           ' 

; инструкциями db мы добавили в код

;последовательности данных (d), конкретнее байт (b)