2013-11-08 5 views
2

В моем университете мы только что познакомились с IA32 SSE. То, что я пытаюсь сделать, это добавить два вектора (они называют это «упакованным значением», это означает, что вектор содержит четыре 32-битных числа с плавающей запятой с одинарной точностью. Размер одного из них составляет 128 бит.) Вот что я пытаюсь делать:Выполнение простой арифметической операции с использованием SSE (сборка IA32)

%xmm0  | 5.5 | 1.2 | 2.4 | 7.0 | 
%xmm1  | 3.0 | 1.5 | 3.5 | 2.2 | 
       |  |  |  | 
       +  +  +  + 
       |  |  |  | 
       V  V  V  V 
%xmm0  | 8.5 | 2.7 | 5.9 | 9.2 | 

Однако на слайдах они только показывают, следующий фрагмент кода, который я просто не попасть на работу:

# %eax and %ebx contain the addresses of the two vectors that are to be added 
movups (%eax), %xmm0 
movups (%ebx), %xmm1 
addps %xmm1, %xmm0 
movups %xmm0, result 

Возникают два вопроса:

1 Как я даже создаю эти векторы в первую очередь и h Должен ли я сделать% eax и% ebx указать на них?

2. Как распечатать результат, чтобы проверить, была ли операция успешной или нет?

Вот что я пробовал. Следующий код компилируется и не сбой при запуске. Тем не менее, нет никакого вывода вообще ...:/

.data 
    x0: .float 7.0 
    x1: .float 2.4 
    x2: .float 1.2 
    x3: .float 5.5 
    y0: .float 2.2 
    y1: .float 3.5 
    y2: .float 1.5 
    y3: .float 3.0 
    result: .float 0 
    intout: .string "Result: %f.\n" 

.text 
.global main 

main: 
    pushl x3 
    pushl x2 
    pushl x1 
    pushl x0 
    movl %esp, %eax 
    pushl y3 
    pushl y2 
    pushl y1 
    pushl y0 
    movl %esp, %ebx 

    movups (%eax), %xmm0 
    movups (%ebx), %xmm1 
    addps %xmm1, %xmm0 
    movups %xmm0, result 

    pushl result 
    pushl $intout 
    call printf 
    addl $40, %esp 
    movl $1, %eax 
    int $0x80 
+2

'movups% XMM0, result' напишут все 128 бит' xmm0' в 'result', но вы объявили' result' как 'float' (32 бит), поэтому он будет перезаписывать части строки 'intout'. – Michael

+1

Ваш результат должен быть достаточно длинным, чтобы содержать 4 значения, теперь 'movups% xmm0, result' также разрушает вашу строку. –

+0

Спасибо за ваш быстрый ответ! Как объявить «результат» таким образом, чтобы он составлял 128 бит? – lambdarookie

ответ

1

%f спецификатор для printf указывает двойной, а не аргумент float. Таким образом, вам нужно скрывать одиночные поплавки в вашем векторе результата и переместить их в стек. Это, как я хотел бы сделать что:

.section ".rodata" 
fmt: .string "%f %f %f %f\n" 
     .align 16 
vec1: 
     .float 7.0 
     .float 2.4 
     .float 1.2 
     .float 5.5 
vec2: 
     .float 2.2 
     .float 3.5 
     .float 1.5 
     .float 3.0  

.data 
     .align 16 
result: 
     .float 0.0 
     .float 0.0 
     .float 0.0 
     .float 0.0 

     .text 
.globl main 
main: 
     movl %esp, %ebp 

     andl $-16, %esp  # align stack 

     movaps vec1, %xmm0 
     movaps vec2, %xmm1 
     addps %xmm1, %xmm0 
     movaps %xmm0, result 

     subl $36, %esp 
     movl $fmt, (%esp) 
     movss result, %xmm0 
     cvtss2sd %xmm0, %xmm0 
     movsd %xmm0, 4(%esp) 
     movss result+4, %xmm0 
     cvtss2sd %xmm0, %xmm0 
     movsd %xmm0, 12(%esp) 
     movss result+8, %xmm0 
     cvtss2sd %xmm0, %xmm0 
     movsd %xmm0, 20(%esp) 
     movss result+12, %xmm0 
     cvtss2sd %xmm0, %xmm0 
     movsd %xmm0, 28(%esp) 
     call printf 
     addl $36, %esp 

     xorl %eax, %eax 
     movl %ebp, %esp 
     ret 
+0

Спасибо, это работает для меня! Я понимаю, что, поскольку '% f' ожидает числа с плавающей запятой с двойной точностью, мы должны выполнить преобразование. Тем не менее, не существует ли подстановочный знак, который ожидает единственную точность? Это сделало бы все это намного проще! – lambdarookie

+0

Это действительно так, но такого спецификатора нет.Обратите внимание, что C будет прозрачно выполнять преобразование, поэтому ни одна из неуклюжих не видна с уровня, на котором предполагается использовать 'printf'. – gsg

2

Вы, кажется, следует путать о том, как объявить метку на несколько элементов данных, и как загрузить метку в регистр. Метка - это просто адрес - точка в памяти - без какого-либо размера или чего-то еще, связанного с ней. Вещи после метки находятся в последовательных адресах в памяти. Таким образом, вы объявляете ярлык со ссылкой на вектор как:

x: 
    .float 7.0 
    .float 2.4 
    .float 1.2 
    .float 5.5 

Теперь вы можете загрузить этот адрес в регистр с простым движением, а затем использовать регистр для загрузки вектора:

movl $x, %eax 
    movups (%eax), %xmm0 

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

movups x, %xmm0 
+0

Большое вам спасибо, Крис! Однако у меня осталось два вопроса: не нужно ли «leal x,% eax»? Мы хотим, чтобы '% eax' удерживал адрес x, а не значение, которое должно быть найдено там, правильно? А во-вторых, как я могу напечатать свои результаты, чтобы убедиться, что он сработал? – lambdarookie

+0

@baerenfaenger: Да, вам нужно '' ', чтобы получить значение метки как немедленное (а не загрузку с метки), которое я изначально опечалил (важная опечатка). Или вы можете использовать 'leal'. –

Смежные вопросы