Вход/Регистрация
Программирование для Linux. Профессиональный подход
вернуться

Самьюэл Алекс

Шрифт:

Таблица 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
. При отсутствии данной секции компилятор может сделать неверное предположение о том, что регистры содержат прежние значения, и это скажется на работе программы.

9.4. Пример

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

Инструкция

bsrl
вычисляет местоположение старшего значащего бита в первом операнде и записывает результат (номер позиции начиная с нуля) во второй операнд. Например, следующая команда анализирует переменную number и помещает результат в переменную
position
:

asm("bsrl %1, %0" : "=r" (position) : "r" (number)};

Ей соответствует такой фрагмент на языке С:

long i;

for (i = (number >> 1), position = 0; i != 0; ++position)

 i >>= 1;

Чтобы сравнить скорость выполнения двух фрагментов, мы поместили их в цикл, где перебирается большое количество чисел. В листинге 9.1 приведена реализация на языке С. Программа перебирает значения от единицы до числа, указанного в командной строке. Для каждого значения переменной number вычисляется позиция старшего значащего бита. В листинге 9.2 показано, как сделать то же самое с помощью ассемблерной вставки. Обратите внимание на то, что в обоих случаях результат вычислений заносится в переменную

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

Листинг 9.1. (bit-pos-loop.c) Нахождение позиции старшего значащего бита в цикле

#include <stdio.h>

#include <stdlib.h>

int main(int argc, char* argv[]) {

 long max = atoi(argv[1]);

 long number;

 long i;

 unsigned position;

 volatile unsigned result;

 /* Повторяем вычисления для большого количества чисел. */

 for (number = 1; number <= max; ++number) {

/* Сдвигаем число вправо, пока результат не станет

равным нулю.

Запоминаем количество операций сдвига. */

 for (i = (number >> 1), position = 0; i != 0; ++position)

i >>= 1;

/* Позиция старшего значащего бита — это общее число

операций сдвига, кроме первой. */

  • Читать дальше
  • 1
  • ...
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: