Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
flor_apparato-orientirovnnoe_prog.doc
Скачиваний:
89
Добавлен:
15.06.2014
Размер:
926.72 Кб
Скачать

5.4. Программный доступ к системным функциям Win32

Доступ к системным функциям операционной системы MS Windows организован через специализированные библиотеки этой системы, которые содержат подпрограммы, вызываемые с помощью машинных команд CALL. Для конкретного доступа библиотеки предоставляют специализированные имена этих функций. Такие имена с подробным описанием аргументов, включая их типы, задаются документацией на API MS Windows с учетом особенностей системы программирования. Следует иметь в виду, что стандартные для документации имена API предоставляются для языка Си, а на уровне фактических имен для ассемблера может иметь место определенное отличие от этих имен, что будет рассмотрено дальше.

Обращение к API функциям в MS Windows осуществляется по соглашению Си для укладки аргументов в стек и по соглашению Паскаля для освобождения стека от этих аргументов. Такое комбинированное соглашение для обращения к подпрограмм в ассемблерах TASM и MASM обозначается также условным именем STDCALL. Все аргументы системной функции должны быть обязательно заданы (иначе нельзя было бы использовать соглашение Паскаля по освобождению области аргументов). Еще раз обратим внимание, что укладка аргументов по соглашению STDCALL выполняется в порядке "от конца к началу" в прототипе функции, а после возврата из системной функции никаких корректирующих действий в вызывающей программе предпринимать не нужно.

Для получения исполняемых программ, предназначенных выполняться под управлением ОС Windows, проще всего воспользоваться форматом выходного файла ассемблера NASM, задаваемого обозначением OBJ. Этот формат отвечает соглашениям, принятым для первых, тогда еще 16-битных версий продуктов Microsoft, и приспособленным в дальнейшем для 32-битных программных продуктов. Тот же самый формат объектных файлов используют системы разработки фирмы Borland/Inprise. Ориентация объектных модулей этого формата как на 16-битную архитектуру для исполняемых файлов, так и на 32-битную приводит к необходимости некоторых дополнительных указаний в самом тексте исходной программы.

В частности, приходится уточнять назначение сегментов, явно указывая их предназначение для 32-битной архитектуры современных версий Windows и задавая детали, существенные для конкретных соглашений компоновщика, выполняющего построение исполняемого файла для операционной системы MS Windows.

При использовании свободно распространяемого компоновщика ALINK.EXE (Copyright 1998/9 Anthony A.J. Williams.) [23], входящего в комплект системы NASMW, ограничений оказывается меньше и необходимо обязательно указывать только 32-битную разрядность сегментов. Для этих целей сегменты кода и данных можно определить с помощью директив

SEGMENT .text USE32

и

SEGMENT .data USE32

соответственно.

При использовании компоновщика TLINK32.EXE, входящего в состав систем программирования Borland/Inprise, ограничений оказывается больше. Во-первых, необходимо дополнительно указывать параметр CLASS=CODE при описании сегмента кодов. Во-вторых, при размещении сегментов данных перед сегментом кодов в исходной программе необходимо использовать дополнительную директиву GROUP, вводя с ее помощью общее описание группы сегментов со стандартным именем DGROUP. Таким образом, для компоновки объектных файлов, формируемых NASM для его формата obj, следует использовать в качестве описания сегмента данных пару директив

GROUP DGROUP DATA

SEGMENT DATA USE32

а для описания сегмента кодов директиву

SEGMENT .text USE32 CLASS=CODE

При использовании, кроме единственного инициализируемого сегмента данных, еще и других сегментов данных, в частности сегмента неинициализированных данных с именем BSS, все имена сегментов данных должны быть перечислены через запятые в директиве GROUP.

В частности, для двух сегментов данных DATA и BSS получается директива

GROUP DGROUP DATA, BSS

Таким образом, структура исходного текста программы NASM для последующего использования компоновщика TLINK32.EXE будет иметь вид

GROUP DGROUP DATA, BSS

SEGMENT DATA USE32

содержимое сегмента данных

SEGMENT BSS USE32

содержимое сегмента неинициализируемых данных

SEGMENT .text USE32 CLASS=CODE

содержимое сегмента кодов

Заметим, что вместо имени .text при обозначении сегмента кодов для указанного типа объектных файлов чаще всего применяют имя CODE.

Еще раз подчеркнем, что более простое построение программы получается, если сегмент кодов размещать раньше сегментов данных. В этом случае даже для TLINK32.EXE структура исходного текста программы будет отличаться от ранее рассмотренных вариантов только дополнительным параметром USE32 в директивах сегментов и еще параметром CLASS=CODE в описании сегмента кодов. Все перечисленные чисто технические сложности использования компоновщика TLINK32.EXE для наших целей обусловлены тем, что его построение (неявно для пользователей) базируется на традиционном в 16-битных программных архитектурах использовании директивы GROUP. Последнее было целесообразно в указанных старых архитектурах, где такой подход давал возможность эффективней использовать очень ограниченные для программиста возможности. Для сравнения компоновщик ALINK.EXE, созданный уже в новых условиях, неявно не ориентирован на такие ограничения и обеспечивает больше возможностей, поэтому (по крайней мере в данном курсе) рекомендуется использовать именно его.

В качестве стандартной метки начала запуска программы для формата OBJ следует использовать имя ..start. Причем то, что это имя оказывается глобальным, принимает по умолчанию сам ассемблер.

Существенными в Windows являются отличия программ, использующих стандартный ввод-вывод, от рассмотренных ранее для других операционных систем. Они заключаются в том, что хэндлы стандартных файлов не предоставляются операционной системой автоматически и с фиксированными значениями. Для получения хэндлов стандартного ввода и вывода необходимо выполнить вызов специальной функции с именем GetStdHandle. Единственный аргумент этой функции указывает хэндл для какого стандартного файла - для стандартного ввода, стандартного вывода или стандартного вывода ошибок требуется получить. В качестве этих констант в системах разработки на языке Си используются символические константы, определенные в заголовочном файле WINCON.H. Они имеют в этом файле обозначения STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, STD_ERROR_HANDLE, а отвечают им в действительности числовые значения -10, -11 и -12, соответственно.

Универсальные функции для ввода и вывода с помощью хэндлов файлов имеют в этой ОС прототипы

BOOL ReadFile(HANDLE hFile, void *buf, dword size,

dword *actlen, OVERLAPPED *Overlapped);

BOOL Write(HANDLE hFile, void *buf, dword size,

dword *actlen, OVERLAPPED *Overlapped);

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

В качестве системной функции завершения программы Windows содержит функцию с прототипом

VOID ExitProcess(UINT uExitCode)

где аргумент также является двойным словом.

Все системные функции обязательно должны быть перечислены в директивах EXTERN, так они соответствуют именам, определенным вне программы их использования.

В листинге 5.4.1 приведен исходный текст простейшей программы для Windows, которая выводит текст, описанный в именованной области данных txt и - сразу за ним - один символ из области symbl.

EXTERN GetStdHandle, WriteFile, ExitProcess

SEGMENT .text USE32 CLASS=CODE

..start: push dword STD_OUTPUT_HANDLE

call GetStdHandle

mov [hstdout],eax

;--- WriteFile(hstdout, txt, 7, &actlen, NULL)

push dword 0

push dword actlen

push dword 7 ; number of bytes

push dword txt ; address of txt

push dword [hstdout] ; N handle=hstdout

call WriteFile

;--- WriteFile(hstdout, symbl, 1, &actlen, NULL)

push dword 0

push dword actlen

push dword 1 ; number of bytes

push dword symbl ; address of txt

push dword [hstdout] ; N handle=hstdout

call WriteFile

; ExitProcess(0)

push dword 0

call ExitProcess

SEGMENT .data USE32

txt db 'Privet!'

symbl db '$'

hstdout dd 0

actlen dd 0

STD_OUTPUT_HANDLE equ -11

Листинг 5.4.1. Простейшая программа wprim.asm вывода текста в ОС Windows

Для превращения этой исходной программы на языке ассемблера в исполняемую программу можно воспользоваться следующими двумя строками командных вызовов:

nasmw -f obj wprim.asm -l wprim.lst

alink -oPE -subsys console wprim C:\util\win32.lib

При разработки многих программ для Windows на ассемблере целесообразно использовать командный файл, текст которого приведен в листинге 5.4.2.

nasmw -f obj %1.asm -l %1.lst

alink -oPE -subsys console %1 C:\util\win32.lib

Листинг 5.4.2. Командный файл для построения исполняемых файлов из NASM-ассемблерных

Его применение заключается в вызове по имени этого командного файла, за которым через пробел следует собственная часть имени файла на ассемблере. В частности, при наименовании этого командного файла как asmal.cmd такой вызов для предыдущего примера будут задаваться строкой

asmal wprim

(Заметим, что в ОС типа Windows 9x, в отличие от Windows NT - Windows 2000 и т.п., расширение командного файла должно быть не cmd, а bat).

Для получения исполняемого файла, предназначенного выполняться в 32-битных операционных системах от MS, следует использовать опцию компоновщика alink.exe, имеющую вид -oPE. Причем для исполняемых файлов текстового режима (называемых здесь консольными приложениями) следует дополнительно указывать в качестве рабочей подсистемы именно консольный режим, задавая его опцией

-subsys concole

Кроме того, компоновщик alink.exe для рассматриваемых исполняемых файлов должен использовать предназначенную для него библиотеку импорта, которая в указанном комплекте имеет имя win32.lib. (Особо подчеркнем, что следует использовать библиотеку импорта именно из указанного комплекта, а не просто "где-то найденный" файл с именем win32.lib) Эту библиотеку при вызове компоновщика нужно указывать как один из компонуемых файлов, в частности задавая его полным именем.

В рассмотренных примере и варианте командного файла предполагается, что библиотека импорта размещается в каталоге C:\util, при размещении ее в другом месте следует (вместо использованного здесь имени каталога) записать действительное имя каталога, хранящего ее. (Еще одной возможностью является указание каталога, в котором помещаются библиотеки импорта, с помощью дополнительной опции -L, что в данном примере приводит к командной строке внутри командного файла, имеющей вид

alink -oPE -subsys console %1 -L C:\util win32.lib

Вариации последней возможности целесообразно использовать, когда разработчику при вызове компоновщика alink нужно указать более чем одну библиотеку импорта в одном каталоге. Тогда, вместо задания полного пути к каждой библиотеке, можно его указать один раз для всех этих библиотек. Заметим еще, что при размещении библиотеки импорта win32.lib в текущем каталоге, откуда производится вызов командного файла, путь к этой библиотеки можно не указывать - ни опцией -L, ни прямой записью пути в полном имени этого файла.)

Если, по какой-нибудь причине, имеется желание использовать компоновщик TLINK32.EXE, то его удобно использовать в составе командного файла asmtl.cmd, состоящего из строк

nasmw -f obj %1.asm -l %1.lst

tlink32 %1, , , IMPORT32

Листинг 5.4.3. Командный файл asmtl.cmd, использующий компоновщик tlink32

Этот вариант компоновки использует библиотеку импорта IMPORT32.LIB для системных библиотек, входящую в состав систем разработки Borland/Inprise. Библиотека используется со своего места размещения в указанной системе разработки, если последняя установлена нормальным образом. В простейшем случае отсутствия полной установки системы разработки достаточно использовать только исполняемый файл TLINK32.EXE и файл IMPORT32.LIB, переписав их, например, в текущий каталог для программирования на NASMW.

Соседние файлы в предмете Системное программное обеспечение