Форум программистов, компьютерный форум, киберфорум
C++
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.62/55: Рейтинг темы: голосов - 55, средняя оценка - 4.62
Автор FAQ
3148 / 368 / 3
Регистрация: 08.08.2009
Сообщений: 1,126
1

Ошибка компиляции ассемблерной вставки

08.11.2009, 16:39. Показов 10305. Ответов 21
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый вечер. Захотелось мне сделать ассемблерную вставку в C++ код. Сделал. Но компилятору MinGW чето не нравится. Выдает следующие ошибки в 8 строке:

error: expected `(' before '{' token
error: expected asm body before '{' token


Что я сделал не так ?

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
 
using namespace std;
int main ()
{
    cout << "Сейчас будет звонить!" << endl;
    asm
    {
        /*MOV AH,2
        MOV DL,7
        INT 21H*/
    }
    cout << "Есть!" << endl;
    return 0;
}
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
08.11.2009, 16:39
Ответы с готовыми решениями:

Выполнить с использованием ассемблерной вставки
Нужно подсчитать кол-во цифр в троке из 10 символов. Реализовать в виде ассемблерной вставки. ...

Как вывести числа в цикле ассемблерной вставки?
Доброго времени, суток! Мне нужно вывести каждый результат получившийся в цикле, как это можно...

Получение значения элемента массива с помощью ассемблерной вставки
У меня есть функция int kontr(char* str1, int len) { __asm{ lea esi, ; xor ebx, ebx;...

Определить размер кеша инструкций первого уровня с помощью ассемблерной вставки
Не знал в каком разделе создать тему, но думаю этот вопрос будет понятен программистам С++. Встала...

21
4337 / 1506 / 101
Регистрация: 12.04.2009
Сообщений: 2,342
08.11.2009, 17:50 2
__asm
0
Автор FAQ
3148 / 368 / 3
Регистрация: 08.08.2009
Сообщений: 1,126
08.11.2009, 17:54  [ТС] 3
Цитата Сообщение от HIMen Посмотреть сообщение
__asm
Те же ошибки
0
2537 / 833 / 10
Регистрация: 31.05.2009
Сообщений: 1,668
10.11.2009, 19:03 4
Почитайте тут.

Добавлено через 2 минуты
Цитата Сообщение от RNT Посмотреть сообщение
Но компилятору MinGW чето не нравится. Выдает следующие ошибки в 8 строке:
У него вроде AT&T синтаксис, а не интеловский и команды будут выглядеть по другому.

Примерно так
C++
1
2
3
4
5
    asm ( 
"movb $2,%ah \n" 
"movb $7,%dl\n" 
"int $0x21\n"
);
1
Автор FAQ
3148 / 368 / 3
Регистрация: 08.08.2009
Сообщений: 1,126
10.11.2009, 19:45  [ТС] 5
Цитата Сообщение от Goodwin98 Посмотреть сообщение
asm (
"movb $2,%ah \n"
"movb $7,%dl\n"
"int $0x21\n"
);
Компилится. Но возникли следующие вопросы:

1) Как сделать нормальный Intel синтаксис ?
2) Почему команды в круглых скобках а не в фигурных ?
3) Почему каждая команда в кавычках ?
4) Почему в конце каждой команды стоит знак переноса строки ?
5) Почему при построчной отладке программы все ассемблерные команды пропускаются ?
6) Почему после "выполнения" команд в регистрах не оказывается нужного значения ?
0
577 / 571 / 65
Регистрация: 29.01.2009
Сообщений: 1,274
10.11.2009, 20:47 6
RNT, у каждого компилятора свой синтаксис асм-вставок. MinGW это портированный в винду GCC со своими особенностями. Если понимаешь по англицки, то вот тебе туториал на эту тему http://www.ibiblio.org/gferg/l... HOWTO.html.
1
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
10.11.2009, 23:54 7
Если что - обращайся. Правда я в intel'овском ассемблере ничерта не понимаю, но если объяснишь, что да как должно быть - попробую написать или объяснить. Почитай ещё эту тему. В конечном итоге в посте 49 я наваял конкретную реализацию для поставленного вопроса, но попробуй всю тему прочитать, может среди этого бардака какое-то общее понимание появится
1
Автор FAQ
3148 / 368 / 3
Регистрация: 08.08.2009
Сообщений: 1,126
11.11.2009, 00:22  [ТС] 8
Я не понимаю, почему в компилятор GCC засунули ассемблер GAS с чудо-юдо синтаксисом AT&T ? Для него даже книжек почти нет.
0
577 / 571 / 65
Регистрация: 29.01.2009
Сообщений: 1,274
11.11.2009, 00:46 9
У AT&T нормальный синтаксис и в чем-то даже удобнее интеловского. AT&T асм появился в UNIX, когда интела еще в помине не было и так и остался классическим асмом для юникс-систем. Книги для него, кстати, есть, но все в английском варианте, а на русском можешь почитать статью http://wasm.ru/article.php?article=asm_linux_for_c
1
Автор FAQ
3148 / 368 / 3
Регистрация: 08.08.2009
Сообщений: 1,126
11.11.2009, 00:56  [ТС] 10
Цитата Сообщение от Gravity Посмотреть сообщение
Книги для него, кстати, есть, но все в английском варианте


Добавлено через 2 минуты
Значит буду изучать intel`овский синтаксис, я еще не настолько хорошо знаю инглиш
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
11.11.2009, 09:47 11
В gcc НЕ "интеловский" или какой-либо другой синтаксис (а точнее, "ФОРМАТ АССЕМЛЕРНОЙ ВСТАВКИ"). Этот синтаксис - единый для ВСЕХ архитектур. Отличие идёт только в constraint'ах (ну и, понятное дело, в самом ассемблерном тексте). Мне уже приходилось писать документацию по формату gnu вставки, сегодня постараюсь на работе найти. Если вдруг случится, что ты это просечёшь досконально, то тогда поймёшь, что более идеально придумать сложно.
0
Автор FAQ
3148 / 368 / 3
Регистрация: 08.08.2009
Сообщений: 1,126
11.11.2009, 10:37  [ТС] 12
Не понимаю, объясни пожалуйста попроще.

Цитата Сообщение от Evg Посмотреть сообщение
Этот синтаксис - единый для ВСЕХ архитектур
AT&T ? Он более кроссплатформенный чем Intel-синтаксис ?

Цитата Сообщение от Evg Посмотреть сообщение
Отличие идёт только в constraint'ах
Что это такое ? constraint ?

Я вот нарыл на одном форуме, как сделать чтобы g++ компилил intel-синтаксис.
Надо в консоли делать так: g++ имя_сорца.cpp -masm=intel
http://www.google.ru/search?hl... u&aq=f&oq=
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
11.11.2009, 13:48 13
Сразу на всякий случай скажу: есть два понятия:
- "синтаксис ассемблера" - зависит от архитектуры
- "формат ассемблерной вставки" (ассемблерная вставка это конструкция ЯЗЫКА GNU-C) - от архитектуры не зависит

По поводу документации. Я её нашёл, но хз насколько она окажется полезной. Дело было так, что партия сказала "надо", комсомол сказал "есть" и сделал абы как, лишь бы отстали. Т.е. документация скорее "чтоб было", чем "чтоб можно было пользоваться". Реально она больше введёт в заблуждение, т.к. описано на примере sparc. В общем я дла начала закину, а ты хоть базу почитай

=================================

GNU ассемблерная вставка по замыслу разработчиков является чёрным ящиком с параметрами, т.е. компилятор НЕ видит ассемблерного текста вставки, но видит описание всех ресурсов, которые подаются на вход вставки (input arguments), принимаются с выхода вставки (output arguments) и неявным образом портятся внутри вставки (clobbers)

Формат вставки такой:

C
1
asm ("<asm text>" : <input arguments> : <output arguments> : <clobbers>);
Рассмотрим сначала просто пример, как построить выражение 'x = y + z' при помощи
gnu ассемблерной вставки:

C
1
2
3
4
5
{
  int x, y, z;
  ...
  asm ("add %1, %2, %0" : "=r"(x) : "r"(y), "r"(z));
}
в данном случае:
* "add %1, %2, %0" - текст вставки,
* "=r"(x) - ВЫХодной аргумент (одна штука),
* "r"(y), "r"(z) - ВХодные аргументы (две штуки, перечисленные через запятую).
* clobber'ы в данной вставке отсутствуют, а потому не написаны

Описание аргументов вставки состоит из двух частей - в кавычках пишется модификатор (FIXME КАК ПРАВИЛЬНО НАЗЫВАЕТСЯ???) (только для output аргументов) и описание аппаратного ресурса, на который должен быть загружен аргумент вставки (это называют словом constraint). В круглых скобках пишется значение (value) аргумента: для input аргумента это rvalue expression (выражение, которое может стоять в правой части присваивания), для output аргумента - это lvalue expression (соответственно, выражение, которое может стоять в левой части присваивания)

Более детально будет расписано ниже, а пока только применительно к данному примеру. У output аргумента "=r"(x) в качестве модификатора стоИт символ '=', что означает аргумент строго на запись. В качестве constraint стоИт символ 'r', что означает целочисленный регистр, доступный компилятору для распределения. В качестве value стоИт x, это означает, что после кода вставки значение упомянутого регистра будет записано в переменную x. У input аргумента "r"(y) в качестве constraint так же стоит целочисленный регистр, в качестве value стоИт y, что означает, что перед кодом вставки значение переменной y будет загружено на регистр, который затем будет использоваться во вставке.

Текст вставки - это то, что в итоге попадает в выходной ассемблерный код, который строит компилятор. Символ % является управляющим. %0, %1 и %2 соответсвуют номерам аргументов в порядке их перечисления в конструкции asm начиная с нуля. В данном случае %0 соответствует аргументу "=r"(x), %1 соответствует аргументу "r"(y), а %2 соответствует аргументу "r"(z).

Добавлено через 56 секунд
Ну и в добавок, ты всегда можешь запустить gcc/g++ с опцией -S и посмотреть результирующий ассемблерный файл (чтобы визуально оценить, насколько правильный код построился)
1
Автор FAQ
3148 / 368 / 3
Регистрация: 08.08.2009
Сообщений: 1,126
11.11.2009, 15:04  [ТС] 14
Цитата Сообщение от Evg Посмотреть сообщение
asm ("add %1, %2, %0" : "=r"(x) : "r"(y), "r"(z));
Ты кажется перепутал порядок управляющих символов. Я правильно поправил ?

C++
1
asm ("add %0, %1, %2" : "=r"(x) : "r"(y), "r"(z));
Я попробовал скомпилировать твой код, выдается ошибка Error: suffix or operands invalid for `add' в строке 119. Такой строки в моем коротеньком исходнике нет.

C++
1
2
3
4
5
6
7
8
9
10
#include <iostream>
using namespace std;
 
int main()
{
    int x=0, y=6, z=7;
    asm ("add %1, %2, %0" : "=r"(x) : "r"(y), "r"(z));
    cout << x;
    return 0;
}
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
11.11.2009, 15:16 15
> Ты кажется перепутал порядок управляющих символов. Я правильно поправил ?

У меня всё правильно. Для sparc'овской операции формат такой "add src1, src2, dst"

Добавлено через 1 минуту
> Я попробовал скомпилировать твой код

Это для sparc'а, а не для intel'а. Скажи мне, как на intel'е делается сложение, и я тебе исходник напишу. Эту ошибку выдаёт ассемблер, а не компилятор. gcc вовнутрь вставки вообще не лезет, только подставляет операнды на нужные позиции
0
577 / 571 / 65
Регистрация: 29.01.2009
Сообщений: 1,274
11.11.2009, 15:21 16
Для интела будет так выглядеть
C++
1
asm ("add %0, %1" : "=m"(x) : "r"(y));
add принимает два операнда. Компилировать надо с флагом intel, иначе не фкурит.

Мне кажется, что проще писать процедуру на асме отдельным файлом и собирать вместе с основным проектом на си, если так хочется поюзать ассемблер.
1
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
11.11.2009, 15:30 17
Gravity, у тебя задан двухоперандный случай. К тому же правильно помечать "+m", а не "=m". Вариант с оформлением в виде отдельной процедуры (для трёхаргументного вычитания):

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
 
int
asm_sub (int src1, int src2)
{
  register int dst;
 
  asm ("subl %2, %0" : "=&r" (dst) : "0" (src1), "r" (src2));
 
  return dst;
}
 
int main (void)
{
  printf ("%d\n", asm_sub (15, 23));
  return 0;
}
Добавлено через 25 секунд
Цитата Сообщение от Gravity Посмотреть сообщение
Мне кажется, что проще писать процедуру на асме отдельным файлом и собирать вместе с основным проектом на си, если так хочется поюзать ассемблер.
В этом случае ты зарубаешь возможность inline'а
2
Автор FAQ
3148 / 368 / 3
Регистрация: 08.08.2009
Сообщений: 1,126
11.11.2009, 15:59  [ТС] 18
Подскажите пожалуйста книжки или статьи, где можно основательно почитать про то, как делать ассемблерные вставки в C/C++.
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
11.11.2009, 16:10 19
Лучший ответ Сообщение было отмечено как решение

Решение

По поводу inline'а лучше поясню на более конкретном примере. Допустим, мы имеем интерфейс для некоторых небольших действий. Что-то мудрённое писатьне будем, а ограничимся операциями сложения и вычитания (чтобы меньше было в коде текста и проще было понять суть). Пусть интерфейсы называются asm_add и asm_sub соотвественно. Таким образом мы реализуем некие кубики, из которых можно будет строить более объёмные блоки. В данном примере в качестве блока реализуем функцию func от трёх параметров, которая реализует свёртку "x+y-z"

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* Файл t.h */
 
static inline int
asm_add (int src1, int src2)
{
  register int dst;
 
  asm ("addl %2, %0" : "=&r" (dst) : "0" (src1), "r" (src2));
 
  return dst;
}
 
static inline int
asm_sub (int src1, int src2)
{
  register int dst;
 
  asm ("subl %2, %0" : "=&r" (dst) : "0" (src1), "r" (src2));
 
  return dst;
}
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* Файл t.c */
 
#include <stdio.h>
#include "t.h"
 
int
func (int x, int y, int z)
{
  int a, b;
  
  a = asm_add (x, y);
  b = asm_sub (a, z);
  
  return b;
}
В итоге, имеем следующий код:

Код
$ gcc t.c -O2 -S
$ cat t.s
        .file   "t.c"
        .text
        .p2align 4,,15
.globl func
        .type   func, @function
func:
        pushl   %ebp
        movl    %esp, %ebp
        movl    12(%ebp), %edx
        movl    16(%ebp), %ecx
        movl    8(%ebp), %eax
        popl    %ebp
#APP
        addl %edx, %eax
        subl %ecx, %eax
#NO_APP
        ret
        .size   func, .-func
        .ident  "GCC: (GNU) 4.1.2 (Gentoo 4.1.2 p1.1)"
        .section        .note.GNU-stack,"",@progbits
В итоге компилятор все наши static inline процедуры подставил (а коды самих процедур удалил) и мы получили "быструю" функцию func, в которой функциональная часть - это две наши операции addl и subl, всё остальное - это работа по перенесению параметров из стека на регистр и сохранение frame-pointer'а. Если бы мы функции asm_add и asm_sub написале в виде процедур на ассемблере в отдельном ассемблерном файле, то компилятор бы подстановку в принципе не смог сделать и быстрый "блок из кубиков" реализовать бы не получилось

В данном случае весь интерфейс у нас реализован в виде процедур на языке GNU-C, который другие компиляторы не понимают. При использовании другого компилятора нам бы нужно было подхачить только "кубиковый" файл t.h и как-то на языке или каким-либо другим способом написать функции, которые выполняют нужные действия. Пусть они будут не на ассемблере, пусть они получатся медленными, но мы исправили только самый нижний уровень, не трогая при этом весь остальной код. В итоге программу заставили работать, пусть и медленнее, чем можно было бы, но для первого шага этого оказалось бы достаточно. Этот абзац уже относится не столько к ассемблерным вставкам, сколько к технике программирования и реализации архитектурно-зависимых частей в виде маленьких кубиков

Добавлено через 1 минуту
Цитата Сообщение от RNT Посмотреть сообщение
Подскажите пожалуйста книжки или статьи, где можно основательно почитать про то, как делать ассемблерные вставки в C/C++.
Анус состоит в том, что по этому поводу по большому счёту нигде нет внятной литературы. Есть техническая документация по gcc, но она слишком ублюдочная. Это хорошая тема для FAQ'а, но чтоды описать доступно, надо будет попотеть и придумать хотя бы с какого боку начать пояснения. Я имею в виду gcc. А общего механизма нет, в каждом компиляторе он реализован по-своему
3
Автор FAQ
3148 / 368 / 3
Регистрация: 08.08.2009
Сообщений: 1,126
11.11.2009, 16:15  [ТС] 20
Цитата Сообщение от Evg Посмотреть сообщение
Анус состоит в том, что по этому поводу по большому счёту нигде нет внятной литературы.
Evg, а как ты это изучил ?
0
11.11.2009, 16:15
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
11.11.2009, 16:15
Помогаю со студенческими работами здесь

С помощью ассемблерной вставки найти отрицательные элементы в массиве, и среднее положительных элементов
Создать массив X. Определить среднее арифметическое положительных чисел, из отрицательных создать...

С помощью ассемблерной вставки сложить a+b, вывести результат, в переменную bool записать было ли переполнение
Нужно написать ассемблерную вставку Есть переменные unsigned char a,b; bool c; Как с помощью...

Ошибка с ассемблерной вставкой
#include &lt;iostream&gt; int main() { char src = &quot;hello&quot;, dst; int a = strlen(src); for...

Ошибка при компилировании ассемблерной вставки
При попытки добавить ассемблерную вставку выдается ошибка: unit1.pas(31,3) Fatal: Selected...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru