LINUX.ORG.RU

Метки в ассмблерных вставках


0

0

Столкнулся с проблемой использования меток во встроенном ассемблере.
При попытки компилировать вот эту процедуру:

/*-------------------------------------------------------*/
/* аналог паскалевской функции pos */
/*-------------------------------------------------------*/
// для совместимости с C99 нужно extern inline
extern inline short int strpos(char ch1,char * s1,const char n1);

inline short int strpos(char ch1,char * s1,const char n1)
{ //регистры вроде не надо сохранять так как они по идеи не должны портить
// потомучто функция инлайн
register short int lng;
__asm__ ( "push %edi"); //без volatile при оптимизации ошибки
__asm__ ( "mov %0,%%edi"::"r"(s1));
__asm__ __volatile__ ( "\
mov $0x00FF,%%cx;\
mov %2,%%al;\
cld;\
repne scasb;\
not %%cl;\
cmp %1,%%cl;\
ja _slbl1;\
mov %%cx,%0;\
jmp _slbl2;\
slbl1:\
mov $0xffff,%0;\
slbl2:\
nop;":"=r"(lng):"r"(n1),"r"(ch1));
__asm__ ( "pop %edi");
return lng;
}
Компилятор раньше не ругался а теперь ругается на метки.
/home/yura/my_progr.cpp/snifflog/source/mysnlog.c:61: Error: symbol `slbl1' is already defined
/home/yura/my_progr.cpp/snifflog/source/mysnlog.c:61: Error: symbol `slbl2' is already defined


Использовать обычный ассемблер не очень хочется. Там нужно будет разбираться с соглашениями о вызовах и както указывать ему(компилятору) что нужно использовать именно это соглашение. Но если подругому никак то вообщем можно и отдельный ассемблерный файл. Главное найти пакет установки а то мне KDevelop пишит что не может найти CCAS и я не могу его найти с помощью менеджера пакетов. Вообщем одни сплошные грабли.
А так хотелось сделать аналог паскалевской функции pos в Си.

> //регистры вроде не надо сохранять так как они по идеи не должны портить

Надо в конце asm'а указывать список изменяемых регистров, помимо входных и выходных, а компилятор уж сам разберётся, что с ними делать.

const86 ★★★★★
()
Ответ на: комментарий от const86

> //регистры вроде не надо сохранять так как они по идеи не должны портить

спасибо, учту. Может и как с метками быть знаете ?

Baltika80
() автор топика
Ответ на: комментарий от const86
inline short int strpos(char ch1, char *s1, const char n1) {
	short int lng;
	asm volatile (
		"mov %3, %%edi\n"
		"mov $0x00FF,%%cx\n"
		"mov %2,%%al\n"
		"cld\n"
		"repne scasb\n"
		"not %%cl\n"
		"cmp %1,%%cl\n"
		"ja slbl1\n"
		"mov %%cx,%0\n"
		"jmp slbl2\n"
		"slbl1:\n"
		"mov $0xffff,%0\n"
		"slbl2:\n"
		"nop\n"
		: "=r" (lng)
		: "r" (n1), "r" (ch1), "r" (s1)
		: "edi");
	return lng;
}
const86 ★★★★★
()

Метки в стиле Кнута еще никто не отменял,
они оптимальны для вставок,
пример на ассемблере:

jmp 1f // Переход к следующему 1:
2:
....
jmp 2f // Переход к следующей 2:
1:
....
jmp 2b // Переход к предыдущей 2:
2:
jmp 1b // Переход к предыдущей 1:

io ★★
()
Ответ на: комментарий от const86

>inline short int strpos(char ch1, char *s1, const char n1) {
> short int lng;
> asm volatile (
> "mov %3, %%edi\n"
> "mov $0x00FF,%%cx\n"
> "mov %2,%%al\n"
> "cld\n"
> "repne scasb\n"
> "not %%cl\n"
> "cmp %1,%%cl\n"
> "ja slbl1\n"
> "mov %%cx,%0\n"
> "jmp slbl2\n"
> "slbl1:\n"
> "mov $0xffff,%0\n"
> "slbl2:\n"
> "nop\n"
> : "=r" (lng)
> : "r" (n1), "r" (ch1), "r" (s1)
> : "edi");
> return lng;
>}


Я человек не гордый, а потому сдела копи-пейст с вашего примера.
И вот результат:
/home/yura/my_progr.cpp/snifflog/source/mysnlog.c: In function 'strpos':
/home/yura/my_progr.cpp/snifflog/source/mysnlog.c:82: error: 'asm' undeclared (first use in this function)
/home/yura/my_progr.cpp/snifflog/source/mysnlog.c:82: error: (Each undeclared identifier is reported only once
/home/yura/my_progr.cpp/snifflog/source/mysnlog.c:82: error: for each function it appears in.)
/home/yura/my_progr.cpp/snifflog/source/mysnlog.c:82: error: expected ';' before 'volatile'
-------------------------------------------------
Но я готов исправить ошибки в компиляторе :)

А символ "_" появился в метке в 101й итерации по модификации этой метки.
Без него тоже не компилировалось.
И непонятно почему виноват препроцессор ? Символ склейки строки "\" у нас препроцессор помнится обрабатывает.
Символ ";" взят из примера из руководства gcc по встроенному ассемблеру.
http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html

И главное: раньше когда писал просто asm ... всёработало, причём работало правильно и никаких ошибок с метками небыло. А щас хоть asm хоть __asm__ всё без толку. с __asm__ он хоть ругается меньше.

Baltika80
() автор топика
Ответ на: комментарий от io

>Метки в стиле Кнута еще никто не отменял,
Спасибо, сработало, но вопросы остались.
Почему раньше компилилось с любыми метками а щас только так как Вы указали.
Раньше я использовал asm(...)
А теперь он воспринимает только __asm__(...)
Неужто во всём C99 виноват ?

Baltika80
() автор топика
Ответ на: комментарий от io

Метки в стиле Кнута еще никто не отменял,

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

const86 ★★★★★
()
Ответ на: комментарий от const86

>Пожалуй, тут так и надо делать, потому что обычные метки из-за
>инлайна могут дублироваться. А вообще, куча кода в ассемблерной
>вставке, да ещё и с инлайном...

Ассемблер выбрал изза того что функция ИМХО должна быть частью STL.
Но такую функцию я там не нашёл. Можно конечно сделать её из нескольких STL-ых или с помощью циклов и указателей, но это криво изза того что есть ассемблерная инструкция scasb которая и предназначена для этой задачи, а компилятор едвали догадается при оптимизации что хотел автор.
Обычные метки раньше не дублировались пока не было C99 mode. Не уверен что дело в нём, но других вариантов не вижу.

Baltika80
() автор топика
Ответ на: комментарий от Baltika80

Ассемблер выбрал изза того что функция ИМХО должна быть частью STL.

Всё смешалось в доме Облонских. Объясняем использование ассемблера поперёк C отсутствием функции в библиотеке C++. Может, лучше использовать strchr или memchr?

есть ассемблерная инструкция scasb которая и предназначена для этой задачи, а компилятор едвали догадается при оптимизации что хотел автор.

Не надо считать себя сильнее компилятора.

А щас хоть asm хоть __asm__ всё без толку. с __asm__ он хоть ругается меньше.

Действительно, в режиме C99 asm не работает, ну пусть будет __asm__, это всё мелочи.

И непонятно почему виноват препроцессор ? Символ склейки строки «\» у нас препроцессор помнится обрабатывает.

Да просто не пишут так. Ассемблерный код пишут в столбик, а не в строчку. Так почему во вставках надо делать наоборот? Да ещё и привлекать к этому препроцессор.

Символ ";" взят из примера из руководства gcc по встроенному ассемблеру.

Почти во всех примерах там используется «\n\t». А остальные примеры компилируются только в голове.

const86 ★★★★★
()
Ответ на: комментарий от const86

>Всё смешалось в доме Облонских. Объясняем использование ассемблера поперёк C отсутствием
>функции в библиотеке C++. Может, лучше использовать strchr или memchr?


Спасибо за ликбез. Для меня STL была просто стандартная библиотека языков Си/Си++. А как тогда ? так "Стандартная библиотека языка СИ" ?
Что до функции то я привык к паскалевской pos. Ваш вариант тоже рассматривал. Можно брать разность указателей используя предложенные вами функции, хотя это возможно может быть чревато изза особенностей виртуальной памяти. Не в коем случае не считаю себя "сильнее" компилятора, но решил что быстрее написать на ассмблере чем думать как написать на Си чтобы компилятор как надо это соптимизировал на урове машинных инструкций. Попробую канибудь и Ваш вариант. Возможно он действительно умнее чем я думаю.


>Почти во всех примерах там используется "\n\t". А остальные примеры компилируются только в голове.

У меня как видите не используются "\n\t" и компилируется мой пример не только в голове.
Если заглянуть сюда: http://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html
то тоже можно увидеть например это:
int frob(int x)
{
int y;
asm goto ("frob %%r5, %1; jc %l[error]; mov (%2), %%r5"
: : "r"(x), "r"(&y) : "r5", "memory" : error);
return y;
error:
return -1;
}
Как видите никакого столбика.

>Да просто не пишут так. Ассемблерный код пишут в столбик, а не в >строчку. Так почему во вставках надо делать наоборот? Да ещё и >привлекать к этому препроцессор.


Спасибо что просветили. Я раньше думал что только я пишу в столбик. Теперь я буду знать что это делают все. Что касается привлечения препроцессора то просто быстрее написать ";\" чем "\n\t"".
Насколько я помню, стиль "столбик" принят в ассемблере для удобства восприятия и имеет значения соответсвенно только в текстовом редакторе. Хотя конечно более строгий стиль порой предохраняет от ошибок.

>Действительно, в режиме C99 asm не работает, ну пусть будет __asm__, это всё мелочи.

Порой такие мелочи отнимаю не один час времени, хотя в данном случае
я нашёл ответ быстрее.
уже не помню где увидел просто #define __asm __ asm

Baltika80
() автор топика
Ответ на: комментарий от Baltika80

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

Если ты пишешь на асме не из-за понтов, а по делу, то попровать тебе надо не "как-нибудь", а сразу же.

<nostradamus_mode>и компилятор порвет твой асм (при правильных ключах компиляции), поскольку repne scasb будет работать не быстрее обычного цикла, а вместо твоих условных джампов компилятор поставит пересылку в регистр по условию</nostradamus_mode>

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

Лениво мне было подбирать ключи изза какойто мелкой функции, а ассемблер решил использовать во первых изза того что вспомнил про repne scasb, во вторых изза того что функция скорей всего будет нужна и дальше и поэтому лучше её "вылезать"и положить в какуюнить свою библиотеку, в третьих просто было интересно познакомиться с ассемблером в линксе. Про услорвную пересылку чтото помню, но на ассемблере не писал лет 5. За это время те инструкции которые раньши были "экзотикой" стали повседневностью.


Baltika80
() автор топика
Ответ на: комментарий от Baltika80

да кстати.
из "понтов" предпочитаю голых женьщин, но никак не ассемблер :)

Baltika80
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.