GCC Inline Assembler

Модератор: Модераторы разделов

BratSinot
Сообщения: 812
ОС: Slackware64

GCC Inline Assembler

Сообщение BratSinot »

Доброго времени суток!

Вообщем сразу к делу, вот код:

Код: Выделить всё

int main(void)
{
 double a = 300.0;
 double b = 1.5;

 asm volatile ("mulpd %[a], %[b]\n"
      :
      : [b] "r" (b), [a] "r" (a)
      : "xmm0", "xmm1"
     );


 printf("%f", a);

 return 0;
};

Этот "нехороший человек" игнорирует третий ":", и использует регистры по усмотрению(в моем случае это были rax и rbx, что соответственно не вяжется с инструкцией mulpd). Как его заставить использовать регистры, которые я указал?
P.S. На всякий пожарный, использую Intel синтаксис, т.е. при компиляции указываю -masm=intel
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: GCC Inline Assembler

Сообщение NickLion »

Предлагаю следующий "workaround":

Код: Выделить всё

#include <stdio.h>
int main(void)
{
        double a = 300.0;
        double b = 1.5;

        asm volatile (
                "movsd xmm0, %[a]\n"
                "movsd xmm1, %[b]\n"
                "mulpd %%xmm0, %%xmm1\n"
                "movsd %[c], xmm0\n"
                : [c] "m" (a)
                : [b] "m" (b), [a] "m" (a)
                : "xmm0", "xmm1"
        );

        printf("%lf", a);

        return 0;
}


PS и да, третий параметр не имеет отношения к входным/выходным аргументам, он показывает какие регистры будут испорчены. А в качестве входных/выходных регистров наверное xmm# не работают, поэтому вручную вот так :)
Спасибо сказали:
BratSinot
Сообщения: 812
ОС: Slackware64

Re: GCC Inline Assembler

Сообщение BratSinot »

NickLion писал(а):
31.10.2011 09:37
Предлагаю следующий "workaround":

Код: Выделить всё

#include <stdio.h>
int main(void)
{
        double a = 300.0;
        double b = 1.5;

        asm volatile (
                "movsd xmm0, %[a]\n"
                "movsd xmm1, %[b]\n"
                "mulpd %%xmm0, %%xmm1\n"
                "movsd %[a], xmm0\n"
                :
                : [b] "m" (b), [a] "m" (a)
                : "xmm0", "xmm1"
        );

        printf("%lf", a);

        return 0;
}

Ну я так изначально и делал, только получается вместо одной инструкции миллион(из памяти в регистры, из регистров в память и перед printf он опять в регистры запихает).
P.S. Только в следующий раз про AT&T синтаксис предупреждайте, а то я сейчас сидел и голову ломал, чой это прога не работает =)

PS и да, третий параметр не имеет отношения к входным/выходным аргументам, он показывает какие регистры будут испорчены. А в качестве входных/выходных регистров наверное xmm# не работают, поэтому вручную вот так :)

И что, ему нельзя указать чтобы он сразу "xmm?" использовал? Так это бред же получается...
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: GCC Inline Assembler

Сообщение NickLion »

// с тремя параметрами я загнул, надо в outputs [a] "+m" (a) - и тогда он и входной и выходной будет, так логичнее

BratSinot писал(а):
31.10.2011 09:56
Ну я так изначально и делал, только получается вместо одной инструкции миллион(из памяти в регистры, из регистров в память и перед printf он опять в регистры запихает).

А что делать, он же не знает, что оно уже готовое в xmm0 лежит?

BratSinot писал(а):
31.10.2011 09:56
И что, ему нельзя указать чтобы он сразу "xmm?" использовал? Так это бред же получается...

Статьи говорят, что r для этого не приспособлен, но f тоже не получлось применить... Может для sse2 что и придумали, не знаю, пока не увидел.
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: GCC Inline Assembler

Сообщение NickLion »

Код: Выделить всё

#include <stdio.h>
int main(void)
{
    double a = 300.0;
    double b = 1.5;

    asm volatile (
        "mulpd %[a], %[b]\n"
        : [a] "+x" (a)
        : [b] "x" (b)
    );

    printf("%lf\n", a);
    return 0;
}

Похоже, что так.
Спасибо сказали:
BratSinot
Сообщения: 812
ОС: Slackware64

Re: GCC Inline Assembler

Сообщение BratSinot »

А "x" и "+x" это что?
P.S. Кстати, выше по постам, вы написали

Код: Выделить всё

: [c] "m" (a)
: [b] "m" (b), [a] "m" (a)
: "xmm0", "xmm1"

А надо

Код: Выделить всё

: [c] "=m" (a)
: [b] "m" (b), [a] "m" (a)
: "xmm0", "xmm1"


Кстати, попутно вопрос, чтоб тему новую не создавать, вот такая строчка:

Код: Выделить всё

and rbx, 9223372036854775807

Не работает, пишет:
Error: operand type mismatch for 'and'

Хотя если написать так, то все заработает:

Код: Выделить всё

mov r8, 9223372036854775807
and rbx, r8
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: GCC Inline Assembler

Сообщение NickLion »

BratSinot писал(а):
31.10.2011 10:47
А "x" и "+x" это что?

x - это использование xmm# регистров (r - это только основные регистры)
+ - признак того, что output регистр является и input заодно (чтобы дважды не писать с разными именами)

BratSinot писал(а):
31.10.2011 10:47
P.S. Кстати, выше по постам, вы написали

Код: Выделить всё

: [c] "m" (a)
: [b] "m" (b), [a] "m" (a)
: "xmm0", "xmm1"

А надо

Код: Выделить всё

: [c] "=m" (a)
: [b] "m" (b), [a] "m" (a)
: "xmm0", "xmm1"

Да, ошибся, когда менял. Но лучше через "+".

BratSinot писал(а):
31.10.2011 10:47
Кстати, попутно вопрос, чтоб тему новую не создавать, вот такая строчка:
...skipped...

Да, это известное ограничение платформы x86_64. Использование 64-х битных констант ограничено командой mov.
Спасибо сказали:
BratSinot
Сообщения: 812
ОС: Slackware64

Re: GCC Inline Assembler

Сообщение BratSinot »

NickLion писал(а):
31.10.2011 11:22
BratSinot писал(а):
31.10.2011 10:47
Кстати, попутно вопрос, чтоб тему новую не создавать, вот такая строчка:
...skipped...

Да, это известное ограничение платформы x86_64. Использование 64-х битных констант ограничено командой mov.

А что тогда можно с этим сделать?
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: GCC Inline Assembler

Сообщение NickLion »

BratSinot писал(а):
31.10.2011 13:19
А что тогда можно с этим сделать?

1. Использовать "переменные".
2. Использовать mov+команда.

PS не забываем, что ограничение касается только 64-х битных чисел, а константы такого размера бывают нужны редко, было решено, что чем городить ещё по одной версии каждой команды для работы с 64-битными константами и усложнять процессор, лучше будет сделать так.
Спасибо сказали:
BratSinot
Сообщения: 812
ОС: Slackware64

Re: GCC Inline Assembler

Сообщение BratSinot »

NickLion писал(а):
31.10.2011 14:17
BratSinot писал(а):
31.10.2011 13:19
А что тогда можно с этим сделать?

1. Использовать "переменные".
2. Использовать mov+команда.

PS не забываем, что ограничение касается только 64-х битных чисел, а константы такого размера бывают нужны редко, было решено, что чем городить ещё по одной версии каждой команды для работы с 64-битными константами и усложнять процессор, лучше будет сделать так.

Так стоять, Intel сократила АЛУ до 16-бит(с 32-х) в Pentium 4, когда они успели его до 32-х поднять?
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: GCC Inline Assembler

Сообщение NickLion »

BratSinot писал(а):
31.10.2011 20:03
Так стоять, Intel сократила АЛУ до 16-бит(с 32-х) в Pentium 4, когда они успели его до 32-х поднять?

А при чём тут разрядность АЛУ - программист хоть и даже и на ассемблере прямого доступа к АЛУ x86 не имеет. А 32-х битные константы всегда были и будут. Просто на 16-битном АЛУ чуть менее эффективно считаются.

PS и да, вроде у Northwood были и 16-ти и 32-ти битные АЛУ, потом и те убрали? я просто не следил
Спасибо сказали: