функция на асме сложения 2 массивов через mmx

Тема в разделе "WASM.BEGINNERS", создана пользователем vasilij, 6 дек 2009.

  1. vasilij

    vasilij New Member

    Публикаций:
    0
    Регистрация:
    6 дек 2009
    Сообщения:
    9
    Помогите пожалуйста разобраться. задача состоит в написании dll использовать 32 бита-это использовать 2 элемента? и сложить элементы массива по минимуму. Заранее спасибо.
    .586
    .XMM
    .MODEL FLAT
    PUBLIC _dMMX@12
    .CODE

    _dMMX@12 PROC
    push ebp
    mov ebp, esp
    mov ebx, [ebp+08h];результат сложения
    mov eax, [ebp+0ch] ;в eax - размер массивов
    mov esi, [ebp+10h] ;в esi - адрес массива left
    mov edi, [ebp+14h] ;в edi - адрес массива right
    the_loop:
    movq mm0, [esi] ;поместить в регистр mm0
    ;элемент массива left
    movq mm1, [edi] ;поместить в регистр mm1
    ;элемент массива right
    paddb mm0, mm1 ;сложить регистры mm0 и mm1
    add ebx, 8 ;следующие 4-ре элемента
    add esi, 8 ;следующие 4-ре элемента
    add edi, 8 ;следующие 4-ре элемента
    sub eax, 4 ;уменьшить значения счетчика
    jnz short the_loop ;конец цикла?
    emms

    pop ebp
    ret
    _dMMX@12 ENDP
     
  2. Rockphorr

    Rockphorr Well-Known Member

    Публикаций:
    0
    Регистрация:
    9 июн 2004
    Сообщения:
    2.622
    Адрес:
    Russia
    vasilij
    32 бита - это использовать 32 битные регистры
    на количество элементов это не влияет
     
  3. tyug

    tyug New Member

    Публикаций:
    0
    Регистрация:
    26 окт 2008
    Сообщения:
    19
    не понял для чего
    Код (Text):
    1. add ebx, 8
    и вообще если ebx используешь то надо-бы его сохранить
     
  4. vasilij

    vasilij New Member

    Публикаций:
    0
    Регистрация:
    6 дек 2009
    Сообщения:
    9
    так же бы хотелось разобраться вот с этим. Может я чего то недопонимаю но эта функция складывает у меня только начальные элементы а остальное выводит не понятно что!
    unsigned int matrix(unsigned int*rez,unsigned int*left,unsigned int*right,unsigned int n)
    {
    unsigned int e,f,h;
    e=int(&rez[0]);
    f=int(&left[0]);
    h=int(&right[0]);
    asm{
    mov ecx, [e]
    mov esi, [f]
    mov edi, [h]
    mov eax, [n]
    l1:
    movq mm0, [esi]
    movq mm1, [edi]
    paddb mm0, mm1
    movq [ecx],mm0
    inc esi
    inc edi
    inc ecx
    dec eax
    jnz l1

    emms
    }
    return *rez;
    }

    Вывод 30 элементов массива:
    -----all massive------
    0
    2
    4
    6
    8
    10
    12
    14
    16
    1074480402
    9403272
    9402620
    0
    536870912
    0
    9402496
    9402496
    284
    1073897101
    0
    0
    0
    0
    0
    1
    1074480507
    9402836
    9403020
    0
    536870912
    ----end all massive-------
    30
    Результат должен быть таким:
    -----all massive------
    0
    2
    4
    6
    8
    10
    12
    14
    16
    18
    20
    22
    24
    26
    28
    30
    32
    34
    36
    38
    40
    42
    44
    46
    48
    50
    52
    54
    56
    58
    ----end all massive-------
    30
     
  5. vasilij

    vasilij New Member

    Публикаций:
    0
    Регистрация:
    6 дек 2009
    Сообщения:
    9
    Так этот код нам дал препод.%-) у нас всего несколько лекций было. И я не особо понимаю в нем и сроки сдачи поджимают
     
  6. al79

    al79 Алексей

    Публикаций:
    0
    Регистрация:
    11 май 2006
    Сообщения:
    133
    Адрес:
    Екатеринбург
    А результат ни куда не сохраняется?
    Наверно надо добавить после сложения movq [ebx],mm0
    И что надо складывать байты, слова или двойные слова?
    В твоем случае складываются байты, а счетчик ты похоже уменьшаешь на количество слов.
     
  7. vasilij

    vasilij New Member

    Публикаций:
    0
    Регистрация:
    6 дек 2009
    Сообщения:
    9
    складывать надо содержимое элементов массива. Видимо надо складывать dword ptr. И разве он не по адресу сохраняет movq [ecx],mm0?
     
  8. vasilij

    vasilij New Member

    Публикаций:
    0
    Регистрация:
    6 дек 2009
    Сообщения:
    9
    Ассемблерная функция должна быть похожа на эту и использовать регистры mmx
    unsigned int matr(unsigned int n,unsigned int * rez,unsigned int *left,unsigned int *right)
    {
    unsigned int e;

    for (e=0;e<n;e++)
    {
    rez[e]=left[e]+right[e];
    }
    return *rez;

    }
     
  9. vasilij

    vasilij New Member

    Публикаций:
    0
    Регистрация:
    6 дек 2009
    Сообщения:
    9
    Все сделал.Спасибо al79! Осталось сделать сравнение по минимуму pfmin. Для элементов массива и поместить весь код в dll.
    mov ecx,dword ptr [e];
    mov esi,dword ptr [f];
    mov edi,dword ptr [h];
    mov eax,dword ptr [n];
    l1:
    movq mm0, [esi];
    movq mm1, [edi];
    paddb mm0, mm1;
    movq [ecx],dword ptr mm0;

    add esi,4;
    add edi,4;
    add ecx,4;
    dec eax;

    jnz short l1;

    emms;
     
  10. al79

    al79 Алексей

    Публикаций:
    0
    Регистрация:
    11 май 2006
    Сообщения:
    133
    Адрес:
    Екатеринбург
    Тогда наверно должно быть так:
    Код (Text):
    1.     mov ecx,dword ptr [e];  
    2.     mov esi,dword ptr [f];
    3.     mov edi,dword ptr [h];
    4.     mov eax,dword ptr [n];
    5.     l1:
    6.     movq   mm0, [esi];
    7.     movq   mm1, [edi];
    8.     [b]paddw[/b]  mm0, mm1;
    9.     [b]movq [ecx],mm0; [/b] Сохраняем все четыре слова
    10.    
    11.     [b]add esi,8;
    12.     add edi,8;
    13.     add ecx,8;  Смещение на 4 слова
    14.     sub eax,4;[/b] если в eax у тебя количество переменных то за раз мы складываем 4 слова
    15.  
    16.     [b]jnc short l1;[/b]  а здесь я думаю лучше сделать так, вдруг количество не кратно 4
    17.  
    18.     emms
     
  11. al79

    al79 Алексей

    Публикаций:
    0
    Регистрация:
    11 май 2006
    Сообщения:
    133
    Адрес:
    Екатеринбург
    Верните редактирование!!!

    mov ecx,dword ptr [e];
    mov esi,dword ptr [f];
    mov edi,dword ptr [h];
    mov eax,dword ptr [n];
    l1:
    movq mm0, [esi];
    movq mm1, [edi];
    paddw mm0, mm1; Складываем сразу четыре слова
    movq [ecx],mm0; Сохраняем все четыре слова

    add esi,8;
    add edi,8;
    add ecx,8; Смещение на 4 слова
    sub eax,4;
    если в eax у тебя количество переменных то за раз мы складываем 4 слова

    jnc short l1; а здесь я думаю лучше сделать так, вдруг количество не кратно 4

    emms
     
  12. vasilij

    vasilij New Member

    Публикаций:
    0
    Регистрация:
    6 дек 2009
    Сообщения:
    9
    Спасибо. Проверил на 1000 элементах выдает результат сходный с функцией на си.
    for(int i=0;i<n;i++)
    rez=left+right;
    //---------------------------
    mov eax,dword ptr [e]; //массив куда складываем левый и правый массивы
    mov esi,dword ptr [l];//массив левый
    mov edi,dword ptr [r];//массив правый
    mov ecx,dword ptr [n];//переменная определяющее количество элементов массива.
    l1:
    movq mm0, [esi];
    movq mm1, [edi];
    paddw mm0,mm1;
    movq [eax],dword ptr mm0;
    add esi,4;
    add edi,4;
    add eax,4;//а разве не 4?если я понял верно то это int и занимает 4?
    dec ecx;//здесь у меня число n (количество элементов массива).
    jnz short l1;

    emms;
     
  13. LiveM

    LiveM New Member

    Публикаций:
    0
    Регистрация:
    30 янв 2008
    Сообщения:
    4
    paddw складывает 16 битные числа
    paddd - 32

    в mmx регистре 64 бит, paddd за раз складывает два 32-х битных числа . Значит, указатели надо увеличивать на 8, а счетчик уменьшать на 2.
     
  14. al79

    al79 Алексей

    Публикаций:
    0
    Регистрация:
    11 май 2006
    Сообщения:
    133
    Адрес:
    Екатеринбург
    А я думал, что это unsigned long int DWORD занимает 4 байта.
    А вообще меня ставит в тупик вот эта команда: movq [eax],dword ptr mm0
    Неужели она еще и копилируется?
     
  15. vasilij

    vasilij New Member

    Публикаций:
    0
    Регистрация:
    6 дек 2009
    Сообщения:
    9
    компилируется. Я этот код вытащил при компиляции с параметром -S для с++ builder, на других компиляторах не проверял.
    А если входящие массивы имеют тип char?
    rez= (char*)malloc(n*sizeof(char));
    left= (char*)malloc(n*sizeof(chart));
    right= (char*)malloc(n*sizeof(char));
     
  16. cppasm

    cppasm New Member

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    923
    Есть больште сомнения. И нафига там dword ptr, если он даже не при обращении к памяти стоит?
    И что?
     
  17. al79

    al79 Алексей

    Публикаций:
    0
    Регистрация:
    11 май 2006
    Сообщения:
    133
    Адрес:
    Екатеринбург
    Наверно будет так:
    mov eax,dword ptr [e]; //массив куда складываем левый и правый массивы
    mov edx,dword ptr [l];//массив левый
    mov edi,dword ptr [r];//массив правый
    mov ecx,dword ptr [n];//переменная определяющее количество элементов массива.
    l1:
    movq mm0, [edx];
    paddb mm0,[edi]; - это для CHAR
    paddw mm0,[edi]; - это для INT
    paddd mm0,[edi]; - это для LONG INT

    movq [eax],mm0;
    add edx,8;
    add edi,8;
    add eax,8; смещение делаем 8, MMX регистр 8 байт!!!!!!
    sub ecx,8; - это для CHAR
    sub ecx,4; - это для INT
    sub ecx,2; - это для LONG INT

    jc l2; это так перестраховаться
    jnz short l1;
    l2:
    emms;
     
  18. vasilij

    vasilij New Member

    Публикаций:
    0
    Регистрация:
    6 дек 2009
    Сообщения:
    9
    Спасибо разобрался. тему можно закрывать