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: |