Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;*********************************
  2. ;*                               *
  3. ;*    PAINT 0.02 для MenuetOS    *
  4. ;*                               *
  5. ;*     Компилировать FASM'ом     *
  6. ;*                               *
  7. ;*********************************
  8.  
  9. ;******************************************************************************
  10. ; Эту программу не нужно серьезно рассматривать - это всего лишь пример,
  11. ; в котором показано, как работать с некоторыми системными функциями МеОС,
  12. ; но никак не нормальный графический редактор. Код программы ОЧЕНЬ простой,
  13. ; и она предназначена для тех, кто только начинает изучать ассемблер,
  14. ; поэтому я стремился сделать его как можно более понятным.
  15. ; Тем не менее, код довольно неплохо оптимизирован, хотя это немного
  16. ; может затруднить его понимание. Я постарался тщательно прокомментировать
  17. ; сложные места. Кстати, идея программы принадлежит не мне, а Sniper'у, для
  18. ; которого вобщем-то все и писалось.
  19. ;   Удачи в изучении асма!
  20. ;   Иван Поддубный, ivan-yar@bk.ru
  21. ;******************************************************************************
  22.  
  23. ; Подключаем необходимые макросы
  24. include 'macros.inc'
  25.  
  26. ;******************************************************************************
  27.  
  28. ; НАЧАЛО ПРОГРАММЫ
  29. meos_app_start
  30. ; ОБЛАСТЬ КОДА
  31. code
  32.     mov  eax,40       ; сообщим системе, какие события будем обрабатывать
  33.     mov  ebx,0100101b ; маска событий - перерисовка (1) + кнопка (3) + мышь (6
  34.     int  0x40         ; эта команда вызывает системную функцию
  35.  
  36.     mov  [workarea.cx],10  ; координаты рабочей (клиентской) области
  37.     mov  [workarea.cy],45  ; для рисования
  38.  
  39. red:
  40.     call draw_window   ; вызываем процедуру отрисовки окна
  41.  
  42. still:            ; ГЛАВНЫЙ ЦИКЛ ПРОГРАММЫ - ЦИКЛ ОБРАБОТКИ СООБЩЕНИЙ
  43.  
  44.     mov  eax,10   ; функция 10 - ждать события; программа останавливается на
  45.     int  0x40     ; следующая команда не будет выполнена до тех пор, пока
  46.                   ; не произойдёт событие
  47.  
  48.     ; теперь регистр eax содержит номер события
  49.     ; поочередно сравним его со всеми возможными значениями, чтобы вызвать
  50.     ; нужный обработчик
  51.  
  52.     cmp  eax,1    ; перерисовать окно ?
  53.     je   red      ; если регистр eax равен единице, то переходим на метку red
  54.     cmp  eax,3    ; нажата кнопка ?
  55.     je   button
  56.     cmp  eax,6    ; мышь?
  57.     je   mouse
  58.  
  59.     jmp  still    ; если произошло событие, которое мы не обрабатываем,
  60.                   ; просто возвращаемся к началу цикла, хотя такого быть
  61.                   ; не должно! Т.е. если эту команду отсюда убрать, то
  62.                   ; ничего страшного не случится.
  63.  
  64. ;******************************************************************************
  65.  
  66.   button:        ; обработчик нажатия кнопки в окне программы
  67.     mov  eax,17  ; функция N17 - получить идентификатор нажатой кнопки
  68.     int  0x40
  69.  
  70.     ; теперь в регистре ah содержится идентификатор.
  71.  
  72.     shr  eax,8   ; ah -> al (сдвиг на 8 бит вправо)
  73.  
  74.     dec  al       ; идентификатор_кнопки--;
  75.     jnz  .noclose ; если результат предыдущей команды равен нулю, закрываемся
  76.                   ; иначе - идём на метку noclose
  77.  
  78.     or   eax,-1  ; выход из программы
  79.     int  0x40
  80.  
  81.   .noclose:
  82.     ; если мы сюда попали, значит идентификатор кнопки не был равен нулю...
  83.     ; теперь у нас в eax содержится (номер цветной кнопки - 1),
  84.     ; т.е или 1, или 2, ... ,или 5
  85.  
  86.     ; уменьшим на 1:
  87.     dec  eax
  88.  
  89.     ; вот эта вот команда извлекает в eax двойное слово по адресу colors+eax*4
  90.     ; где colors - смещение метки colors, после которой идет последовательность
  91.     ; цветов, eax*4 - номер цвета, умноженный на 4, т.к. на один цвет нужно
  92.     ; четыре байта.
  93.     mov  eax,[colors+eax*4]
  94.  
  95.     ; теперь мы установим цвет, содержащийся в регистре eax как основной:
  96.     mov  [active_color],eax
  97.  
  98.     ; ну вот, собственно, и всё, что от нас требовалось ;)
  99.     ; вернёмся к началу цикла обработки событий
  100.     jmp  still
  101.  
  102. ;******************************************************************************
  103.  
  104.   mouse:          ; обработчик мыши
  105.     mov  eax,37             ; сначала получим текущие координаты мыши
  106.     mov  ebx,1
  107.     int  0x40
  108.  
  109.     mov  ebx,eax            ; преобразуем их
  110.     shr  eax,16             ;   eax=x;
  111.     and  ebx,0xffff         ;   ebx=y;
  112.  
  113.     cmp  ebx,22
  114.     jb   save_canvas
  115.  
  116.     sub  eax,[workarea.cx]  ; x-=[workarea.cx]
  117.     cmp  eax,0              ; если мышь левее клиентской области,
  118.     jle  .not_pressed       ;   ничего не рисуем
  119.     cmp  eax,[workarea.sx]  ; если мышь правее...
  120.     jae  .not_pressed
  121.  
  122.     sub  ebx,[workarea.cy]
  123.     cmp  ebx,0              ; ...выше...
  124.     jle  .not_pressed
  125.     cmp  ebx,[workarea.sy]  ; ...ниже...
  126.     jae  .not_pressed
  127.  
  128.     ; какие кнопки нажаты?
  129.     mov  eax,37
  130.     mov  ebx,2
  131.     int  0x40
  132.  
  133.     ; если левая кнопка (т.е. eax = 1), те пойдём дальше
  134.     cmp  eax,1
  135.     je   .leftbtn
  136.  
  137.   .not_pressed:
  138.     ; Левая кнопка не нажата, запомним текущие координаты и будем ждать события
  139.     mov  [mouse_pressed],0   ; мышь не нажата
  140.     mov  eax,37              ; получим координаты
  141.     mov  ebx,1
  142.     int  0x40
  143.     mov  ebx,eax
  144.     shr  eax,16
  145.     and  ebx,0xffff
  146.     mov  [old_x],eax         ; запомним их
  147.     mov  [old_y],ebx
  148.     jmp  still
  149.  
  150.   .leftbtn:
  151.     ; Левая кнопка нажата, надо это записать!
  152.     mov  [mouse_pressed],1
  153.  
  154.     ; Получим координаты курсора мыши (относительно окна)
  155.     mov  eax,37              ; функция 37 - получить состояние мыши
  156.     mov  ebx,1               ; подфункция 1
  157.     int  0x40
  158.  
  159.     ; Переделаем их так, чтобы они были в разных регистрах, т.е. eax и ebx
  160.     mov  ebx,eax
  161.     shr  eax,16
  162.     and  ebx,0xffff
  163.  
  164.     ; Подготовим параметры для функции рисования линии
  165.     mov  ecx,[old_x]     ; для начала загрузим старые координаты
  166.     mov  edx,[old_y]
  167.     mov  [old_x],eax     ; теперь сохраним текущие в старые
  168.     mov  [old_y],ebx
  169.     shl  ecx,16          ; в верхнее слово начальные (текущие) координаты
  170.     shl  edx,16
  171.     add  eax,ecx         ; а в нижнее слово конечные, т.е. старые
  172.     add  ebx,edx
  173.  
  174.     mov  ecx,ebx             ; поменяем регистры так, как эту нужно 38 функции
  175.     mov  ebx,eax
  176.     mov  eax,38              ; номер функции в eax
  177.     mov  edx,[active_color]  ; в edx цвет
  178.     int  0x40
  179.  
  180. ;             - попробуйте поставить другие значения (00090001)
  181.     mov  edi,0x00010001      ; чтобы линия не была слишком тонкой,
  182.     add  ebx,edi             ; нарисуем рядом еще 3!
  183.     int  0x40
  184.     add  ecx,edi
  185.     int  0x40
  186.     sub  ebx,edi
  187.     int  0x40
  188.  
  189.     sub  ebx,edi             ; ну а чтобы смотрелось совсем круто,
  190.     int  0x40                ; дорисуем еще 5!
  191.     sub  ecx,edi
  192.     int  0x40
  193.     sub  ecx,edi
  194.     int  0x40
  195.     add  ebx,edi
  196.     int  0x40
  197.     add  ebx,edi
  198.     int  0x40
  199.  
  200.   jmp still
  201.  
  202. ;******************************************************************************
  203.  
  204. save_canvas:
  205.     mov  eax,[process.x_size]
  206.     add  eax,[workarea.cx]
  207.     mov  ebx,[process.y_size]
  208.     add  ebx,[workarea.cy]
  209.  
  210.     jmp still
  211.  
  212. ;******************************************************************************
  213.  
  214. ;   *********************************************
  215. ;   *******  ОПРЕДЕЛЕНИЕ И ОТРИСОВКА ОКНА *******
  216. ;   *********************************************
  217.  
  218. draw_window:
  219.  
  220.     mov  eax,48                    ; ПОДГРУЖАЕМ СИСТЕМНЫЕ ЦВЕТА
  221.     mov  ebx,3
  222.     mov  ecx,sc
  223.     mov  edx,sizeof.system_colors
  224.     int  0x40
  225.  
  226.     mov  eax,12      ; функция 12: сообщить ОС об отрисовке окна
  227.     mov  ebx,1       ; 1, начинаем рисовать
  228.     int  0x40
  229.  
  230.                                    ; СОЗДАЁМ ОКНО
  231.     mov  eax,0                     ; функция 0 : определить и отрисовать окно
  232.     mov  ebx,100*65536+400         ; [x старт] *65536 + [x размер]
  233.     mov  ecx,100*65536+300         ; [y старт] *65536 + [y размер]
  234.     mov  edx,[sc.work]             ; цвет рабочей области  RRGGBB,8->color gl
  235.     or   edx,0x02000000
  236.     mov  esi,[sc.grab]             ; цвет полосы заголовка RRGGBB,8->color gl
  237.     or   esi,0x80000000
  238.     mov  edi,[sc.frame]            ; цвет рамки            RRGGBB
  239.     int  0x40
  240.  
  241.     mov  eax,9                     ; получим информацию о себе
  242.     mov  ebx,process
  243.     mov  ecx,-1
  244.     int  0x40
  245.  
  246.     mov  eax,[process.x_size]      ; настроим размер рабочей области
  247.     add  eax,-20                   ;   (х размер окна - 20)
  248.     mov  [workarea.sx],eax         ;
  249.     mov  eax,[process.y_size]      ;
  250.     add  eax,-60                   ;   (у размер - 60)
  251.     mov  [workarea.sy],eax         ;
  252.  
  253.                                    ; ЗАГОЛОВОК ОКНА
  254.     mov  eax,4                     ; функция 4 : написать в окне текст
  255.     mov  ebx,8*65536+8             ; [x] *65536 + [y]
  256.     mov  ecx,[sc.grab_text]        ; цвет
  257.     or   ecx,0x10000000            ; шрифт
  258.     mov  edx,header                ; адрес строки
  259.     mov  esi,header_len            ; и её длина
  260.     int  0x40
  261.  
  262.                                    ; КНОПКА ЗАКРЫТИЯ ОКНА
  263.     mov  eax,8                     ; функция 8 : определить и нарисовать кнопку
  264. ;   mov  ebx,(300-19)*65536+12     ; [x старт] *65536 + [x размер]
  265.     mov  ebx,[process.x_size]
  266.     add  ebx,-19
  267.     shl  ebx,16
  268.     add  ebx,12
  269.     mov  ecx,5*65536+12            ; [y старт] *65536 + [y размер]
  270.     mov  edx,1                     ; идентификатор кнопки
  271.     mov  esi,[sc.grab_button]      ; цвет кнопки RRGGBB
  272.     int  0x40
  273.  
  274.     cmp  [process.y_size],80
  275.     jb   .finish
  276.  
  277.     ; создаём кнопки выбора цвета:
  278.     mov  ebx,10*65536+10           ; начальная x координата и размер
  279.     mov  ecx,27*65536+10           ; начальная y координата & size
  280.  .new_button:
  281.     inc  edx                       ; идентификатор++;
  282.     mov  esi,[btn_colors-8+edx*4]  ; цвет кнопки
  283.     int  0x40                      ; ставим кнопку
  284.     add  ebx,12*65536              ; следующая кнопка правее на 12
  285.     cmp  edx,9                     ; сравниваем edx (идентификатор) с 9
  286.     jbe  .new_button               ; если меньше или равно -> ещё одну кпоку
  287.  
  288.     mov  eax,13                    ; чистим "холст" - клиентскую область
  289.     mov  ebx,[workarea.cx]
  290.     mov  ecx,[workarea.cy]
  291.     shl  ebx,16
  292.     shl  ecx,16
  293.     add  ebx,[workarea.sx]
  294.     add  ecx,[workarea.sy]
  295.     mov  edx,0xffffff
  296.     int  0x40
  297.  
  298.  .finish:
  299.     mov  eax,12      ; сообщаем системе о завершении отрисовки окна
  300.     mov  ebx,2
  301.     int  0x40
  302.  
  303.     ret
  304.  
  305. ;******************************************************************************
  306. ; начало области инициализированных данных
  307. ; если кто ещё не знает, что значит "инициализированные", то поясняю:
  308. ; это те данные, которым присвоено начальное значение
  309. data
  310.  
  311. header:                  ; строка заголовка
  312.    db  'PAINT v0.2 for MenuetOS'
  313. header_len = $ - header  ; и её длина
  314.  
  315.    mouse_pressed   db  0 ; показывает, нажата ли была мышь в предыдущий момент
  316.  
  317. ; цвета кнопок
  318. btn_colors:
  319.    dd 0xdddddd ; white
  320.    dd 0x444444 ; black
  321.    dd 0x00dd00 ; green
  322.    dd 0x0000dd ; blue
  323.    dd 0xdd0000 ; red
  324.    dd 0xdd00dd ; magenta
  325.    dd 0xdddd00 ; yellow
  326.    dd 0x00dddd ; cyan
  327.    dd 0x559955 ; warm green
  328.  
  329. ; цвета кисти (в том же порядке, что и цвета кнопок)
  330. colors:
  331.    dd 0xffffff ; белый
  332.    dd 0x000000 ; черный
  333.    dd 0x00ff00 ; зеленый
  334.    dd 0x0000ff ; синий
  335.    dd 0xff0000 ; красный
  336.    dd 0xff00ff ; пурпурный
  337.    dd 0xffff00 ; желтый
  338.    dd 0x00ffff ; голубой
  339.    dd 0x77bb77 ; теплый зеленый
  340.  
  341. ;******************************************************************************
  342. ; а вот тут начинается область НЕинициализированных данных, т.е.
  343. ; здесь данным значения не присвоены. В отличие от иниц., не увеличивают размер
  344. ; файла
  345.  
  346. udata
  347.  
  348.    active_color    dd  ?           ; активный цвет
  349.  
  350.    old_x           dd  ?           ; старые координаты мыши
  351.    old_y           dd  ?
  352.  
  353.    workarea:                       ; координаты и размеры клиентской области
  354.        .cx     dd  ?               ;   c - коодинаты
  355.        .cy     dd  ?
  356.        .sx     dd  ?               ;   s - размеры
  357.        .sy     dd  ?
  358.  
  359.    sc          system_colors       ; системные цвета
  360.    process     process_information ; информация о процессе
  361.  
  362.    restflag    dd  ?
  363.    canvas      rb  800*600*3
  364.  
  365. meos_app_end
  366.