необходимо разобраться с ассемблерными вставками в языке С/C++

Тема в разделе "WASM.BEGINNERS", создана пользователем amvoz, 27 ноя 2011.

  1. amvoz

    amvoz Member

    Публикаций:
    0
    Регистрация:
    12 ноя 2008
    Сообщения:
    640
    Стоит простенькая задача: перегнать значение переменной per в региср eax, поехали (пояснение в коде):

    Код (Text):
    1. #include <stdio.h>
    2. int main(int argc,char *argv[]){
    3.  int per;
    4.  per= 0Xcc;
    5.  
    6.  
    7.  asm ("mov %1, %eax;"
    8.  
    9.   //А дальше очень всё интересно начинается, у меня в книге написано, что
    10.   //щас должны идти выходные операнды, а у меня выходных нет, у меня один ВХОДНОЙ операнд
    11.   //переменная per, что делать? Значит, пишем две строчки нулевую и первую
    12.   //нулевую он пропустит, а из первой возьмёт входной операнд per
    13.   //и всё будет круто
    14.  
    15.   :"=r"(per) //Вот эту строчку компилятор должен пропустить.
    16.   :"r"(per));
    17.  
    18.   //Но он почему-то этот код не хавает, а пишет
    19.   //operand number missing after %-letter
    20.   //Короче непонятно чёто где отсутствует, помогите пожалуййста, я
    21.   //на самом деле пробовал ВСЯКО-РАЗНО, не буду же я загромождать код всякой чушью
    22.  
    23.  
    24.  
    25.  
    26.  printf ("a=%x   \n" ,per);
    27.  getchar ();
    28. return 0 ;
    29. }
    Так-то я знаю, что сперва надо с теорией разобраться. Но не получается у меня не понимаю я чё и куда писать. Инфу брал из книги "полное руководство gcc"? глава про ассемблерные вставки, спасибо, кто откликнется.
    компилятор g++
     
  2. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    4.814
    Код (Text):
    1. int main()
    2. {
    3.   unsigned int per = 0xCC;
    4.   asm("movl %1, %eax" : : "r" (per));
    5.   // ...
    6. }
    и так понятно или пояснить?
     
  3. amvoz

    amvoz Member

    Публикаций:
    0
    Регистрация:
    12 ноя 2008
    Сообщения:
    640
    ошибки в 4-ой строке:
    operand number out of range
    operand number missing after %-letter
     
  4. amvoz

    amvoz Member

    Публикаций:
    0
    Регистрация:
    12 ноя 2008
    Сообщения:
    640
    Надо так:
    Код (Text):
    1. int main()
    2. {
    3.   unsigned int per = 0xCC;
    4.   asm("mov %0, %%eax" : : "r" (per));
    5.   // ...
    6. }
    иcпытания завтра, щас всем спать
     
  5. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    4.814
    Код (Text):
    1. asm("mov %0, %%eax" : : "r" (per));
    да, действительно... я просто не большой фанат AT&T синтаксиса... в интеловском все попроще выглядит, ключ компилятора:
    Код (Text):
    1. -masm=intel
     
  6. amvoz

    amvoz Member

    Публикаций:
    0
    Регистрация:
    12 ноя 2008
    Сообщения:
    640
    Твой код не коплилируется безусловно, с ЛЮБЫМ КЛЮЧОМ (-masm=intel или -masm=att)
    Вопрос: на что же тогда влияют эти ключи? Ответ: они влияют на выработку ассемблерного кода

    Код (Text):
    1. g++ main.cpp -masm=att -S
    генерит файл main.s с кодом на асме, синтаксис att
    Код (Text):
    1. g++ main.cpp -masm=intel -S
    генерит файл main.s с кодом на асме, синтаксис intel


    Это из книги:
     
  7. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    4.814
    он не компилируется потому, что он написан на AT&T с ошибкой... к интеловскому синтаксису он не имеет отношения...
    синтаксисы AT&T и Intel весьма разные: http://asm.sourceforge.net/articles/linasm.html#Syntax

    не верно... ассемблер gcc/g++ - это макроассемблер... асм-код никак не компилируется компилятором gcc/g++, он предоставляется практически как есть GNU-ассемблеру, который в зависимости от флага принимает либо интеловский либо атинти синтаксис... то есть при использовании inline-ассемблера ты можешь писать в интеловском синтаксисе, используя флаг -masm=intel...
     
  8. amvoz

    amvoz Member

    Публикаций:
    0
    Регистрация:
    12 ноя 2008
    Сообщения:
    640
    А я понял твоё утверждение из поста номер 5 так, что можно с разными ключами писать используя разный синтаксис, угу? А вот у меня не выходит. Компилятор хавает ТОЛЬКО синтаксис AT&T. Если компилятор хавает ассемблерные вставки с использованием синтаксиса intel и ты умеешь это делать, покажи как, буду благодарен.
     
  9. cppasm

    cppasm New Member

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    923
    Это потому что ты документацию не читаешь :)
    .intel_syntax noprefix в начало ассемблерной вставки надо добавить.

    http://xorl.wordpress.com/2009/01/01/intel-syntax-on-gcc/

    Хотя работает и без .intel_syntax noprefix
    Код (Text):
    1. #include <stdio.h>
    2.  
    3. int get_random(void)
    4. {
    5.     int x;
    6.     asm("mov eax, 42\n" : "=a" (x));
    7.     return x;
    8. }
    9.  
    10. int main(void)
    11. {
    12.     return printf("The answer is %d.\n", get_random());
    13. }
    gcc -O2 -masm-intel test.c

    a.exe
    The answer is 42.
     
  10. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    4.814
    совершенно не обязательно... ключ компиляции решает)))... префикс полезно вставлять в каждую асм-вставку, если хочешь замиксить at&t и intel синтаксисы в одном исходнике например...

    компилятор хавает, ты видимо делаешь ошибки в интеловском синтаксисе, покажи мне код, который у тебя "не хавает"... и "gcc --version" за одно...
    Код (Text):
    1. #include <stdio.h>
    2. #include <stdint.h>
    3.  
    4. int main(int argc, char* argv[])
    5. {
    6.     register uint32_t A = 0;
    7.     asm volatile("push eax           \n"
    8.                  "mov eax, 0xFFFFFFFF\n"
    9.                  "mov %0, eax        \n"
    10.                  "pop eax            \n"
    11.                  : "=r" (A));
    12.     printf("%d\n", A);
    13.     return 0;
    14. }
    компиляция и вывод:
    Код (Text):
    1. > g++ -o main.elf -masm=intel main.cpp
    2. > ./main.elf
    3. -1
    вывод листинга (перменная A, как я и хотел - в регистре ebx):
    Код (Text):
    1. ....
    2. # 11 "main.cpp" 1
    3. push eax          
    4. mov eax, 0xFFFFFFFF
    5. mov ebx, eax        
    6. pop eax
    7. ....
    ЗЫ at&t синтаксис с "сурдопереводом"))): http://cs.nyu.edu/courses/fall03/V22.0201-003/c_att_syntax.html
     
  11. cppasm

    cppasm New Member

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    923
    Я поправил уже.

    Надо либо ключ компилятору, либо .intel_syntax noprefix вначале вставки, и .att_syntax prefix в конце.
    Но не и то и другое одновременно.
     
  12. amvoz

    amvoz Member

    Публикаций:
    0
    Регистрация:
    12 ноя 2008
    Сообщения:
    640
    Может, у меня книга неправильная, но я перед именами регистов писал %, а я по ссылкам походил, а там нигде в синтаксисе intel нет такого знака, а у меня написано в книге:

    "Перед именем реrистра ставятся два знака процента  "%%". Например, %%еах
    или %%esi. Имена реrистров процессоров lntel начинаются со знака "%", а применение втoporo знака "%" требуют правила конструкции аsm, так что в нa
    шем случае их должно быть два. "

    Книга что ли лжёт?
     
  13. amvoz

    amvoz Member

    Публикаций:
    0
    Регистрация:
    12 ноя 2008
    Сообщения:
    640
    Артур Гриффитс, "GCC настольная книга для пользователей, программистов и системных администраторов" , глава 15 "Ассемблер GNU" вставка ассемблерного кода
     
  14. Psionic

    Psionic New Member

    Публикаций:
    0
    Регистрация:
    25 сен 2008
    Сообщения:
    153
    как все сложно
    CL.exe:
    Код (Text):
    1. __asm
    2. {
    3.  nop
    4. nop
    5. nop
    6. nop
    7. }
    trollface.jpg
     
  15. amvoz

    amvoz Member

    Публикаций:
    0
    Регистрация:
    12 ноя 2008
    Сообщения:
    640
    тут идёт обсуждение g++
     
  16. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    4.814
    здается мне, что под Intel понимается процессор, а не синтаксис... тем более, что книга вышла в 2004 году... не помню, с какой версии гцц поддерживает интеловский синтаксис, но что-то мне кажется, что в то время он еще не поддерживался...

    а теперь сделай тоже самое на x64-архитектуре... pokerface.jpg)))
     
  17. amvoz

    amvoz Member

    Публикаций:
    0
    Регистрация:
    12 ноя 2008
    Сообщения:
    640
    Хм, получается я пишу программу "Hello, word" на masm, использую там имена регистров без %, потом компилю и она не запустится у меня на процессоре Intel?
    (Потому, что имена регистров Intel начинаются с %) Так?
     
  18. cppasm

    cppasm New Member

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    923
    С директивой .intel_syntax noprefix процент перед именем регистра не нужен, с директивой .intel_syntax prefix - проценты нужны.
    Можно в AT&T отключить необходимость писать процент перед именем регистра - .att_syntax noprefix
    Если интеловский синтаксис включать ключом компилятора - проценты перед именем регистов не нужны.

    Сильный пример. Особенно если учесть, что нопы в любом синтаксисе одинаково пишутся.
     
  19. amvoz

    amvoz Member

    Публикаций:
    0
    Регистрация:
    12 ноя 2008
    Сообщения:
    640
    И потом: раз имена регситров процессора Intel начинаются с %, что же в синтаксисе Intel при обращении к регистрам не используется %?
    Всё это крайне непонятно.
     
  20. cppasm

    cppasm New Member

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    923
    Потому что нету в интеловском синтаксисе процентов перед именем регистра.
    И в AT&T это не часть имени регистра - это указание на то, что дальше идёт имя регистра.

    Поставь .intel_syntax prefix и будут тебе проценты.