Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Флоренсов А.Н. УП Системное программное обеспечение.docx
Скачиваний:
66
Добавлен:
28.06.2021
Размер:
148.95 Кб
Скачать

5.4. Использование свободно распространяемых утилит для Win32

С учетом стремления пользоваться некоммерческими продуктами, которые нередко более активно совершенствуются в последующих общедоступных версиях, рассмотрим современный библиотекарь для форматов файлов Windows. (Можно заметить, что 10–15 лет назад активно использовались и поддерживались выпуском новых версий, теперь почти забытые утилиты от фирмы Borland и Watcom и некоторых независимых производителей, на которых, как морально устаревших, останавливаться не будем.)

Наиболее интересным оказывается утилита системного компоновщика GoLink.exe (CopyrightJeremyGordon 2002–2016 – JG@JGnet.co.uk). Отличительной особенностью этой утилиты является полный отказ от библиотек объектных файлов и библиотек импорта. С формальной стороны отсюда вытекает отсутствие возможности использовать в качестве параметров файл, имеющий расширение .LIB. Отказ от библиотек импорта компенсируется решением использовать информацию об импортируемых именах (в первую очередь именах подпрограмм) непосредственно из DLL, задействованных в дальнейшем выполнении исполняемых файлов.

Практически такое решение значительно упрощает разработку, поскольку для будущей работы DLL обязательно должны быть в системе, а ориентация на библиотеки импорта требует наличия таких библиотек у разработчика, в том числе не имеющего коммерческих средств разработки. Другие корпоративные разработчики (Borland и Watcom) предоставляли стандартные для них средства оперативного преобразования имеющихся DLL в соответствующие им библиотеки импорта, но Microsoft целенаправлено избегала предоставления таких средств и ограничивала тем самым возможности сторонних разработчиков. Сами библиотеки импорта от Microsoft всегда специально строились так, чтобы обеспечивать взаимодействие только с определенной версией DLL для конкретного типа особенностей операционной системы, что неявно понуждала не очень профессиональных программистов пользоваться программными инструментами исключительно от MS и заметно снижала оперативность сторонних разработок.

Неподдержка программой GoLink библиотек объектных файлов не позволяет разработчику использовать такие библиотеки, поэтому очевидным образом автор указанной утилиты и не предлагает никакой собственный вариант утилиты библиотекаря. Фактически все это отражает современную ситуация отхода от широкого спектра инструментальных возможностей и от применения по возможности компактных и нерасточительных относительно запросов на аппаратурные ресурсы средств. В результате происходит подталкивание к использованию в качестве библиотечных наборов исключительно DLL, несмотря на то, что они в частных решениях иногда оказываются неэффективными (аналогично забиванию мелких гвоздей большим молотком).

Очень приятное свойство утилиты GoLink для 32-битных приложений заключается в том, что, как следствие принятых и кратко описанных выше технических решений, не нужно отвлекаться на модифицированные имена системных функций. Поскольку в DLL применяются «родные» имена системных функций, то никаких дополнительных подчеркиваний, специальных символов и числовых добавлений не требуется.

В результате для решения поставленной выше простейшей проблемы ввода и вывода формируются тексты, приведенные в листингах 5.4.1 и 5.4.2.

GLOBAL _start

EXTERN GetStdHandle, WriteFile, ExitProcess

EXTERN ReadFile

segment .text

_start: push dword STD_OUTPUT_HANDLE

call GetStdHandle

mov [hstdout],eax

push dword STD_INPUT_HANDLE

call GetStdHandle

mov [hstdin],eax

;--- ReadFile(hstdin, buf, 80, &actlen, NULL)

push dword 0

push dword actlen

push dword 80 ; number of bytes

push dword buf ; address of txt

push dword [hstdin] ; N handle=hstdout

call ReadFile

mov byte [buf+1],'!'

;---WriteFile(hstdout, buf, actlen, &actlen, NULL)

push dword 0; NULL

push dword actlen ; address of actual byte number

push dword [actlen]

push dword buf ; address of txt

push dword [hstdout]; N handle=hstdout

call WriteFile

; ExitProcess(0)

push dword 0

call ExitProcess

segment .data

buftimes 80 db 0

hstdin dd 0

hstdout dd 0

actlendd 0

STD_INPUT_HANDLE equ –10

STD_OUTPUT_HANDLE equ –11

Листинг 5.4.1. Программа на ассемблере для компоновщика GoLink

Командный файл разработки для этой программы имеет вид

nasm –f win32 %1.asm

golink /entry _start /console %1.obj kernel32.dll

Листинг 5.4.2. Командный файл для получения выполняемой программы

Таким образом, трансляция NASM не имеет никаких особенностей (транслятору все равно, какие внешние имена используются для функций, детализация их связей с местом реализации – это забота компоновщика). Вызов golink имеет ряд мелких, но приятных относительно link от MS особенностей. В опции /entry задается без раздражающего специального разделителя именно то имя точки входа, которое было написано в исходной программе на ассемблере (никаких закулисных соглашений и неявных договоренностей). Назначение результирующего файла задается как консольного более кратким вариантом содержательной опции /console. При ее отсутствии формируется по возможности исполняемый файл графического приложения.

Хотя утилита golink не позволяет использовать библиотеки объектных файлов, в ее вызове можно явно указать любое число объектных файлов. Эти объектные файлы опять же следует использовать с собственными именами системных функций. В результате для нашей задачи должны быть построены файлы wrstdg, rdstdg, exitprocg и на их основе получены объектные модули writestdg, readstdg, exitprocg (листинг 5.4.3, 5.4.4, 5.4.5):

segment .text

writestdg: ; регистр EBX – адрес выводимых данных, ECX – их длина

extern GetStdHandle, WriteFile

global writestdg

push dword –11;STD_OUTPUT_HANDLE

call GetStdHandle

mov [hstdout],eax

;---WriteFile(hstdout, prmpt, actlen, &actlen, NULL)

push dword 0

push dword actlen ; address of actual byte number

push ecx ; number of bytes (value !)

push ebx ; address of txt

push dword [hstdout]; N handle=hstdout

call WriteFile

mov eax, [actlen]

ret

SEGMENT .data

hstdout dd 0

actlendd 0

Листинг 5.4.3. Содержимое файла stdwrg.asm с процедурой writestd

segment .text

readstdg: ; регистр EBX – адресданных, ECX – ограничение на длину ввода

extern GetStdHandle,ReadFile

global readstdg

push dword –10 ;STD_INPUT_HANDLE

call GetStdHandle

mov [hstdin],eax

;---ReadFile(hstdin, buf, 80, &actlen, NULL)

push dword 0

push dword actlen

push ecx ; number of bytes

push ebx; address of txt

push dword [hstdin] ; N handle=hstdout

call ReadFile

mov eax, [actlen]

ret

SEGMENT .data

hstdin dd 0

actlen dd 0

Листинг 5.4.4. Содержимое файла stdrdg.asm с процедурой rditestdg

segment .text

exitprocg: ; параметр кода ошибки в регистре ECX

extern ExitProcess

global exitprocg

push ecx

call ExitProcess

ret

Листинг 5.4.5. Содержимое файла stdexg.asm с процедурой exitprocg

Главная программа будет задаваться текстом, приведенным в листинге 5.4.6.

GLOBAL _start

EXTERN writestdg, readstdg, exitprocg

segment .text

_start: mov ebx, prmpt

mov ecx, 20

call writestdg

mov ebx, buf

mov ecx, 80

call readstdg

mov byte [buf+1],'!'

mov ebx, buf

mov ecx, eax

call writestdg

mov ecx, 0

call exitprocg

segment .data

buf times 80 db 0

prmpt db 'Input text, please: '

Листинг 5.4.6. Главная программа prog3g, использующая writestd, readstd, exitstd

Вызов компилятора и компоновщика для построения выполняемого файла в данном случае должен задаваться в виде последовательности команд:

nasm –fwin32 prog3g.asm

golink /entry _start /console prog3g.obj stdwrg.obj stdrdg.obj stdexg.obj kernel32.dll