5 / 5 / 1
Регистрация: 16.01.2011
Сообщений: 37
1

Как перевести синтаксис Intel в синтаксис AT&T? (ассемблерная вставка в СИ)

02.01.2014, 16:14. Показов 5188. Ответов 5
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Извиняюсь, что, возможно, пишу не в ту тему.

Нужен именно AT&T синтаксит. В качестве примера для курсовой я разбираю перемножение соответствующих элементов массивов с помощью SSE инструкций. Синтаксис Intel является не родным для компилятора GCC, поэтому с ним постоянно возникают проблемы, причём в разных версиях компилятора разные: то регистры eax недопустимы, то ex, то перевод синтаксиса в at&t недопустим, и куча других, а если скомпилируется, то возникает ошибка segmentation fault.

Вставка, написанная с использованиемсинтаксиса AT&T работает без проблем, но перевод, сделанный по мануалу на википедии не компилируется.

Как перевести код на AT&T синтаксис? Вот код вставки:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
__asm__ volatile (
    ".intel_syntax noprefix \n\t"
    "loop:                  \n\t"
    "movups xmm0, [eax+edx] \n\t"
    "movups xmm1, [ebx+edx] \n\t"
    "mulps xmm0, xmm1       \n\t"
    "movups [ecx+edx], xmm0 \n\t"
    "sub edx, 16            \n\t"
    "jnz loop               \n\t"
    ".att_syntax prefix \n\t"
    :
    : "a"(arr1), "b"(arr2), "c"(arr3), "d"(count)
    : "xmm0", "xmm1"
);
arr1, arr2 и arr3 имеют тип float*, count — long.

P.S. Вставки сделанные с помощью конструкции __asm { ... }; тоже не компилируются. Версия GCC: 4.4.7.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
02.01.2014, 16:14
Ответы с готовыми решениями:

Как перевести строку из синтаксиса Intel в синтаксис AT&T?
mov al, byte ptr string

Как перевести синтаксис макроса VBA (Excel) в синтаксис Visual FoxPro
Здравствуйте! Скажите пожалуйста, как перевести синтаксис записанного макроса в excel в синтаксис...

Ключи для переключения с AT&T на Intel синтаксис в среде Code::Blocks
здр.. планирую написать ассемблерную вставку в чистый Си в среде Code::Blocks v17.12.. желательно...

Intel-синтаксис
учусь программировать на FASM, но книг и документации на Русском языке мало. Подскажите книги и...

5
Ушел с форума
Автор FAQ
16279 / 7604 / 1065
Регистрация: 11.11.2010
Сообщений: 13,617
02.01.2014, 16:52 2
Finesse,
попытайся переводить по одной строке, основное различие - это обратный порядок операндов и указание типа операндов в названии операции, то есть sub edx, 16 = subl $16,%edx
1
5 / 5 / 1
Регистрация: 16.01.2011
Сообщений: 37
03.01.2014, 02:47  [ТС] 3
Цитата Сообщение от Mikl___ Посмотреть сообщение
Finesse,
попытайся переводить по одной строке, основное различие - это обратный порядок операндов и указание типа операндов в названии операции, то есть sub edx, 16 = subl $16,%edx
Спасибо, получилось
C
1
2
3
4
5
6
7
8
9
10
11
12
__asm__ volatile (
    "loop:                          \n\t"
    "movups (%%eax,%%edx), %%xmm0   \n\t" // Загружает 4 числа в первый регистр (xmm0)
    "movups (%%ebx,%%edx), %%xmm1   \n\t" // Загружает 4 числа во второй регистр (xmm1)
    "mulps %%xmm1, %%xmm0           \n\t" // Перемножает оба векторных регистра
    "movups %%xmm0, (%%ecx,%%edx)   \n\t" // Записывает результат в память
    "subl $0x10, %%edx              \n\t" // Понижение адресной метки на 4 float'а
    "jnz loop                       \n\t"
    :
    : "a"(arr1), "b"(arr2), "c"(arr3), "d"(count)
    : "xmm0", "xmm1"
);
Но почему-то если предпоследнюю строку заменить на subq $0x10, %%edx, то не компилируется (у переменной count, которая передаётся в регистр edx, тип long).

И всё равно возникает ошибка segmentation fault, но уже при выполнении скомпилированной программы. Возникает она в строке movups (%%eax,%%edx), %%xmm0, даже если переделать её в movups (%%eax), %%xmm0. Память под указатель arr1, который передаётся в регистр eax выделена через функцию malloc. Не знаете, в чём дело?

Добавлено через 7 минут
P.S.: немного контекста:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
long amount = 1000;
float *vectorA, *vectorB, *vectorC;
vectorA = (float*)malloc(amount * sizeof(float));
vectorB = (float*)malloc(amount * sizeof(float));
vectorC = (float*)malloc(amount * sizeof(float));
for(long i = 0; i < amount; ++i) {
    vectorA[i] = (float)rand() / 100000;
    vectorB[i] = (float)rand() / 100000;
    vectorC[i] = (float)rand() / 100000;
}
__asm__ volatile (
    "loop:                          \n\t"
    "movups (%%eax,%%edx), %%xmm0   \n\t" // Загружает 4 числа в первый регистр (xmm0)
    "movups (%%ebx,%%edx), %%xmm1   \n\t" // Загружает 4 числа во второй регистр (xmm1)
    "mulps %%xmm1, %%xmm0           \n\t" // Перемножает оба векторных регистра
    "movups %%xmm0, (%%ecx,%%edx)   \n\t" // Записывает результат в память
    "subl $0x10, %%edx              \n\t" // Понижение адресной метки на 4 float'а
    "jnz loop                       \n\t"
    :
    : "a"(vectorA), "b"(vectorB), "c"(vectorC), "d"(amount)
    : "xmm0", "xmm1"
);
0
Ушел с форума
Автор FAQ
16279 / 7604 / 1065
Регистрация: 11.11.2010
Сообщений: 13,617
03.01.2014, 03:03 4
Цитата Сообщение от Finesse Посмотреть сообщение
Но почему-то если предпоследнюю строку заменить на subq $0x10, %%edx, то не компилируется (у переменной count, которая передаётся в регистр edx, тип long)
то что в intel-синтаксисе называется duoble в AT&T называется long, а вот команда subq, скорее всего, скомпилируется с регистром %%rdx попробуй указатель на память передать в регистр командой lea в intel-синтаксисе это бы выглядело как lea eax,vectorA
1
5 / 5 / 1
Регистрация: 16.01.2011
Сообщений: 37
03.01.2014, 15:06  [ТС] 5
Цитата Сообщение от Mikl___ Посмотреть сообщение
то что в intel-синтаксисе называется duoble в AT&T называется long, а вот команда subq, скорее всего, скомпилируется с регистром %%rdx попробуй указатель на память передать в регистр командой lea в intel-синтаксисе это бы выглядело как lea eax,vectorA
Я понял в чём дело. Переменные длиной 4 байта помещаются в регистры e_x, а переменные длиной 8 байт (все переменный из примера), помещаются в регистры r_x. С этими регистрами и оператор subq нормально компилируется. В итоге полностью рабочий и исправленный семантически код вставки выглядит так:

C
1
2
3
4
5
6
7
8
9
10
11
12
__asm__ volatile (
    "loop:                          \n\t"
    "subq $0x10, %%rdx              \n\t" // Понижение адресной метки на 4 float'а
    "movups (%%rax,%%rdx), %%xmm0   \n\t" // Загружает 4 числа в первый регистр (xmm0)
    "movups (%%rbx,%%rdx), %%xmm1   \n\t" // Загружает 4 числа во второй регистр (xmm1)
    "mulps %%xmm1, %%xmm0           \n\t" // Перемножает оба векторных регистра
    "movups %%xmm0, (%%rcx,%%rdx)   \n\t" // Записывает результат в память
    "jnz loop                       \n\t"
    :
    : "a"(vectorA), "b"(vectorB), "c"(vectorC), "d"(amount)
    : "xmm0", "xmm1"
);
Спасибо за подсказки, тему можно закрывать.
0
5 / 5 / 1
Регистрация: 16.01.2011
Сообщений: 37
07.01.2014, 13:55  [ТС] 6
В итоге полный рабочий код для 64-битной архитектуры программы, каторая перемножает 2 массива векторными SSE инструкциями:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <stdio.h>
#include <stdlib.h>
int main() {
    long amount = 100000; // Должно быть кратно 4
    float *vectorA, *vectorB, *vectorC;
    vectorA = (float*)malloc(amount * sizeof(float));
    vectorB = (float*)malloc(amount * sizeof(float));
    vectorC = (float*)malloc(amount * sizeof(float));
    for(long i = 0; i < amount; ++i) {
        vectorA[i] = (float)rand() / 100000;
        vectorB[i] = (float)rand() / 100000;
        vectorC[i] = 0.0;
    }
    __asm__ volatile (
        "loop:                          \n\t"
        "subq $0x10, %%rdx              \n\t" // Понижение адресной метки на 4 float'а
        "movups (%%rax,%%rdx), %%xmm0   \n\t" // Загружает 4 числа в первый регистр (xmm0)
        "movups (%%rbx,%%rdx), %%xmm1   \n\t" // Загружает 4 числа во второй регистр (xmm1)
        "mulps %%xmm1, %%xmm0           \n\t" // Перемножает оба векторных регистра
        "movups %%xmm0, (%%rcx,%%rdx)   \n\t" // Записывает результат в память
        "jnz loop                       \n\t"
        :
        : "a"(vectorA), "b"(vectorB), "c"(vectorC), "d"(amount)
        : "xmm0", "xmm1"
    );
    free(vectorA);
    free(vectorB);
    free(vectorC);
    return 0;
}
Можно ещё приделать ввод/вывод и замер времени
1
07.01.2014, 13:55
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
07.01.2014, 13:55
Помогаю со студенческими работами здесь

Синтаксис. Использование &
Скажите, пожалуйста, чем отличается foo(std::string a); от этого foo(std::string&amp; a); ?

Отсутствует синтаксис Intel в gdb
Когда пытаюсь перейти с синтаксиса ATT на Intel происходит следующее: (gdb) set...

Перевести с C++ в Си (синтаксис)
всем доброго времени суток. немного знаю Си, но совершенно не владею С++. задача перевести код из...

Синтаксис запросов vs. синтаксис методов
Занимаюсь изучением LINQ'a, и возник вопрос, как переписать следующий запрос IEnumerable&lt;int&gt;...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru