Марк Митчелл - Программирование для Linux. Профессиональный подход
- Название:Программирование для Linux. Профессиональный подход
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:2002
- Город:Москва
- ISBN:5-8459-0243-6
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Марк Митчелл - Программирование для Linux. Профессиональный подход краткое содержание
Данная книга в основном посвящена программированию в среде GNU/Linux. Авторы применяют обучающий подход, последовательно излагая самые важные концепции и методики использования расширенных возможностей системы GNU/Linux в прикладных программах. Читатели научатся писать программы, к интерфейсу которых привыкли пользователи Linux; освоят такие технологии, как многозадачность, многопотоковое программирование, межзадачное взаимодействие и взаимодействие с аппаратными устройствами; смогут улучшить свои программы, сделав их быстрее, надежнее и безопаснее; поймут особенности системы GNU/Linux, ее ограничения, дополнительные возможности и специфические соглашения.
Книга предназначена для программистов, уже знакомых с языком С и имеющих базовый опыт работы в GNU/Linux.
Программирование для Linux. Профессиональный подход - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Во второй секции задаются выходные операнды. Единственный такой операнд будет помещен в C-переменную answer, которая должна быть адресуемым (левосторонним) значением. В выражении "=r"знак равенства обозначает выходной операнд, а буква rуказывает на то, что значение переменной answerзаносится в регистр.
В третьей секции перечислены входные операнды. Переменная operandсодержит значение, подвергаемое битовому сдвигу. Выражение "r"означает, что значение переменной записывается в регистр.
Выражение "cc"в четвертой секции говорит о том. что инструкция меняет значение регистра cc(содержит код завершения).
9.2.1. Преобразование функции asm() в ассемблерные инструкции
Компилятор gccинтерпретирует функцию asm()очень просто: он генерирует ассемблерные инструкции, обрабатывающие указанные входные и выходные операнды, после чего заменяет вызов функции заданной инструкцией. Никакой дополнительный анализ не выполняется.
Например, следующий фрагмент программы:
double foo, bar;
asm("mycool_asm %1, %0" : "=r" (bar) : "r" (foo));
будет преобразован в такую последовательность команд x86:
movl -8(%ebp),%edx
movl -4(%ebp),%ecx
#APP
mycool_asm %edx, %edx
#NO_APP
movl %edx,-16(%ebp)
movl %ecx,-12(%ebp)
Переменные fooи barзанимают по два слова в стеке в 32-разрядной архитектуре x86. Регистр ebpссылается на данные, находящиеся в стеке.
Первые две команды копируют переменную foo в регистры edxи ecx, с которыми работает инструкция mycool_asm. Компилятор решил поместить результат в те же самые регистры. Последние две команды копируют результат в переменную bar. Выбор нужных регистров и копирование операндов осуществляются автоматически.
9.3. Расширенный синтаксис ассемблерных вставок
В следующих подразделах будет описан синтаксис правил, по которым строятся выражения в функции asm(). Секции выражения отделяются друг от друга двоеточиями. Мы будем ссылаться на следующую инструкцию, которая вычисляет результат булевого выражения x > y:
asm("fucomip %%st(1), %%st; seta %%al" :
"=a" (result) : "u" (y), "t" (x) : "cc", "st");
Сначала инструкция fucomipсравнивает два операнда, xи y, и помещает значение, обозначающее результат, в регистр cc, после чего инструкция setaпреобразует это значение в 0 или 1.
9.3.1. Ассемблерные инструкции
Первая секция содержит ассемблерные инструкции, заключенные в кавычки. В рассматриваемом примере таких инструкций две: fucomipи seta. Они разделены точкой с запятой. Если текущий вариант языка ассемблера не допускает такого способа разделения инструкций, воспользуйтесь символом новой строки ( \n).
Компилятор игнорирует содержимое первого раздела, разве что один уровень символов процента удаляется, т.е. вместо %%будет %. Смысл выражения %%st(1)и ему подобных зависит от архитектуры компьютера.
Если при компиляции программы, содержащей функцию asm(), указать опцию -traditionalили -ansi, компилятор gccвыдаст предупреждение. Чтобы этого избежать, используйте альтернативное имя __asm__.
9.3.2. Выходные операнды
Во второй секции указаны выходные операнды инструкции. Каждому операнду соответствует строка адресации и выражение языка С, записанное в скобках. В случае выходных операндов (все они должны быть левосторонними значениями) строка адресации должна начинаться со знака равенства. Компилятор проверяет, действительно ли каждый выходной операнд является левосторонним значением (т.е может стоять в левой части оператора присваивания).
Список обозначений регистров для конкретной архитектуры можно найти в исходных текстах компилятора gcc(конкретнее — в определении макроса REG_CLASS_FROM_LETTER). Например, в файле gcc/config/i386/i386.hсодержатся обозначения, соответствующие архитектуре x86 (табл. 9.1).
Таблица 9.1. Обозначения регистров в архитектуре Intel x86
| Символ регистра | Регистры, которые могут использоваться компилятором gcc |
|---|---|
| R | Регистры общего назначения (EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP) |
| q | Общие регистры хранения данных (EAX, ЕВХ, ECX, EDX) |
| f | Регистр для чисел с плавающей запятой |
| t | Верхний стековый регистр для чисел с плавающей запятой |
| u | Второй после верхнего стековый регистр для чисел с плавающей запятой |
| a | Регистр EAX |
| b | Регистр EBX |
| с | Регистр ECX |
| d | Регистр EDX |
| x | Регистр SSE (регистр потокового расширения SIMD) |
| y | Мультимедийные регистры MMX |
| A | Восьмибайтовое значение, формируемое из регистров EAX и EDX |
| D | Указатель приемной строки в строковых операциях (EDI) |
| S | Указатель исходной строки в строковых операциях (ESI) |
Если есть несколько однотипных операндов, то они разделяются запятыми, как показано в секции входных операндов. Всего можно задавать до десяти операндов, адресуемых как %0, %1, … %9. Если выходные операнды отсутствуют, но есть входные операнды или модифицируемые регистры, то вторую секцию следует оставить пустой или пометить ее комментарием наподобие /* нет выходных данных */.
9.3.3. Входные операнды
В третьей секции задаются входные операнды. Строка адресации такого операнда не должна содержать знака равенства, в остальном синтаксис совпадает с синтаксисом выходных операндов.
Если требуется указать, что в одной инструкции осуществляется как чтение регистра, так и запись в него, необходимо в строке адресации входного операнда поставить номер выходного операнда. Например, если входной регистр должен быть тем же, что и регистр первого выходного операнда, назначьте ему номер 0. Выходные операнды нумеруются слева направо, начиная с нуля. Если просто указать одинаковое C-выражение для входного и выходного операндов, то это еще не означает, что оба значения будут помещены в один и тот же регистр.
Данную секцию можно пропустить, если входные операнды отсутствуют и следующая секция модифицируемых регистров пуста.
9.3.4. Модифицируемые регистры
Если в качестве побочного эффекта инструкция модифицирует значение одного или нескольких регистров, в функции asm()должна присутствовать четвертая секция. Например, инструкция fucomipменяет регистр кода завершения, обозначаемый как cc. Строки, представляющие затираемые регистры, разделяются запятыми. Если инструкция способна изменить произвольную ячейку памяти, в этой секции должно стоять ключевое слово memory. На основании этой информации компилятор определяет, какие значения должны быть загружены повторно после завершения функции asm(). При отсутствии данной секции компилятор может сделать неверное предположение о том, что регистры содержат прежние значения, и это скажется на работе программы.
Интервал:
Закладка: