Форум программистов, компьютерный форум, киберфорум
С++ под Linux
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.73/40: Рейтинг темы: голосов - 40, средняя оценка - 4.73
0 / 0 / 0
Регистрация: 27.06.2010
Сообщений: 49
1

C++ и ассемблерная вставка

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

Всем доброго времени суток.

Необходимо было написать программу, которая складывает попарно числа из 2х массивов обычным способом и с помощью ассемблерной вставки с использованием технологии mmx. Всё казалось бы просто, но я столкнулся с проблемой при компиляции. Вот код самой программы:
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <stdio.h> 
#include <stdlib.h> 
#include <time.h>
 
int main(){
  int frst_arr[100],scnd_arr[100],res_arr_cpp[100],res_arr_asm[100]; 
  
  clock_t start, end;
  srand(time(0));//заполняю массивы случайными числами
  for(int i=0;i<=99;++i){
    frst_arr[i] = rand() % 10001 - 5000;
    scnd_arr[i] = rand() % 10001 - 5000;
  }
  
  //обычный способ суммирования
  
  start = clock(); 
  for(long int j=0;j<=9999999;++j)//этот цикл необходим, что бы лучше было видно какой способ работает быстрее
    for(int i=0;i<=99;++i)
      res_arr_cpp[i]=frst_arr[i]+scnd_arr[i];
  end = clock();
  float time_cpp = (end - start);
  time_cpp = time_cpp / 1000000;
  printf("%f seconds\n",time_cpp);
  
  //mmx
  
  asm(
      "xor %eax,%eax;"
    "s:cmp %eax,10000000;"
      "je e;"
      "xor %ecx,%ecx;"
    "l:movq %mm0,frst_arr[ecx*8];"
      "movq %mm1,scnd_arr[ecx*8];"
      "paddq %mm0,%mm1;"
      "movq res_arr_asm[ecx*8],%mm0;"
      "inc %ecx;"
      "cmp %ecx,51;"
      "jne l;"
      "inc %eax;"
      "jmp s;"
    "e:emms;"
  );
    
  for(int i=0;i<=99;++i)
    printf("%d %d\n",res_arr_cpp[i],res_arr_asm[i]);
}
А вот что мне "отвечает" компилятор:
Bash
1
2
3
4
5
xxxx@xxxxxxxx:~$ g++ workspace/laba1.cpp -o workspace/zar
workspace/laba1.cpp: Assembler messages:
workspace/laba1.cpp:43: Error: junk `[ecx*8]' after expression
workspace/laba1.cpp:43: Error: junk `[ecx*8]' after expression
workspace/laba1.cpp:43: Error: junk `[ecx*8]' after expression
Подскажите пожалуйста в чем косяк.
__________________
Помощь в написании контрольных, курсовых и дипломных работ здесь
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
16.09.2012, 16:16
Ответы с готовыми решениями:

Не работает ассемблерная вставка
Здравствуйте. Захотелось мне как-то отловить переполнения, возникающие во время выполнения...

Ассемблерная вставка
Товарищи!! кто знает, подскажите как сделать ассемблерную вставку в cи-проекте в среде Turbo C??...

С++ и Ассемблерная вставка/чтение SPD ОЗУ
Добрый день форумчане, делаю программу на подобии CPU-Z, необходимо узнать тайминги и прочую...

Ассемблерная вставка
Всем доброй ночи!!! Я хочу попросить помощи в решении вот такой функции: Найти целое значение...

14
538 / 398 / 99
Регистрация: 18.08.2012
Сообщений: 1,024
16.09.2012, 17:35 2
Ошибся адресом
0
0 / 0 / 0
Регистрация: 27.06.2010
Сообщений: 49
16.09.2012, 17:41  [ТС] 3
Цитата Сообщение от Dmitrinik Посмотреть сообщение
Вот таким образом [ecx*8] процессор не умеет вычислять адреса. Нужно делать add %ecx,<размер элемента массива>
я на самом деле об этом знал, но если даже оставить [ecx], то всё равно выходит ошибка
Bash
1
2
3
workspace/laba1.cpp:43: Error: junk `[ecx]' after expression
workspace/laba1.cpp:43: Error: junk `[ecx]' after expression
workspace/laba1.cpp:43: Error: junk `[ecx]' after expression
0
4085 / 1799 / 211
Регистрация: 06.10.2010
Сообщений: 4,030
17.09.2012, 13:12 4
[frst_arr+ecx*8]
0
538 / 398 / 99
Регистрация: 18.08.2012
Сообщений: 1,024
17.09.2012, 15:42 5
Во-первых извиняюсь за сообщение о невозможности адресации вида [ecx*8].
Во-вторых, вот этот код не дает ошибок. Правда, в "Сервис>Параметры>Добавить следующие команды в запуск компилятора" я вставил -masm=intel. Еще описание переменных я вынес над int main(), а в самой ассемблерной вставке их имена надо предварять символом "_" (подчеркивание).

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <stdio.h> 
#include <stdlib.h> 
#include <time.h>
int frst_arr[100],scnd_arr[100],res_arr_cpp[100],res_arr_asm[100]; 
int main()
{
//  int frst_arr[100],scnd_arr[100],res_arr_cpp[100],res_arr_asm[100]; 
  
  clock_t start, end;
  srand(time(0));//заполняю массивы случайными числами
  for(int i=0;i<=99;++i)
  {
    frst_arr[i] = rand() % 10001 - 5000;
    scnd_arr[i] = rand() % 10001 - 5000;
  }
  
  
  //обычный способ суммирования
  
  start = clock(); 
  for(long int j=0;j<=9999999;++j)//этот цикл необходим, что бы лучше было видно какой способ работает быстрее
    for(int i=0;i<=99;++i)
      res_arr_cpp[i]=frst_arr[i]+scnd_arr[i];
  end = clock();
  float time_cpp = (end - start);
  time_cpp = time_cpp / 1000000;
  printf("%f seconds\n",time_cpp);
  //mmx
  
  __asm(
      "xor %eax,%eax;"
    "s:"
      "cmp %eax,10000000;"
      "je e;"
      "xor %ecx,%ecx;"
    "l:"
      "movq %mm0,_frst_arr[ecx*8];"
      "movq %mm1,_scnd_arr[ecx*8];"
      "paddq %mm0,%mm1;"
      "movq _res_arr_asm[ecx*8],%mm0;"
      "inc %ecx;"
      "cmp %ecx,51;"
      "jne l;"
      "inc %eax;"
      "jmp s;"
    "e:emms;"
  );
 
    
  for(int i=0;i<=99;++i)
    printf("%d %d\n",res_arr_cpp[i],res_arr_asm[i]);
}
0
337 / 4 / 1
Регистрация: 29.11.2011
Сообщений: 39
17.09.2012, 15:51 6
оригинальный at&t синтаксис выглядит так
Assembler
1
2
3
asm(
    "l: movq %mm0,frst_arr(, %ecx, 8) \n\t"
  );
вот так нормально будет с точки зрения синтаксиса, но линкер такой код не пропустит через себя, потому что frst_arr у тебя локальная переменная, то есть по сути такого имени в программе нет, только в уме компилятора. Поэтому нужно переписать полностью вставку в соответствии с синтаксисом extended asm'a, или делать переменные глобальными
2
0 / 0 / 0
Регистрация: 27.06.2010
Сообщений: 49
17.09.2012, 22:39  [ТС] 7
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <stdio.h> 
#include <stdlib.h> 
#include <time.h>
#include "TPerfMeter.h"
 
int main(){
  int frst_arr[100],scnd_arr[100],res_arr_cpp[100],res_arr_asm[100];
  double t;
  TPerfMeter m;
 
  srand(time(0));
  for(int i=0;i<=99;++i){
    frst_arr[i] = rand() % 5001;
    scnd_arr[i] = rand() % 5001;
  }
  
  //обычный способ сумирования
  
  m.Start();
  for(long int j=0;j<=9999999;++j)
    for(int i=0;i<=99;++i)
      res_arr_cpp[i]=frst_arr[i]+scnd_arr[i];
  t = m.Stop();
  printf("Time: %f ms\n",t);  
    
  //mmx
  
  m.Start();
  for(long int j=0;j<=9999999;++j){
    _asm{
            lea ebx,frst_arr
            lea esi,scnd_arr
            lea edi,res_arr_asm
            mov eax,0
          l:MOVQ mm0,word ptr [ebx]
            PADDD mm0,word ptr [esi]
            MOVQ word ptr [edi],mm0
            add ebx,8
            add esi,8
            add edi,8
            inc eax
            cmp eax,50
            jne l
            emms
       
    }
  }
  t = m.Stop();
  printf("Time: %f ms\n\n",t);  
 
  for(int i=0;i<=99;++i)
    printf("%d) %d %d\n",i+1,res_arr_cpp[i],res_arr_asm[i]);
}
решил не взрывать себе мозг и в visual studio сделал так. всё работает как надо
0
337 / 4 / 1
Регистрация: 29.11.2011
Сообщений: 39
18.09.2012, 15:50 8
Цитата Сообщение от Armind Посмотреть сообщение
mov eax,0
Цитата Сообщение от Armind Посмотреть сообщение
inc eax
cmp eax,50
jne l
Assembler
1
2
mov $50, %ecx
loop l
0
0 / 0 / 0
Регистрация: 27.06.2010
Сообщений: 49
18.09.2012, 18:43  [ТС] 9
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
asm(
         "lea frst_arr,%ebx;"
         "lea scnd_arr,%esi;"
         "lea res_arr_asm,%edi;"
         "mov $0,%eax;"
       "l:MOVQ (%ebx),%mm0;"
         "PADDD (%esi),%mm0;"
         "MOVQ %mm0,(%edi);"
         "add $8,%ebx;"
         "add $8,%esi;"
         "add $8,%edi;"
         "inc %eax;"
         "cmp $50,%eax;"
         "jne l;"
         "emms;"
    );
полностью рабочее с AT&T синтаксисом
0
337 / 4 / 1
Регистрация: 29.11.2011
Сообщений: 39
18.09.2012, 19:31 10
нет, не рабочее

Добавлено через 14 минут
с вариантом программы из стартового сообщения это ошибка линковки, как уже было сказано ранее, но даже если сделать переменные глобальными, то всё равно есть ещё одна серьёзная проблема. В extended asm'e есть clobbered list во вставке, затираемые регистры, компилятор например может положить в eax какую-нибудь переменную и работать с ней, когда он встретит правильную асм вставку, в которой указано, что еах затирается, то он после неё снова загрузит переменную в еах, а если он встретит твою вставку, то он будет работать с еах так, будто там до сих лежит его переменная, хотя это уже и неправда, так работает gcc

и после слова асм нужно добавить volatile
0
0 / 0 / 0
Регистрация: 27.06.2010
Сообщений: 49
18.09.2012, 19:41  [ТС] 11
Цитата Сообщение от Super-Windоws Посмотреть сообщение
нет, не рабочее

Добавлено через 14 минут
с вариантом программы из стартового сообщения это ошибка линковки, как уже было сказано ранее, но даже если сделать переменные глобальными, то всё равно есть ещё одна серьёзная проблема. В extended asm'e есть clobbered list во вставке, затираемые регистры, компилятор например может положить в eax какую-нибудь переменную и работать с ней, когда он встретит правильную асм вставку, в которой указано, что еах затирается, то он после неё снова загрузит переменную в еах, а если он встретит твою вставку, то он будет работать с еах так, будто там до сих лежит его переменная, хотя это уже и неправда, так работает gcc

и после слова асм нужно добавить volatile
ога не рабочее) запускаю компилятор, компилирует, запускаю программу и выходят ожидаемые результаты)
0
337 / 4 / 1
Регистрация: 29.11.2011
Сообщений: 39
18.09.2012, 20:20 12
Цитата Сообщение от Armind Посмотреть сообщение
ога не рабочее) запускаю компилятор, компилирует, запускаю программу и выходят ожидаемые результаты)
а я компилирую, не компилируется, запускаю и вылазит синий экран. Работоспособность твоей программы целиком зависит от опций компилятора, его версии и настроения. Программа, работающая через раз хуже просто неработающей программы. Если не веришь можешь выложить свой код на более компетентный сайт, например stackoverflow и спросить какие проблемы есть в этом коде и тебе ответят тоже самое что и я выше, только по английски
0
0 / 0 / 0
Регистрация: 27.06.2010
Сообщений: 49
18.09.2012, 22:22  [ТС] 13
Bash
1
2
3
xxxxx@xxxxxxxxxx:~$ g++ --version
g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
Copyright (C) 2011 Free Software Foundation, Inc.
и про какой синий экран речь идёт? вы компилируете, у вас может или скомпилироваться или нет, выдав ошибки. или я чего-то не знаю/не понимаю
0
337 / 4 / 1
Регистрация: 29.11.2011
Сообщений: 39
19.09.2012, 14:16 14
мне не нужен компилятор, ведь и так видно что здесь ошибки линковки будут, символы frst_arr[100],scnd_arr[100],res_arr_cpp[100],res_arr_asm[100] не определены, они выделяются на стеке и недоступны из твоей ассемблерной вставки по имени, и уж тем более эта программа не могла запуститься, как ты говоришь. Это первая ошибка, и вторую я уже озвучивал изменение регистров посреди сишного кода, без уведомления об этом компилятора, соответственно программа может работать правильно, а может и нет, это уж как бог на душу положит. Обе проблемы решаются использованием расширенного ассемблера, вторую можно ещё решить вынесением вставки в отдельную процедуру
0
Evg
Эксперт CАвтор FAQ
21204 / 8220 / 633
Регистрация: 30.03.2009
Сообщений: 22,542
Записей в блоге: 30
25.09.2012, 22:45 15
Цитата Сообщение от Super-Windоws Посмотреть сообщение
вот так нормально будет с точки зрения синтаксиса
В gnu'шных вставках использовать регистры напрямую - плохой стиль. Ну а если всё-таки их использовать, то надо в обязательном порядке их в clobber'ах указывать. А то есть хороший шанс, что компилятор сгенерит неправильный код
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
25.09.2012, 22:45

Ассемблерная вставка на С++
Написал сегодня код. int x, y; //Исходные числа float res = 0; //Результат расчетов cin &gt;&gt; x...

Ассемблерная Вставка
Добрый день. начал изучать ассемблер(начал со вставок, на этом основание пишу здесь). Должен был...

Ассемблерная вставка в с++
С помощью логических операций реализуйте запись битов в данной ячейки памяти, размером в 2 байта, в...

Ассемблерная вставка
#include &lt;iostream&gt; #include &lt;cstdlib&gt; using namespace std; int main() { int x, y; cout &lt;&lt;...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.