Subversion Repositories Kolibri OS

Rev

Rev 3497 | Details | Compare with Previous | Last modification | View Log | RSS feed

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