встроенная сборка sse с g++

Я пробую встроенную сборку g++ и sse и написал первую программу. Это segfaults - почему?

#include <stdio.h>

float s[128*4] __attribute__((aligned(16)));

#define r0 3
#define r1 17
#define r2 110
#define rs0 "3"
#define rs1 "17"
#define rs2 "110"

int main () {
  s[r0*4+0] = 2.0;  s[r0*4+1] = 3.0;  s[r0*4+2] = 4.0;  s[r0*4+3] = 5.0;
  s[r1*4+0] = 3.5;  s[r1*4+1] = 3.5;  s[r1*4+2] = 3.5;  s[r1*4+3] = 3.5;
  asm (
    "\n\t  .intel_syntax noprefix"

    "\n\t  mov     edx,                s"
    "\n\t  movaps  xmm0,               [edx + " rs0 "*16]"
    "\n\t  movaps  xmm1,               [edx + " rs1 "*16]"
    "\n\t  mulps   xmm0,               xmm1"
    "\n\t  movaps  [edx + " rs2 "*16], xmm0"

    "\n\t  .att_syntax"
  );
  printf ("%f %f %f %f\n", s[r2*4+0], s[r2*4+1], s[r2*4+2], s[r2*4+3]);
}

И почему gdb не позволяет мне выполнить пошаговые инструкции по сборке? Нужно ли писать asm (""..") вокруг каждой строки?


person Thomas    schedule 15.09.2010    source источник
comment
[edx + rs2 *16] = [edx + 110*16] — не слишком ли это много? (Просто Угадай).   -  person Alex F    schedule 15.09.2010
comment
Отличный вопрос, нам нужно больше сборки здесь.   -  person Matt Joiner    schedule 15.09.2010
comment
IIRC GDB не устанавливает символы для встроенных функций (ASM или иных). Но не цитируйте меня по этому поводу.   -  person Rushyo    schedule 15.09.2010
comment
Используйте stepi для перехода от инструкции к инструкции.   -  person Stephen Canon    schedule 15.09.2010
comment
Да, я думаю, что это будет переполнение, но компилятор не жаловался, поэтому я решил подождать и посмотреть, работает ли он, а затем взглянуть на дизассемблирование. Segfault также возникает, когда я заменяю r0, r1, r2 на 3,4,5.   -  person Thomas    schedule 15.09.2010
comment
stepi не показывает мне инструкцию по сборке.   -  person Thomas    schedule 15.09.2010
comment
display/ni $pc отобразит следующие n инструкции для выполнения (кстати, все это есть в руководстве по GDB; вам действительно следует его прочитать).   -  person Stephen Canon    schedule 15.09.2010
comment
Спасибо. Это позволило мне выяснить, что программа вылетает при первых movaps: mov 0x8049170,%edx, movaps 0x30(%edx),%xmm0 -> SIGSEGV. Но почему? Выравнивание вроде в порядке.   -  person Thomas    schedule 15.09.2010


Ответы (2)


Вы загружаете данные в s[0] в %edx и используете их как указатель. Когда вы затем попытаетесь получить доступ к %edx + 0x30, произойдет сбой, потому что s[0] + 48 не отображается для вашего процесса для чтения. (В частности, поскольку s является глобальным и, следовательно, инициализируется всеми нулями, вы пытаетесь выполнить загрузку с адреса 0x30)

person Stephen Canon    schedule 15.09.2010
comment
Ой. Я хотел, чтобы mov edx, s загрузил адрес как немедленный. Я постараюсь найти правильную инструкцию или синтаксис... - person Thomas; 15.09.2010
comment
Вы, вероятно, хотите быть немного осторожным с s. Это глобальный символ, который может быть перемещен во время ссылки/загрузки. Сказав это, я никогда не беспокоился о встроенном ассемблере, так что я мог бы говорить чепуху. - person JeremyP; 15.09.2010
comment
Правильный синтаксис: offset s - и теперь он работает. Спасибо! - person Thomas; 15.09.2010
comment
О, это не так: Он печатает: 7.000000 10.500000 14.000000 0.000000 ... Где последнее значение? - person Thomas; 15.09.2010
comment
Решение: float -> volatile float - person Thomas; 15.09.2010
comment
@Thomas: вы должны использовать ввод/вывод директивы/списки засорения вместо объявления массива volatile. - person caf; 16.09.2010

Вы можете использовать stepi или si для пошагового выполнения отдельных машинных инструкций. Многие другие функции доступны с суффиксом -i, например nexti.

person Matt Joiner    schedule 15.09.2010
comment
Это то, что я пробовал, но я не вижу инструкции по сборке в gdb во время шага. Он выводит только последнюю закрывающую скобку ')' ассемблерного блока. - person Thomas; 15.09.2010