Win32 в машинных кодах


Главная функция окна


Сегодня мы впервые будем создавать собственную функцию, поэтому освежим в памяти особенности функций.

Функция - это некий код, который находится где-то по другому адресу от того места, из которого вызывается. Поэтому адрес возврата сохраняется в стеке. Кроме того, мы уже работали с передаваемыми функции данными - ее параметрами - и знаем, что они тоже помещаются в стек. А значит, при возвращении из функции мы должны компенсировать изменения в стеке, иначе он будет несбалансированным.

Процедура окна - это функция, которая вызывается самой системой; поэтому она должна удовлетворять соглашениям вызова функций API. Т.е. мы можем внутри функции свободно работать с регистрами EAX, ECX, EDX и изменять их значения; но если потребуется работа с регистрами EBX, ESI или EDI, нужно сначала сохранить их содержимое в стеке, а перед возвращением из функции - восстановить старые значения. Кроме того, в EAX должен быть помещен результат работы функции, если она возвращает какое-то значение.

Теперь разберем все эти детали подробнее. Нужно каким-то образом получить доступ к параметрам, помещенным в стек. Мы уже знаем, что указатель стека находится в ESP, и можно было бы воспользоваться косвенной адресацией через этот регистр. Кстати, современные оптимизирующие компиляторы используют именно этот способ. Но если функция сама будет активно использовать стек, например, сохранять и восстанавливать регистры EBX, ESI или EDI, смещение параметров относительно ESP будет все время меняться и работать с ним будет неудобно - особенно при "ручном" кодировании. Поэтому для работы с параметрами (и локальными переменными, с которыми мы познакомимся позже) создается т.н. фрейм стека: значение ESP в самом начале функции копируется в регистр EBP, который и используется в дальнейшем в качестве базового указателя при обращении к параметрам (и локальным переменным). Предварительно в стек заносится старое значение EBP, которое восстанавливается перед завершением функции.

Главная функция окна строится по единому шаблону. Эта функция получает в качестве параметров значения 4 из 7 полей, содержащихся в структуре MSG. Параметры помещаются в стек в следующем порядке:




Начало  Назад  Вперед