Введение в программирование для Win32
🕛 30.10.2006, 16:00
Программирование на ассемблере всегда отличалось от программирования на языках высокого уровня и требовало от программиста дополнительных знаний, дополнительной практики и большего проффесионализма. Поэтому прежде чем начать создавать приложения для Win32 мы должны рассмотреть некоторые особенности системы Win32, которые были введены фирмой Microsoft.1. Передача параметрам функциям Windows API реализована по прямому алгоритму. То есть если на C Вы вызывали фнукциию так:
FARPROC GetProcAddress(HMODULE hModule, LPCSTR lpProcName)
то на ассемблере вызов подобной функции будет выглядеть так :
...
mov eax,offset lpProcName
mov ebx,hModule
push eax
push ebx
call GetProcAddress
...
В то время как в TASM :
.model FLAT,STDCALL
...
call GetProcAddress, [hModule], offset lpProcName
...
В инструкции компилятору ".model" мы передали в параметре, что будем использовать модель памяти FLAT и осуществлять стандартную передачу параметров типа STDCALL.
STDCALL использует соглашения языка C для процедур с переменными аргументами и соглашения языка Pascal для процедур с постоянными аргументами. Для всех остальных идентификаторов применяются соглашения языка C.
Так например некоторые функции Windows API используют способ перевернутой передачи параметров в стек. Так называемый (метод языка С или С-метод). К таким функциям относят функции который могут получать переменное число параметров. Примером такой функции может послужить функция wsprintf(LPTSTR lpOut, LPCTSTR lpFmt, ... ). Для вызова таких функций нужно воспользоваться модификатором вызова, что в TASM делается так :
call _wsprintfA C, offset lpOut, offset lpFmt, offset lpFirstParameter, offset lpSecondParameter
в то время как другие функции с постоянным числом параметров можно вызывать без всяких модификаторов ( если вы конечно воспользовались директивой ".model FLAT, STDCALL").
call GetProcAddressA, [hModule], offset lpProcName
2. Все функции API подразделены на две группы: функции которые поддерживают UNICODE, и функции которые поддерживают ANSI. Функции, поддерживающие UNICODE имеют в конце названия букву "W", а функции, поддерживающие ANSI имеют в конце названия букву "A". Таким образом :
GetProcAddressA - прототип функции GetProcAddress для ANSI.
GetProcAddressW - прототип функции GetProcAddress для UNICODE.
Различие UNICODE от ANSI заключается в том, что в ANSI для передачи одной буквы используется один байт, в зависимости от текущей кодовой страницы в различных кодировках, а в UNICODE использьзуется два байта (так называемый WIDE символ). Поэтому при использовании UNICODE все ссылки на строки включают в себя букву W. Так например :
LPCTSTR (ANSI) = LPCWSTR (UNICODE)
LPTSTR (ANSI) = LPWSTR (UNICODE)
3. Все функции Windows API теперь зависят от регистра букв. То есть если если функция API называется GetProcAddressA то и объявление то же должно быть GetProcAddressA. Например :
...
EXTRN GetProcAddressA: PROC
...
call GetProcAddressA,[hModule], offset lpProcName
...
4. Рассмотрим теперь оссобенности компиляции и компоновки программ. Для компиляции под Win32 Вам понадобяться следующие программы:
tasm32.exe - Borland Turbo Assembler
tlink32.exe - Borland Turbo Link
brcc32.exe - Borland Resource Compiler
Для запуска этих программ понадобяться еще несколько библиотек.
Итак для того, что бы откомпилировать нашу программу используя TASM надо передать компилятору такие параметры:
tasm32.exe /ml <имя файла>
Опция /ml в данном случае говорит о том, что в тексте программы во всех именах следует различать регистр букв, то есть CreateWindow будет отличаться от CREATEWINDOW.
Теперь скомпонуем нашу программу :
tlink32.exe -c -aa -Tpe <имя файла>
Опция -с аналогична опции /ml, она говорит компоновщику о том, что в файле должны различаться регистры букв у имен переменных и функций.
Опция -aa указывает компилятору что нужно создать обычное приложение Windows использующее GDI. Если вы укажите опцию -ap то компоновщик сгенерирует консольное приложение Windows (примером консольного приложения может послужить FAR). Написание консольных приложений я рассмотрю в одной из своих следующих статей.
Последней опцией -Tpe мы сообщаем компоновщику, что нужно сгенерировать EXE файл. Если мы укажем опцию -Tpd то на выходе компоновщика получим DLL файл.
Компиляция ресурсов в Win32 происходит по тому-же алгоритму, что и в Win16. Например для компиляции ресурсов, находящихся в файле myres.rc нужно запустить brcc32.exe с следующимим параметрами.
brcc32.exe myres.rc
Ну вот и все об основных различиях программирования для Win32.