Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Ассемблер? Это просто! Учимся программировать


Информационный Канал Subscribe.Ru


Ассемблер под Windows №4

Приложение Windows, почему и зачем №2!


Доброго время суток, уважаемые подписчики. В этом выпуске я постараюсь подробно объяснить, что мы делали в процедуре окна.


Итак, в предидущем выпуске рассылки мы закончили обсуждать нашу программу на создании и выводе на дисплей нашего окна. Продолжим:
mov edi,offset msg_
Этой строкой мы заносим адрес переменной сообщений в edi, так как при обработке сообщений нам придётся несколько раз помещать этот адрес в стек, а "push edi" быстрее и компактнее команды "push offset msg_".
main_:
Начало нашего главного цикла обработки сообщений.
push ebx
push ebx
push ebx
push edi
call Getmessage

При вызове GetMessage эта процедура забирает из стека 4 параметра и использует их как первое сообщение, второе сообщение, объект, к которому принадлежат сообщения и адрес структуры сообщений. Мы используем её с параметрами 0,0,0,offset msg_, то есть принимаем все сообщения от всех объектов данной задачи в структуру msg_!
test eax,eax
jz exit_
Если пользователь закрывает приложение, то эта процедура возвращает 0, поэтому стоит устроить проверку на 0, и в случае равенства выхода.
push edi
call translatemessage
push edi
call dispatchmessage
Эти две процедуры расшифровывают сообщение, при входе надо поместить в стек адрес структуры сообщения.
jmp main_
Этой строкой мы зацикливаем процесс обработки сообщений, то есть сообщения будут непрерывно, или насколько позволит скорость процессора, повторятся. Наверняка у многих из Вас появился вопрос, а как работает процедура окна, когда о ней даже не упоминается. Спешу ответить на этот вопрос, в Windows каждая часть приложения выполняется как отдельная задача. Заглянем назад, при инициализации переменных и структур мы записали в структуру нашего окна адрес процедуры окна! В связи с этим при создании окна Windows создал отдельную задачу, в которую поместил нашу процедуру обработки окна. Наша программа и процедура окна выполняются параллельно, а так как обе ссылаются на одну и ту же структуру сообщений, то сообщения передаются через неё. При этом при завершении программы мы должны отдельно закрыть каждую часть нашего приложения.
exit_:
push ebx
call exitprocess
Вот и само завершения программы, но не процедура окна. Единственное, что хотел бы здесь отметить, что в отличии от DOS в Windows программа завершается не директивой ret, которая передаёт управление программе терминатору, а вызовом процедуры терминатора напрямую.
win_procproc
pushebp
movebp,esp
wp_hWndequdword ptr [ebp+08h]
wp_uMsgequdword ptr [ebp+0Ch]
wp_wParamequdword ptr [ebp+10h]
wp_lParamequdword ptr [ebp+14h]
cmpwp_uMsg,wm_destroy
jnenot_
push0
callpostquitmessage
jmpend_
not_:
leave
jmpDefWindowProc
end_:
leave
ret16
win_procendp
end_start

А это наша процедура окна! Рассмотрим подробно каждую её строку! push ebp mov ebp,esp Этими двумя командами мы создаём так называемый стековой кадр для нашей процедуры. На самом деле мы помещаем в стек значение ebp, а потом сохраняем размер стека в ebp, после этого мы спокойно можем использовать стек, с условием, что перед завершением процедуры мы загрузим размер стека обратно в esp! Следовательно, мы не должны изменять ebp в течении процедуры!
wp_hWndequdword ptr [ebp+08h]
wp_uMsgequdword ptr [ebp+0Ch]
wp_wParamequdword ptr [ebp+10h]
wp_lParamequdword ptr [ebp+14h]
Эти четыре строки в программе не участвуют, но существенно облегчают нашу работу!
cmp wp_uMsg,wm_destroy
jne not_
Так как в этом примере наше окно ничего не делает, то единственное действие, которое может произойти с ним это закрытие. Поэтому стоит поставить проверку на закрытие (сообщение windows wm_destroy). Если окно не было закрыто, то переходим на метку not_,
push 0
call postquitmessage
jmp end_
Если же оно было закрыто, то помещаем в стек 0 и сообщаем об этом Windows при помощи процедуры PostQuitMessage.
not_:
leave
jmp DefWindowProc
Если сообщение не получено, то управление передаётся на эту метку. Команда leave эквивалентна двум командам, mov esp,ebp и pop ebp, то есть она возвращает esp и ebp их изначальные значения! Так как полная обработка окна (вырисовка на экран и т.д.) выполняется Windows, то надо не завершить программу, а передать управление на процедуру окна, jmp DefWindowProc.
end_:
leave
ret 16
А при завершении процедуры нам нужно ещё убрать структуру сообщений из стека, а так как она занимает 4 двойных слова, что равно 16 байтам, это за нас сделает директива ret 16!


Вот вроде и всё! Если есть какие вопросы, пишите, обязательно отвечу. В следующем уроке мы повторим MessageBox и полатаем нашу программу! Пишите, Dark_Lord@land.ru, сюда, если первое мыло перегружено!


be number one Яндекс цитирования

© 2002 Россия, Москва. Авторское право: RusFAQ.ru

http://subscribe.ru/
E-mail: ask@subscribe.ru
Отписаться
Убрать рекламу

В избранное