g++ и его встроенный ассемблер в режиме intel

Тема в разделе "WASM.UNIX", создана пользователем aa_dav, 25 мар 2009.

  1. aa_dav

    aa_dav Active Member

    Публикаций:
    0
    Регистрация:
    24 дек 2008
    Сообщения:
    457
    Синтаксис AT&T учить большого смысла не вижу, ведь в as и в g++ появилась опция "режим интел". g++ -masm=intel превосходно генерит асм под ключём -S, именно интел, в общем осталось научится делать асмовые вставки в нём...
    Просто
    asm("команда без аргументов");
    работает на ура.
    Но задачка - выполнить примерно следующее:
    Код (Text):
    1. double fpu_cos( double arg )
    2. {
    3.     double res;
    4.     asm("fld QWORD PTR arg");
    5.     asm("fcos");
    6.     asm("fstp QWORD PTR res" );
    7.     return res;
    8. };
    И вот тут as ругается "undefined reference to arg"... А это не радует... В стиле AT&T было как-то мощно через двоеточия отсылки к внешним переменным из асма, а как это делается в режиме intel?
     
  2. Yorik

    Yorik Артур

    Публикаций:
    0
    Регистрация:
    11 янв 2008
    Сообщения:
    18
  3. aa_dav

    aa_dav Active Member

    Публикаций:
    0
    Регистрация:
    24 дек 2008
    Сообщения:
    457
    Не рулед. Там нет ответов на вопрос который я задал. Ни одного вообще примерно похожего. Про то что g++ и as уже позволяют юзать intel синтаксис я сам написал в первом же посте. Проблема вообще в другом. Как во встроенный асм передать адреса сишных переменных в этом синтаксисе (intel).
    Методом святого гугла ничего путнего найти не могу. Либо речь идет об AT&T синтаксисе, либо команды в intel-синтаксисе встроенного асма не имеют аргументов-операндов из C-шной части проги.
    Скрещивая знания, почёрпнутые из ссылок про AT&T пытаюсь приладить по подобной схеме аргументы-С-переменные к intel-синтаксису и вроде даже начало получаться, но к сожалению бздрищ и ах.... Туплю последние два часа, пытаясь загрузить в eax адрес аргумента arg (G++/AS):

    Код (Text):
    1. double fpu_cos( double arg )
    2. {
    3.     double res = 0;
    4.     asm("mov eax, QWORD PTR %[asm_arg]" : : [asm_arg] "m" (arg));
    5.     ...
    6. }
    error: ambigious operand size invalid for mov.

    При этом вариантов уже испробовал кучу чертову, и без QWORD PTR и вместо "m" - "X" и т.п. и т.д, всего уже не упомню. Смысл - чтобы в eax оказался адрес arg, чтобы скормить его потом fld QWORD PTR [eax], но увы, не компилица.... Ругается на всякое.

    P.S.

    Напоминаю, что всё это компилится с ключем -masm=intel и действительно в моей версии опознаваться должно правильно. Одиночная asm("fcos"); не вызывает никаких ошибок, что для AT&T синтаксиса неприемлемо.
     
  4. Voodoo

    Voodoo New Member

    Публикаций:
    0
    Регистрация:
    9 апр 2003
    Сообщения:
    297
    Адрес:
    Новосибирск
    первая ссылка в гугле
    Код (Text):
    1. #include <stdio.h>
    2.  
    3. double fpu_sqrt( double arg )
    4. {
    5.     double res;
    6.     asm("fld %0"::"m"(arg));
    7.     asm("fsqrt");
    8.     asm("fstp %0":"=m"(res) );
    9.     return res;
    10. };
    11.  
    12. int main()
    13. {
    14.     printf("%f\n", fpu_sqrt(3));
    15.     return 0;
    16. }
     
  5. aa_dav

    aa_dav Active Member

    Публикаций:
    0
    Регистрация:
    24 дек 2008
    Сообщения:
    457
    Voodoo

    Спасибо за код, он действительно скомпилировался без ошибок, хотя я готов был поклястся, когда увидел, что такой вариант уже пробовал.
    Трабла правда в том, что я действительно пробовал этот вариант и отказался, т.к. он генерирует ужасную хрень: думает что если "m", то это не на стеке должно быть, а.... опять же копирует в стек ниже адресом, чтобы передать уже асму как параметр. Вот оно:

    Код (Text):
    1. _Z8fpu_sqrtd:
    2. .LFB534:
    3.     push    ebp
    4. .LCFI2:
    5.     mov ebp, esp
    6. .LCFI3:
    7.     sub esp, 24
    8. .LCFI4:
    9.     mov eax, DWORD PTR [ebp+8]
    10.     mov DWORD PTR [ebp-24], eax
    11.     mov eax, DWORD PTR [ebp+12]
    12.     mov DWORD PTR [ebp-20], eax
    13. #APP
    14. # 55 "main.cpp" 1
    15.     fld QWORD PTR [ebp-24]
    16. # 0 "" 2
    17. # 56 "main.cpp" 1
    18.     fcos
    19. # 0 "" 2
    20. # 57 "main.cpp" 1
    21.     fstp QWORD PTR [ebp-8]
    22. # 0 "" 2
    23. #NO_APP
    24.     fld QWORD PTR [ebp-8]
    25.     leave
    26.     ret
    Обратите внимание, на то что происходит в метке .LCFI4 - всё ради того, чтобы асм-код ниже инструкцией "схавал" ту самую "m" (операнд из памяти). Абсолютно непонятно зачем и почему. Такое ощущение, что "m" входит в режим "read-only" или что-то из такого дурдома.
    Поэтому я действительно этого (для чтения) достигал, но как увидел результат - отказался сразу же. И на каких-то других (вроде "f") спецификаторах достигал нужного - fld QWORD PTR [ebp+8] и ликовал, но применить то же по отношению к fstp никак не мог! =(((
    Та же проблема и у записи - вместо того чтобы сразу писать в res, со всеми вытекающими, сперва в переменную пишет, потом снова достаёт, чтобы вернуть из функции, как-будто бы не видит что запись шла в эту же переменную изначально, как будто бы всё-таки, упущены другие важные квалификаторы, делающие код эффективным по AT-энд-T-шному....
    Блин... В MVSC++ асм оптимизировался без всяких таких костылей, как влитой инструмент в язык. Тут же видно, что всё сложнее, инструмента в языке встроенного нет, но есть все причиндалы, чтобы он вёл себя с ними как можно эффективнее, но пока не получается. =(
     
  6. TheGood

    TheGood New Member

    Публикаций:
    0
    Регистрация:
    9 ноя 2009
    Сообщения:
    1
    Помогите перевести inline intel в inline at&t формат
    Код (Text):
    1. func (UINT64 x)
    2. {
    3.   {
    4.     _asm
    5.       {
    6.       mov eax, dword ptr x[0]
    7.       test eax, eax
    8.       jz f_hi
    9.       bsf eax, eax
    10.       jmp f_ret
    11.       f_hi: bsf eax, dword ptr x[4]
    12.       add eax, 20h
    13.       f_ret:
    14.       }
    15.   }
    16. }
    Особенно интересует - как записать mov eax, dword ptr x[0] и bsf eax, dword ptr x[4]
    (и разве допустима запись x[0] и x[4] ?). intel2gas спотыкается на данной адресации
     
  7. black_hole

    black_hole New Member

    Публикаций:
    0
    Регистрация:
    3 янв 2006
    Сообщения:
    44
    угу реальный гемор, этот встроеннный асм, хоть at&t, хоть intel
    btw 2 Voodoo пример компилится, но работает неверно, так что низачот:)
    завтра прийдётся медитировать на мануал, так как эмипирические наблюдения ничего полезного за полдня не дали
     
  8. black_hole

    black_hole New Member

    Публикаций:
    0
    Регистрация:
    3 янв 2006
    Сообщения:
    44
    вот такое работает в качестве fsqrt, инструмент мощный, этот inline gcc asm, но разобраться очень тяжело, и похоже intel режим только костылей добавляет, а помощи от него никакой, передать параметры функции как в этом примере - ну никак, а ld ругается на неизвестные символьные имена...
    Код (Text):
    1. #include <stdio.h>
    2. double fpu_sqrt(double x)
    3. {
    4.    double res;
    5.    asm ("fsqrt" : "=t" (res): "0" (x));
    6.    return res;
    7. };
    8. int main()
    9. {
    10.     printf("%f\n",fpu_sqrt(3));
    11.     return 0;
    12. }
     
  9. r90

    r90 New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2005
    Сообщения:
    898
    black_hole
    Я могу поверить, что за intel синтаксис можно держаться, если писать на асме много. Но если речь идёт об inline вставке -- то какая разница? Не машинный код, мнемониками -- уже хорошо, и ладно.
    info gcc "C Implementation" Constraints
    Там всё расписано. В секции же "Extended Asm" описано как этим пользоваться. Ну и, в конце концов, если этого мало можно сказать:
    Код (Text):
    1. find /usr/src/linux -name \*.c | xargs grep asm | grep -v include
    И поизучать это дело на примерах.
     
  10. black_hole

    black_hole New Member

    Публикаций:
    0
    Регистрация:
    3 янв 2006
    Сообщения:
    44
    r90, cпасибо за участие! Вы мне очень помогли!