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

Узнай цену своей работы

Формулировка задачи:

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

Решение задачи: «Как перевести синтаксис Intel в синтаксис AT&T? (ассемблерная вставка в СИ)»

textual
Листинг программы
#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. Синтаксис программы: Программа написана на языке C и содержит ассемблерную вставку.
  2. Выделение памяти: В начале программы выделяется память под три указателя на float.
  3. Инициализация векторов: Затем, с помощью генератора случайных чисел, инициализируются два вектора (vectorA и vectorB) с 4 случайными числами в каждом. Третий вектор (vectorC) инициализируется нулями.
  4. Ассемблерная вставка: Далее следует ассемблерная вставка, которая выполняет перемножение двух векторов и сохранение результата в третий вектор.
  5. Освобождение памяти: В конце программы освобождается выделенная память.
  6. Условие цикла: В ассемблерной вставке используется цикл, который продолжается до тех пор, пока дескриптор (rdx) не станет кратным 4.
  7. Загрузка и перемножение векторов: Внутри цикла загружаются два вектора в соответствующие регистры (xmm0 и xmm1) и выполняется операция перемножения.
  8. Сохранение результата: Результат перемножения записывается обратно в память по адресу, указанному в регистре rcx с учетом смещения, определяемого дескриптором.
  9. Свободно используемые регистры: В ассемблерной вставке используются регистры rdx, rax и rbx, а также регистры xmm0 и xmm1.
  10. Свободно используемые библиотеки: В программе используются стандартные библиотеки C stdlib.h и printf.h.
  11. Синтаксис ассемблера: Ассемблерная вставка использует синтаксис Intel.
  12. Вывод: Программа не содержит операций вывода, поэтому она не выводит никаких чисел.
  13. Использование операции jnz: В ассемблерной вставке используется операция jnz (или jmp), которая продолжает цикл, если условие истинно.
  14. Использование операции mulps: В ассемблерной вставке используется операция mulps, которая выполняет перемножение двух векторов.
  15. Использование операции movups: В ассемблерной вставке используется операция movups, которая загружает или сохраняет 4 числа из или в память.
  16. Использование оператора ',': В ассемблерной вставке используется оператор запятой (,), который используется для перегрузки операндов.
  17. Использование регистров rdx, rax и rbx: В ассемблерной вставке используются регистры rdx, rax и rbx для адресации памяти и выполнения операций.
  18. Использование регистров xmm0 и xmm1: В ассемблерной вставке используются регистры xmm0 и xmm1 для хранения векторов.
  19. Использование директивы 'volatile': Ассемблерная вставка объявлена как volatile, что означает, что она будет выполняться точно так, как написана, и не будет оптимизирована компилятором.
  20. Указатели на функции: В программе используются функции malloc и free для выделения и освобождения памяти, а также функция rand для генерации случайных чисел.

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

11   голосов , оценка 4.091 из 5
Похожие ответы