Go to most recent revision | Details | 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 | ; Подключаем необходимые макросы |
||
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 |