Форум программистов, компьютерный форум, киберфорум
C/С++ под Linux
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.64/58: Рейтинг темы: голосов - 58, средняя оценка - 4.64
14 / 10 / 1
Регистрация: 28.04.2009
Сообщений: 219
1

Встроенный asm не понимает метки (GCC).

28.05.2009, 20:39. Показов 11168. Ответов 64
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
C
1
2
3
4
5
6
7
8
9
10
11
12
unsigned int iFactor(unsigned int n){
//(n==0)=>1; переполнение=>вернуть 0
//unsigned long long f; unsigned long f1; 
unsigned int f2=1;
for (;n;n--){
    f2*=n;
    asm ("jo OUT1");//при переполнении - return 0;
    }//for(n) end
return f2;
OUT1:
return 0;
}
Uncnown reference to OUT1, говорит.
Только не думайте, что я, как чуть что - сразу спрашивать бегу. Искал...
(Вообще, вроде должен видеть все метки и к переменные, "как свои". Так я думал...)

Добавлено через 9 часов 14 минут 6 секунд
Пробовал в операнд (имя метки) добавлять "_" (одно нижнее подчёркивание) - нет...
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
28.05.2009, 20:39
Ответы с готовыми решениями:

Встроенный asm и 64-битные регистры
Всем привет! Попробовал записать в 64-битный регистр ( R8 ) данные, на что студия ответила что...

Встроенный asm не видит метку (Borland 3.1)
Вот кусок кода: void fdc_out(unsigned char parm) { _asm { mov dx,3F4h...

AVRstudio 4 + GCC + ASM
Доброго времени суток! У меня назрел вопрос - можно ли использовать при написании использовать...

Нужно вставить блок на асме, но он не понимает asm и __asm
VC понимает директиву __asm, я пишу в данное время под Linux c компилером g++ v.3.0 нужно...

64
14 / 10 / 1
Регистрация: 28.04.2009
Сообщений: 219
02.06.2009, 11:03  [ТС] 41
Author24 — интернет-сервис помощи студентам
Мне же интересно решение первоначальной задачи
А Вы разве ещё не поняли? Повторяю:

"Что позволено Гераклу,
Не позволено в gcc"

Вот, читал тут.http://www.ibiblio.org/gferg/l... HOWTO.html
Там о переходах из блока asm вообще скромно умалчивают.
0
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
02.06.2009, 11:11 42
Ultrator, не понял чего? Переход из ассемблерного кода на внешнюю метку после return вполне возможен. В крайнем случае, это можно сделать без метки, каким-либо другим способом. Например, используя eip или еще что-то. Сейчас просто времени нет смотреть что-то по этому вопросу, других дел хватает.

Добавлено через 3 минуты 2 секунды
Но любой такой способ, как было упомянуто выше Evg, будет являться хаком. Скорее всего.
0
14 / 10 / 1
Регистрация: 28.04.2009
Сообщений: 219
02.06.2009, 11:17  [ТС] 43
А в таком асмовом коде, как вариант 3, будет окончание типа:
...................jc OUT1;
.......................
jmp OUT2; //а как же иначе?
OUT1:
mov $0, %0; //запись "0" в "res", после jc
OUT2:
//конец блока.
return res;
}

Что мы имеем? Один "лишний" jmp...

Добавлено через 2 минуты 17 секунд
Переход из ассемблерного кода на внешнюю метку после return вполне возможен.
В других компилерах - конечно!

А в GCC - покажи, плз, как, если знаешь... (Уже 2 дня пытаюсь это сделать)
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
02.06.2009, 11:43 44
Блин, да нарисуйте же вы мне код на ассемблере для умножения в цикле - всё сделаю. Для таких конструкций, чтобы избежать лишнего jmp'а в наиболее часто работающей ветке, используется subsection

> В других компилерах - конечно!

Другие компиляторы работают с вставками предельно тупо. Ассемблерная вставка это полюс, через который не работает ни одна оптимизация. Только за счёт такого поведения возможно из вставки непосредственно обращаться к переменным, меткам и т.п.

Добавлено через 1 минуту 22 секунды
Реально получается, что туеву кучу времени и слов потратил только потому, что не понимаю интеловский ассемблер, а те кто знает начисто игнориуют несколько раз написанную просьбу написать код

Добавлено через 8 минут 41 секунду
Если настолько лениво писать код, то посмотрите, как выглядит реализация spinlock'а:

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int
__pthread_spin_lock (pthread_spinlock_t *lock)
{
  asm volatile
    ("\n"
     "1:\n\t"
     "lock; decl %0\n\t"
     "js 2f\n\t"
     ".section .text.spinlock,\"ax\"\n"
     "2:\n\t"
     "cmpl $0,%0\n\t"
     "rep; nop\n\t"
     "jle 2b\n\t"
     "jmp 1b\n\t"
     ".previous"
     : "=m" (*lock));
  return 0;
}
Конструкция .subsection означает заведение переключение на новый кусок секции, которая будет помещена в самых хвост секции с кодом, а .previous - возврат к первоначальной секции. В итоге наиболее часто работающий "быстрый" участок состояит из двух операций без переходов, а редко работающий - на двух переходах и в жо$е (такое расположение в том числе позитивно влияет на кэш команд - редко работающие коды не забивают кэш)

Т.е. если написать код (в предположении, что процедура проинлайнится),

C
1
2
3
trampampam1;
__pthread_spin_lock(p);
trampampam2;
то в памяти машинный код будет лежать так:

Код
  код, соотвествующий trampampam1
1:
  lock; decl %0
  js 2f
  код, соотвествующий trampampam1
  ....
  <где-то в хвосте кодовской секции>
2:
  cmpl $0,%0
  rep; nop
  jle 2b
  jmp 1b
Метки, состоящие из одной цифры называются локальными метками и могутповторяться. Для обращения к ним используется, например, 1f (означает ближайшая по тексту вперёд метка с именем 1) или 1b (ближайшая по тексту назад метка с именем 1)
0
14 / 10 / 1
Регистрация: 28.04.2009
Сообщений: 219
02.06.2009, 12:16  [ТС] 45
MULL источник
Выполняет беззнаковое умножение источника (регистр или переменная) на содержимое EAX и помещает результат в EDX:EAX.
Если старшее слово в результате (EDX) не равно 0, флаг CF (и флаг OF тоже) - "1", иначе - "0".
0
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
02.06.2009, 12:16 46
Мдя...еще спины припахал.
Я сделал проще:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
 
int main()
{
   asm ("jmp l");
   int a=-1;
   if (a+1==0)
   {
    return 0;
   }
   asm ("l:");
   printf("Error\n");
   return 1;
}
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#APP
# 5 "one.c" 1
   jmp l
# 0 "" 2
#NO_APP
   movl  $-1, -8(%ebp)
   cmpl  $-1, -8(%ebp)
   jne   .L2
   movl  $0, -24(%ebp)
   jmp   .L3
.L2:
#APP
# 11 "one.c" 1
   l:
# 0 "" 2
#NO_APP
   movl  $.LC0, (%esp)
   call  puts
   movl  $1, -24(%ebp)
.L3:
   movl  -24(%ebp), %eax
   addl  $36, %esp
   popl  %ecx
   popl  %ebp
   leal  -4(%ecx), %esp
   ret
Метка осталась, все работает. Вариантов обмануть оптимизатор gcc до фига.
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
02.06.2009, 12:26 47
Цитата Сообщение от Vourhey Посмотреть сообщение
Мдя...еще спины припахал
Потому что если не хотите выдать код, чтобы я сделал правильно - дал хоть образец того, как это нужно делать.

Цитата Сообщение от Vourhey Посмотреть сообщение
Метка осталась, все работает. Вариантов обмануть оптимизатор gcc до фига.
Добавил опцию -O1, после мусорный код с чистой совестью снесло и метку заодно. Попытки обмануть оптимизатор в большинстве случаев означают, что ты его обманешь для данной версии компилятора и при данном наборе опций. Шаг влево или шаг вправо - работать перестаёт. Ну либо если пытаешься обмануть, надо как минимум понимать, как работает компилятор и оптимизации
1
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
02.06.2009, 12:47 48
Блин, не на ту кнопку попал
С кодом вообще не ко мне.
Выше я написал код, который будет работать. Если ты не можешь справиться с опциями оптимизации это твоя личная проблема и недостаток знаний. Я выше поэтому и написал, что способов дофига.

Добавлено через 15 минут 54 секунды
Evg, да, тьфу...
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <stdlib.h>
 
int main()
{
   asm ("jmp l");
   int a = rand();
   if (a!=-1)
   {
    return 0;
   }
   asm ("l:");
   printf("Error\n");
   return 1;
}
На стадии компиляции он не будет считать тебе rand. Все будет работать даже на O3. 100% рабочий на любой версии гсс. Это один из примеров.
Ладно, я привел уже два рабочих примера. Сами разбирайтесь со спинами там, где и без легко можно обойтись.
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
02.06.2009, 13:04 49
См. комментарии около ассемблерных конструкций и поправьте код, если написал неправильно:

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
unsigned __attribute__((fastcall))
iFactorial (unsigned n)
{
  /* Поместим в %eax, т.к. на этом регистре происходит возврат значения */
  register unsigned res asm ("%eax") = 1;
 
  asm ("  testl %[op_n], %[op_n]\n\t"  /* сравнение n с нулём */
       "  je    2f\n\t"                /* если n==0, то переход на метку 2*/
       "1:\n\t"
       "  imull %[op_n], %[op_res]\n\t"  /* op_res = op_res * op_n */
       "  jc    3f\n\t"                /* в случае переполнения переход на метку 3 */
       "  decl  %[op_n]\n\t"           /* op_n-- */
       "  jne 1b\n\t"                  /* если op_n не равен нулю, переход на метку 1 */
       "2:\n\t"                        /* эта точка соотвествует концу вставки */
       "  .subsection 1\n\t"           /* с этого места код будет помещён в конце сегмента кода */
       "3:\n\t"
       "  movl $0, %[op_res]\n\t"      /* записываем 0 в op_res */
       "  jc   2b\n\t"                 /* безусловный переход на 2 (не знаю, какая инструкция, поставил jc) */
       "  .previous"
       : [op_res] "+&r" (res) : [op_n] "r" (n));
 
  return res;
}
Код
$ gcc t.c -O2 -fomit-frame-pointer -c
$ objdump -d t.o
00000000 <iFactorial>:
   0:   b8 01 00 00 00          mov    $0x1,%eax
   5:   85 c9                   test   %ecx,%ecx
   7:   74 08                   je     11 <iFactorial+0x11>
   9:   0f af c1                imul   %ecx,%eax
   c:   72 04                   jb     12 <iFactorial+0x12>
   e:   49                      dec    %ecx
   f:   75 f8                   jne    9 <iFactorial+0x9>
  11:   c3                      ret
  12:   b8 00 00 00 00          mov    $0x0,%eax
  17:   72 f8                   jb     11 <iFactorial+0x11>
return делается в команде 11. Случай переполнения трактуем как редкоисполняемый код, а потому там два перехода (зато нет лишних переходов при исполнении основного кода). Можно наложить дополнительное ограничение - входной параметр не должен равняться нулю. В этом случае выкидываем первые две операции вставки (проверка аргумента на равенство нулю)

Добавлено через 5 минут 13 секунд
Цитата Сообщение от Vourhey Посмотреть сообщение
На стадии компиляции он не будет считать тебе rand. Все будет работать даже на O3. 100% рабочий на любой версии гсс.
Ога, вылизываем процедуру из 10 тактов и для обмана компилятора дёргаем процедуру, которая исполняется несколько сотен или тысяч тактов

Добавлено через 2 минуты 42 секунды
Цитата Сообщение от Vourhey Посмотреть сообщение
Выше я написал код, который будет работать. Если ты не можешь справиться с опциями оптимизации это твоя личная проблема и недостаток знаний.
Я тебе уже написал, что с опциями оптимизации код не будет работать. Если ты уже забыл, то постановка задачи не в том, чтобы написать код, который хоть как-то работал, а код с предельной производительностью

Цитата Сообщение от Vourhey Посмотреть сообщение
Я выше поэтому и написал, что способов дофига.
Тем не менее пока ещё не привёл ни одного рабочего кода. Код, который не работает в режиме с оптимизациями, рбочим не считается
0
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
02.06.2009, 13:29 50
Блин, ты че, думать разучился. Его рабочим сделать проще простого. Выше смотри, слепой.
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
02.06.2009, 13:39 51
Цитата Сообщение от Vourhey Посмотреть сообщение
Блин, ты че, думать разучился. Его рабочим сделать проще простого. Выше смотри, слепой.
Если ты имеешь в виду код с rand'ом, я тебе уже объяснил, по какой причине он не канает
0
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
02.06.2009, 13:43 52
Все канает. Достаточно вставить любой код, который компилер не сможет обработать на стадии компиляции и он попадет в бинарь. Я дал рабочую идею. Пример рабочий привел. Башка есть? Значит, доделаешь.
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
02.06.2009, 13:48 53
Цитата Сообщение от Vourhey Посмотреть сообщение
Все канает.
Тогда приведи код для поставленной задачи, потому как начинается детский сад и словесная перепалка: "канает" - "не канает"

Постановка была такая: Функция должна считать факториал и при переполнении возвращать 0. Хотелось сделать максимально быструю, насколько возможно
0
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
02.06.2009, 14:05 54
Детский сад, я тебе выше привел код, который будет работать.
Если решать вопрос о нахождении факториала, то я бы вообще так не извращался в метками, прыжками из ассемблерных вставок, и возни с оптимизацией. Если решать только посталенную задачу, то все элементарно, безо всяких извращений с прыжками, которыми заразили с самого начала.

Добавлено через 1 минуту 26 секунд
Тогда самый обычный чистый ассемблерный код все решает.

Добавлено через 5 минут 41 секунду
Короче, если брать решение именно задачи с факториалом, то все вещи здесь описанные нами на фиг не нужны.
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
02.06.2009, 14:16 55
Цитата Сообщение от Vourhey Посмотреть сообщение
Детский сад, я тебе выше привел код, который будет работать.
Ещё раз говорю. Постановка задачине в том, чтобы написать работающий код, а в том, чтобы сделать код максимально быстрым

Цитата Сообщение от Vourhey Посмотреть сообщение
Если решать вопрос о нахождении факториала, то я бы вообще так не извращался в метками, прыжками из ассемблерных вставок, и возни с оптимизацией.
Тут не просто факториал, а с переполнением. Чисто теоретически переполнение вроде бы как ловится по факту того, что после умножения число стало меньше, но из-за слабости с математикой на 100% я в этом не уверен. Как ещё по другому отловить переполнение я не знаю. Да и опять-таки вопрос не в "простонахождении факториала", а в предельной скорости кода (собственно из-за чего Ultrator и завёл эту тему)

Цитата Сообщение от Vourhey Посмотреть сообщение
Если решать только посталенную задачу, то все элементарно, безо всяких извращений с прыжками, которыми заразили с самого начала.
Прыжки вылезли из-за того, что нужно отловить факт преполнения

Цитата Сообщение от Vourhey Посмотреть сообщение
Тогда самый обычный чистый ассемблерный код все решает.
А я к этому уже давно веду. Но чистый ассемблер я бы писать не стал по нескольким причинам:
1. В этом месте надо понимать программные соглашения (хотя я косвенно это зацепил, принудительно распределив res на регистр %eax)
2. Код на ассемблере уже нельзя будет inline'ить. Код написанный в виде процедуры обкладки плюс ассемблерная вставка - можно. Вообще высокопроизводительные библиотеки на этом базируются - строятся такие примитивные кирпичики в виде коротких процедур, далее строится нужное тебе большое выражение, состоящее из этих кирпичиков, а далее компилятор всё это дело по возможности оптимальным образом схлопывает. Единственно, что gcc далеко не всегда сделает это максимально оптимальным образом (мы с тобой уже это обсуждали), а потому без доработки напильником иногда не обойтись. При этом всегда нужно чётко осознавать, что код должен быть корректным. И по возможности избегать читов, которые я приводил с asm entry

Цитата Сообщение от Vourhey Посмотреть сообщение
Короче, если брать решение именно задачи с факториалом, то все вещи здесь описанные нами на фиг не нужны.
Я на 99% уверен, что Ultrator'у нахер не сдался этот факториал. Ему нужно понять, как реализовывать подобные вещи
0
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
02.06.2009, 14:33 56
Ну вопрос максимальной скорости, это уже другой вопрос. Тогда не понимаю, зачем вообще нам понадобились джампы через сишный код? Смысла нет, по сути, в таком подходе изначально.
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
02.06.2009, 14:35 57
Цитата Сообщение от Vourhey Посмотреть сообщение
Тогда не понимаю, зачем вообще нам понадобились джампы через сишный код?
Ну как... таким образом он пытался построить "return 0" в случае переполнения, ибо никаких других идей у него не было
0
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
02.06.2009, 14:37 58
Прыжки вылезли из-за того, что нужно отловить факт преполнения
Да это понятно. Просто подход мне лично кажется неправильным. Стоило так мудрить ему все это дело, asm, return, asm return...heh

Добавлено через 1 минуту 59 секунд
Ладно, код на асме ты ему вроде написал. Способ оставить метку у него теперь тоже есть. Все зашибись
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
02.06.2009, 14:41 59
Цитата Сообщение от Vourhey Посмотреть сообщение
Просто подход мне лично кажется неправильным. Стоило так мудрить ему все это дело, asm, return, asm return...heh
Если бы я не разбирался в том, как работают компиляторы - я бы смог изобрести только дополнительный вариант с двумя goto. А здесь фактически появился лишь один дополнительный переход

Кстати. в моём коде на ассемблере в самом конце можно сделать "ret" вместо перехода на метку "2", но это менее честный вариант, т.к. он коряво отработает в том случае, если процедура про'inline'иться (ну и не говоря уж о том, что это гораздо более явное использование знаний о программных соглашениях, а потому способ менее честный)
0
14 / 10 / 1
Регистрация: 28.04.2009
Сообщений: 219
02.06.2009, 14:52  [ТС] 60
Наконец, понял я, в чём проблема.
В том, что он её инлайнит.
Только и всего.
Если ф-ю не вызывать нигде - всё пучком, хоть с оптимизацией, хоть без.
Вот попробуйте...
0
02.06.2009, 14:52
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
02.06.2009, 14:52
Помогаю со студенческими работами здесь

Asm вставки в AVR GCC
Есть у кого-то описание как писать эти _страшные_ вещи? Конструкция подразумевающая всего лишь swap...

STM32 + ASM + arm-none-eagi-gcc = непонятки
Скачал я с сайта ARM документик &quot;Sortix -M3 Devices Kimeric User Guide&quot;. Смотрю там раздел &quot;The...

Использование внешних переменных в asm вставке и компиляцией gcc
Есть такой код для выполнения операций со входной строкой (функциональная часть сейчас неважна): ...

Реализовать 2 функции с использованием языка C и конструкции asm компилятора gcc
формат binary16 стандарта IEEE 754-2008. В прототипах функций, приведённых ниже, обозначается как...


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

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