asm вставки в си

Тема в разделе "LANGS.C", создана пользователем DeFuckTo, 27 апр 2007.

  1. DeFuckTo

    DeFuckTo New Member

    Публикаций:
    0
    Регистрация:
    8 мар 2007
    Сообщения:
    8
    Имеет ли смысл перевод на asm тела функци,а затем его ассемблерная вставка?
    Код (Text):
    1. unsigned long LFSR1()
    2. {
    3. for(int i = 0; i < 32; i++)
    4. {
    5. unsigned long int ret = 0;
    6. SReg1 = ((((SReg1 >> 31)
    7. ^ (SReg1 >> 6)
    8. ^ (SReg1 >> 4)
    9. ^ (SReg1 >> 2)
    10. ^ (SReg1 >> 1)
    11. ^ SReg1)
    12. & 0x00000001) <<31)
    13. | (SReg1 >> 1);
    14. ret <<= 1;
    15. ret |= (SReg1 & 0x00000001);
    16. }
    17. return ret;
    18. }
    Код (Text):
    1. unsigned long LFSR1()
    2. {
    3. unsigned long int ret = 0;
    4. asm
    5. {
    6. ...
    7. ...
    8. ...
    9. }
    10.  return rt;
    11. }
     
  2. Stub

    Stub New Member

    Публикаций:
    0
    Регистрация:
    11 май 2004
    Сообщения:
    311
    Адрес:
    Siberia
    Если ты уверен, что сможешь написать более эффективный (исходя из потребностей: скорость, размер и т.д.) код, чем его сгенерирует компилятор, то ответ - имеет.
     
  3. nobody

    nobody New Member

    Публикаций:
    0
    Регистрация:
    8 сен 2004
    Сообщения:
    32
    Адрес:
    Afghanistan
    А не правильнее будет так:
    SReg1 = ((((SReg1 & (1 << 31))
    ^ (SReg1 & (1 << 6))
    ^ (SReg1 & (1 << 4))
    ^ (SReg1 & (1 << 2))
    ^ (SReg1 & (1 << 1))
    ^ SReg1)
    ?
     
  4. DeFuckTo

    DeFuckTo New Member

    Публикаций:
    0
    Регистрация:
    8 мар 2007
    Сообщения:
    8
    Я из книжки код выдрал, там было именно так как у меня в посте...
     
  5. Ustus

    Ustus New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2005
    Сообщения:
    834
    Адрес:
    Харьков
    Вот такую фиговину сделал MSVC++ 7.0
    Код (Text):
    1. ?LFSR1@@YAKXZ PROC NEAR                 ; LFSR1, COMDAT
    2.  
    3. ; 6    :     unsigned long int ret = 0;
    4.  
    5.     mov ecx, DWORD PTR ?SReg1@@3IA      ; SReg1
    6.     xor eax, eax
    7.     mov edx, 32                 ; 00000020H
    8.     push    esi
    9.  
    10. ; 19   :     }
    11. ; 20   :     return ret;
    12. ; 21   : }
    13.  
    14.     npad    2
    15.  
    16. ; 6    :     unsigned long int ret = 0;
    17.  
    18. $L274:
    19.  
    20. ; 7    :     for(int i = 0; i < 32; i++)
    21. ; 8    :     {
    22. ; 9    :         SReg1 = ((((SReg1 >> 31)
    23. ; 10   :             ^ (SReg1 >> 6)
    24. ; 11   :             ^ (SReg1 >> 4)
    25. ; 12   :             ^ (SReg1 >> 2)
    26. ; 13   :             ^ (SReg1 >> 1)
    27. ; 14   :             ^ SReg1)
    28. ; 15   :             & 0x00000001) <<31)
    29. ; 16   :             | (SReg1 >> 1);
    30.  
    31.     lea esi, DWORD PTR [ecx+ecx]
    32.     xor esi, ecx
    33.     shl esi, 1
    34.     xor esi, ecx
    35.     shl esi, 2
    36.     xor esi, ecx
    37.     shl esi, 2
    38.     xor esi, ecx
    39.     shl esi, 25                 ; 00000019H
    40.     xor esi, ecx
    41.     and esi, -2147483648            ; 80000000H
    42.     shr ecx, 1
    43.     or  ecx, esi
    44.  
    45. ; 17   :         ret <<= 1;
    46. ; 18   :         ret |= (SReg1 & 0x00000001);
    47.  
    48.     mov esi, ecx
    49.     and esi, 1
    50.     add eax, eax
    51.     or  eax, esi
    52.     dec edx
    53.     jne SHORT $L274
    54.     mov DWORD PTR ?SReg1@@3IA, ecx      ; SReg1
    55.     pop esi
    56.  
    57. ; 19   :     }
    58. ; 20   :     return ret;
    59. ; 21   : }
    60.  
    61.     ret 0
    62. ?LFSR1@@YAKXZ ENDP                  ; LFSR1
    На моем рабочем эстоооонском прескотте :) выполняется в темпе <20 тактов на одну итерацию. Кто сможет быстрее? :)
     
  6. DeFuckTo

    DeFuckTo New Member

    Публикаций:
    0
    Регистрация:
    8 мар 2007
    Сообщения:
    8
    хоть у меня уже есть код на asm, но все равно премного благодарен….
     
  7. asmfan

    asmfan New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2006
    Сообщения:
    1.004
    Адрес:
    Abaddon
    DeFuckTo
    Компилятору или Ustus'у?))
     
  8. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Ustus
    Если пошевелить мозгами, а не повторять выдранный из книжки код, то можно сделать покороче и побыстрее ;)
    Код (Text):
    1. ;SReg1 = ((((SReg1 >> 31)
    2. ;^ (SReg1 >> 6)
    3. ;^ (SReg1 >> 4)
    4. ;^ (SReg1 >> 2)
    5. ;^ (SReg1 >> 1)
    6. ;^ SReg1)
    7. ;& 0x00000001) <<31)
    8. ;| (SReg1 >> 1);
    9. ;--------------------
    10. mov ecx,SReg1
    11. mov eax,ecx
    12. rol ecx,1         ;собираем все биты для xor в младший байт
    13. and ecx,10101111b
    14. setp cl           ;cl = 1 если число единиц четное, т.е. серия xor = 0
    15. sub cl,1         ;перенос, если серия xor = 1
    16. rcr eax,1
    Вроде ничего не напутал ?
     
  9. kaspersky

    kaspersky New Member

    Публикаций:
    0
    Регистрация:
    18 май 2004
    Сообщения:
    3.006
    DeFuckTo
    не забывай о том, что ассемблерные вставки привязывают тебя к компилятору, что не есть гуд и если потом ты захочешь перенести свою программу на тот же линух, то тебе придется долго трахаться. так же ассемблерные вставки срубают оптимизацию (в большей или меньше степени), в частности, компилятор, встретив асм-вставку может сгенерировать стандартный пролог и сохранять кучу регистров в стеке, в результате чего прирост производительности за счет ассемблерной оптимизации будет уничтожен тормозами компилятора. уж если и писать на асме, то всю функцию целиком.
     
  10. DeFuckTo

    DeFuckTo New Member

    Публикаций:
    0
    Регистрация:
    8 мар 2007
    Сообщения:
    8
    После всего выше сказанного думаю оставить всё на СИ без asm.
     
  11. kaspersky

    kaspersky New Member

    Публикаций:
    0
    Регистрация:
    18 май 2004
    Сообщения:
    3.006
    DeFuckTo
    если забить на неисполняемый стек (который мало где есть), то можно поступить так:

    int (*foo)();

    bar()
    {
    // объявляем массив и заполняем его машинным кодом
    char shell[]="\x0F\x31"; // RDTSC

    // преобразуем указатель на массив в указатель на функцию foo
    foo = (int(*)())shell;

    // вызываем функцию foo, возвращая результат ее выполнения
    // для простоты результат усекается до 32-бит, передаваемых в регистр EAX,
    // старшие 32-бита, помещаемые командой RDTSC в регистр EDX мы отбрасываем
    return foo();
    }

    main()
    {
    int a;
    a = bar();
    }
     
  12. asmfan

    asmfan New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2006
    Сообщения:
    1.004
    Адрес:
    Abaddon
    А не должно ли быть так?
    Или там "строка" заинлайнится?
     
  13. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    asmfan
    по идее ret должно быть)
     
  14. kaspersky

    kaspersky New Member

    Публикаций:
    0
    Регистрация:
    18 май 2004
    Сообщения:
    3.006
    вы правы товарищи. ret там быть должен. это я просто выравл его из контекста. а еще там был пролог, обращающийся к аргументам, который я тоже сократил, поскольку там довольно муторный способ определения аргументов, зато ассемблерная вставка автоматически распознает си, паскаль и stdcall методы передачи параметров ;) да, и еще забыл сказать, что на системах с неисполняемым стеком это работать не будет. на винде еще можно вызывать VirtualProtect. а вот в юнихе - mprotect работает не всегда. в некоторых случаях линух ложит стек в отдельный селектор, запрещая исполнение кода, и на уровне страниц атрибуты "исполняемый" просто игнорируются. но это - уже экзотика.
     
  15. asmfan

    asmfan New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2006
    Сообщения:
    1.004
    Адрес:
    Abaddon
    А с модификатором static будет, думается, работать...?
     
  16. cpp_and_wasm

    cpp_and_wasm Владимир

    Публикаций:
    0
    Регистрация:
    27 июл 2006
    Сообщения:
    128
    2 DeFuckTo
    У меня были страшные глюкозабры с такими вставками при включённой оптимизации кода
     
  17. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    cpp_and_wasm
    В VS2005 я ещё ни разу не замечал глюки, связанные с ассемблерными вставками и оптимизацией. Может быть, Вы имеете в виду GCC? GCC действительно страшно глючит в этим плане даже в более-менее свежих версиях.