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

5.6. Стандартный доступ к системным функциям Unix

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

Для ОС Unix, реализованных в архитектуре Intel, стандартный доступ выливается в укладку аргументов на стек и вызов машинной функции CALL, конкретизация же машинного доступа осуществляется с помощью стандартной библиотеки языка С, которая оказывается необходимой при компоновке.

Сама стандартная библиотека языка С в Linux называется libc и размещается в каталоге, который автоматически просматривает компоновщик (информация о таких каталогах находится в конфигурационном файле /etc/ld.conf ).

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

В последних версиях Linux из этого вытекает для чисто ассемблерных программ необходимость либо использовать достаточно тонкую опцию универсального компоновщика ld, либо задействовать для целей компоновки универсальную программу обработки программ, ориентированную прежде всего на язык Си. Вначале рассмотрим первый вариант.

Он требует явного указания в составе опций вызова программы ld опции

-dynamic-linker полное_имя_динамического_компоновщика

где полное имя динамического компоновщика в момент написания данного пособия в Linux задается как /lib/ld-linux.so.2, обозначая разделяемую библиотеку. (В общем случае, если такого файла в системе разработки нет, целесообразно либо найти его близкий аналог по названию и попробовать его использовать, либо, что значительно надежней, найти, какое имя динамического компоновщика используют выполняемые файлы, получаемые как результат работы программы gcc.)

Кроме того, при компоновке необходимо указать использование самой библиотеки libc, для чего служит специальная опция вида -lc. (Собственно опция, в общем случае имеет вид ‑lсобственная_часть_имени_библиотеки, а первые три буквы обозначения библиотеки libc относятся к стандартной части ее наименования.) Поэтому для построения выполняемой программы из одного исходного файла программы на ассемблере целесообразно использовать командный файл, текст которого приведен в листинге 5.6.1.

nasm -f elf $1.asm -l $1.lst

ld -o "$1".exe "$1".o -dynamic-linker /lib/ld-linux.so.2 -lc

Листинг 5.6.1. Командный файл nasmlc для трансляции программ со стандартным доступом

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

gcc имя_объектного_файла.o

Дело в том, что программа gcc настолько универсальна, что из объектного файла (или объектных файлов), указанного в перечне ее параметров, она формирует исполняемый файл, автоматически выполняя все необходимые при компоновке действия. При этом следует иметь в виду только одну, но очень важную деталь: точка входа в исходном ассемблерном файле должна быть обозначена не именем _start, а именем main. Для использования gcc с указанными целями может быть также построен командный файл, представленный листингом 5.6.2.

nasm -f elf $1.asm -l $1.lst

gcc -o "$1".exe "$1".o

Листинг 5.6.2. Командный файл nasmlg для трансляции программ

со стандартным доступом

Программы стандартной библиотеки языка Си в Linux вызываются, естественно, по стандартным для этого языка соглашениям. В частности, для программ на языке ассемблера необходимо позаботиться о очистке участка стека от использованных аргументов вызова. Напомним, что для этого после выполнения команды CALL имяфункции записывается команда

ADD ESP, длина_области_аргументов.

К удобству пользователей ОС Unix даже на ассемблере имена функций библиотеки языка Си не требуют никаких дополнительных символов. При этом не следует забывать указывать эти имена и в директивах EXTERN программы на ассемблере.

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

GLOBAL _start

EXTERN write, exit, printf

SEGMENT .text

_start:

;--- write(1, txt, lentxt) == <4>(ebx, ecx, edx)

push dword lentxt

push dword txt

push dword 1

call write

add esp, 12

; call printf(formt, x, y)

push dword [y]

push dword [x]

push dword formt

call printf

add esp,12

push dword 1

call exit

SEGMENT .data

txt db 'Privet!',27,'[10;40H',27,'[1;31;44mOu-key!'

db 27,'[0m',10

lentxt equ $-txt

x dd 3456

y dd -78881

formt db 'X=%d, Y=%d',10,0

Листинг 5.6.3. Пример использования системных функций через библиотеку libc

В этой программе использованы системные функции write и exit ОС Linux, а также очень удобная функция форматированного вывода printf, хорошо известная всем программистам на языке Си.

Еще раз подчеркнем, что для компоновки с помощью gcc, завершающей построение исполняемого файла (вместо компоновки с помощью комповщика ld), в этой программе строки

GLOBAL _start

и

_start:

должны быть заменены, соответственно, на строки

GLOBAL main

и

main:

С помощью стандартного вывода в рассматриваемой программе на экран выводятся фрагменты текста «Privet!» и «Ou_key!», которые сопровождаются управляющими последовательностями в самом тексте, который представляется на вывод функцией write. Управляющие последовательности позволяют позиционировать курсор (переустанавливать его в любое место экрана и тем самым направлять вывод в любое место экрана), а также управлять цветовыми атрибутами вывода. Подробней о управляющих последовательностях смотрите соответствующую литературу, например [15]. (Заметим, что управляющие последовательности доступны, конечно, не только через стандартные библиотеки, но и выводом через прерывание INT 80h, используемое в Linux на более низком уровне.)

Для использования функции printf в ассемблерной программе ее первый аргумент описан отдельно текстом в сегменте данных и обозначен именем formt. Этот текст включает служебные символы формата %d, которые обеспечивают задание преобразования значений, заданных последующими аргументами в обозримый для человека формат десятичных чисел.

Упражнения.

1. Построить библиотеку объектных модулей Linux, содержащих доступные извне процедуры с именами atoi, itoa. Процедура atoi должна выполнять преобразование последовательности цифр, заданной адресом, который содержит регистр eax, в двоичный код, выдаваемой ее также через регистр eax. Процедура itoa должна выводить в стандартный вывод последовательность десятичных цифр, представляющих исходное значение аргумента в регистре eax, задаваемое им в двоичном коде. Кроме того, библиотека должна содержать процедуру lfwrite, которая переводит вывод на экране на следующую строку и рассмотренные выше процедуры stdread, stdwrite, stdexit, собранные в один объектный файл. Дополнительно построить программу, которая использует все эти процедуры и при разработке которой используется данная библиотека объектных модулей.

2. Построить библиотеку объектных модулей, описанных в первом упражнении, для ОС Windows и разработать тестовый пример проверки функционирования этих модулей.

3. Построить ассемблерную программу, использующую процедуру вычисления функции Аккермана. Эта функция задается рекуррентными соотношениями

A(0,M)=M+1; A(N,0)=A(N-1,1); A(N,M)=A(N-1, A(N,M-1))

и естественный способ ее вычисления заключается в рекурсивных вызовах вычисляющей процедуры. Главная часть программы должна вводить числовые значения аргументов M и N, а затем обращаться к процедуре вычисления функции. Результат выводится на экран. При отладке начинать проверку работы с очень небольших значений, в частности полагая N<3, иначе есть риск не дождаться результата за приемлемое время.

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