скопировать из памяти для регистрации в c ++ с использованием ассемблерного кода

у меня проблема при преобразовании программы на С ++ в сборку
я должен сделать это для

вот мой код с ++

for(int i=0;i<rows-4;i++,a+=4,b+=4,c+=4,d+=4,e+=4,f+=4,x+=4,o+=4){
for(int j=0;j<cols-4;j++,a++,b++,c++,d++,e++,f++,x++,o++){
*o=*a>*x;
*o=*b>*x|(*o<<1);
*o=*c>*x|(*o<<1);
*o=*d>*x|(*o<<1);
*o=*e>*x|(*o<<1);
*o=*f>*x|(*o<<1);
}
}

o — указатель для выходных данных, в то время как a, b, c, d, e, f и x — указатель на входные данные. я хочу просто сохранить сравнения из входных данных в одной переменной, но приведенный выше код неэффективен, когда обрабатываемые данные большие. Программе нужно больше раз сохранять данные в памяти по сравнению с сохранением временных данных в регистре.

так что я хочу сделать это просто сделать этот процесс в реестре. Я попытался сохранить данные, на которые ссылается x, в EBX, сравнить EBX с ECX, которые содержат значение, на которое ссылается a (и b, c, d, e, f, последовательно), сохранить результат сравнения в EAX и сдвиг EAX регистр слева, так что все сравнения будут храниться в одной переменной. после того, как все 6 сравнений уже обработаны, значение из ECX копируется в память.

вот что я сделал, моя программа может работать в два раза быстрее, но все значения, которые я получаю, равны нулю. может я ошибаюсь?

      __asm__(
"xorl %%eax,%%eax;""xorl %%ebx,%%ebx;""xorl %%ecx,%%ecx;"
"movl %1, %%ebx;"
//start here
"movl %2,%%ecx;""cmp %%ebx,%%ecx;""jnz .one;""orl $0x1,%%eax;"
".one:;""shll $1,%%eax;""movl %3,%%ecx;""cmp %%ebx,%%ecx;""jnz .two;""orl $0x1,%%eax;"
".two:;""shll $1,%%eax;""movl %4,%%ecx;""cmp %%ebx,%%ecx;""jnz .three;""orl $0x1,%%eax;"
".three:;""shll $1,%%eax;""movl %5,%%ecx;""cmp %%ebx,%%ecx;""jnz .four;""orl $0x1,%%eax;"
".four:""shll $1,%%eax;""movl %6,%%ecx;""cmp %%ebx,%%ecx;""jnz .five;""orl $0x1,%%eax;"
".five:""shll $1,%%eax;""movl %7,%%ecx;""cmp %%ebx,%%ecx;""jnz .six;""orl $0x1,%%eax;"
".six:"//output
"movl %%eax,%0;"
:"=r"(sett)
:"r"((int)*x),"r"((int)*a) ,"r"((int)*b) ,"r"((int)*c) ,"r"((int)*d),"r"((int)*e),"r"((int)*f) /* input */
);

0

Решение

Несколько вариантов:

1) Выбросьте свой код сборки ручной сборки. Вы сказали, что код на C медленный, расскажите нам, насколько. Я не вижу, как можно было бы измерить разницу каким-либо значимым образом, поскольку версия asm даже не дает правильного результата. Поставь по другому, попробуй asm("nop;");Это еще более быстрый способ получить неправильный результат.

2) Перепишите ваш код на C, чтобы прочитать *x только однажды; сохранить результат во временной переменной и писать только в *o в конце.

3) Если это соответствует вашей семантике (и поддерживается вашим компилятором), украсьте ваши указатели с помощью restrict/__restrict/__restrict__ (из C99, обычно доступен в C ++ как расширение), поэтому компилятор не знает, что ни одна из входных переменных не изменяется при записи в *o,

4) Компиляторы достаточно хороши в автоматическом развертывании циклов. Это может потребовать комбинации параметров командной строки, #pragma директивы или расширение / атрибуты.

Вот что я имею в виду, переписав его, чтобы использовать временные:

for(int i=0;i<rows-4;i++,a+=4,b+=4,c+=4,d+=4,e+=4,f+=4,x+=4,o+=4){
for(int j=0;j<cols-4;j++,a++,b++,c++,d++,e++,f++,x++,o++){
uint32_t tmp_x = *x;
*o = (*a > tmp_x ? 0x20 : 0)
|  (*b > tmp_x ? 0x10 : 0)
|  (*c > tmp_x ? 0x08 : 0)
|  (*d > tmp_x ? 0x04 : 0)
|  (*e > tmp_x ? 0x02 : 0)
|  (*f > tmp_x ? 0x01 : 0);
}
}

Что это меняет? На оригинальной версии, x читается в каждом задании. Компилятор этого не знает o а также x указать на разные места; в худшем случае компилятор должен читать из x снова каждый раз, потому что, написав o, значение в x может меняться

Конечно, этот код имеет другую семантику: если вы действительно позволяете o псевдоним любого другого указателя, он будет делать что-то отличное от оригинала.

1

Другие решения

Я предполагаю, что вы используете новейший чип Intel. … и я думаю, что вы действительно хотите использовать (довольно ограниченный, если использовать, скажем, векторные возможности Cray :-), они называются AVX. Есть также библиотеки, которые будут делать это в C / C ++, начните с поиска в Google AVX и C.

Сказав это, вы также можете указать компилятору сохранить некоторые переменные в регистрах, используя ключевое слово «register», см. Это Зарегистрировать ключевое слово в C ++

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector