Использование массивов C во встроенной сборке GCC - PullRequest
0 голосов
/ 17 мая 2011

Я хотел бы использовать два массива, переданных в функцию C, как показано ниже, при сборке с использованием компилятора GCC (Xcode на Mac).Прошло много лет с тех пор, как я написал ассемблер, поэтому я уверен, что это легко исправить.

Первая строка здесь в порядке.Вторая строка не проходит.Я пытаюсь сделать следующее, A [0] + = x [0] * x [0], и я хочу сделать это для многих элементов в массиве с разными индексами.Я только показываю один здесь.Как использовать массив чтения / записи в блоке сборки?

И если есть лучший способ сделать это, у меня открытые уши.

inline void ArrayOperation(float A[36], const float x[8])
{
    float tmp;

    __asm__ ( "fld %1; fld %2; fmul; fstp %0;" : "=r" (tmp) : "r" (x[0]), "r" (x[0]) );
    __asm__ ( "fld %1; fld %2; fadd; fstp %0;" : "=r" (A[0]) : "r" (A[0]), "r" (tmp) );

    // ...
}

1 Ответ

2 голосов
/ 17 мая 2011

Причина сбоя кода не в массивах, а в том, как работают команды fld и fst.Это код, который вы хотите:

float tmp;

__asm__ ( "flds %1; fld %%st(0); fmulp; " : "=t" (tmp) : "m" (x[0]) );
__asm__ ( "flds %1; fadds %2;" : "=t" (A[0]) : "m" (A[0]), "m" (tmp) );

fld и fst инструкции нуждаются в операнде памяти.Также вам необходимо указать, хотите ли вы загружать float (flds), double (fldl) или long double (fldt).Что касается выходных операндов, я просто использую ограничение =t, которое просто сообщает компилятору, что результат находится на вершине стека регистров, то есть ST (0).

У арифметических операций либо нет операндов(fmulp) или один операнд памяти (но затем вам нужно снова указать размер, fmuls, fadds и т. д.).

Подробнее о встроенном ассемблере , GNU Assembler в целом и см. Руководство разработчика программного обеспечения для архитектур Intel® 64 и IA-32 .

Конечно, лучше всего избавиться от временной переменной:

   __asm__ ( "flds %1; fld %%st(0); fmulp; fadds %2;" : "=t" (A[0]) : "m" (x[0]), "m" (A[0]));

Хотя, если вы хотите повысить производительность, вам не нужно использовать ассемблер.GCC полностью способен производить этот код.Но вы можете рассмотреть возможность использования векторных инструкций SSE и других простых методов оптимизации, таких как разрыв цепочек зависимостей в вычислениях, см. Руководства по оптимизации Agner Fog

...