inline assembler gcc

Вопросы программного кода и архитектуры Linux

Модератор: Olej

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: inline assembler gcc

Непрочитанное сообщение Olej » 28 фев 2012, 19:07

Olej писал(а):... а вот это как-то мучительно медленно :cry:
Но получилось в конце концов ;-)

Очень хорошая книжка (уже успел бегло пробежать), даже такие вещи свежие как:
...
Control registers
...
Multimedia extensions (MMX)
...
Streaming SIMD extensions (SSE)
...
Из недостатков (не этого автора, потому как "нельзя объять необъятное" - но то, что хотелось бы видеть):
1. описывается ассемблер исключительно для Inteel x86, хотя AT&T/GAS покрывают куда более широкий перечень платформ процессорных;
2. описываются только IA-32 процессоры, про IA-64 ни слова, хотя там даже регистры будут по-другому записываться: %rax вместо %eax, а для AMD_64 даже число и назначение регистров будет другое, чем у Intel IA-64.

bose
Писатель
Сообщения: 107
Зарегистрирован: 23 фев 2012, 14:41
Откуда: Киев
Контактная информация:

Re: inline assembler gcc

Непрочитанное сообщение bose » 29 фев 2012, 14:30

Olej писал(а):Из недостатков (не этого автора, потому как "нельзя объять необъятное" - но то, что хотелось бы видеть):
1. описывается ассемблер исключительно для Inteel x86, хотя AT&T/GAS покрывают куда более широкий перечень платформ процессорных;
2. описываются только IA-32 процессоры, про IA-64 ни слова, хотя там даже регистры будут по-другому записываться: %rax вместо %eax, а для AMD_64 даже число и назначение регистров будет другое, чем у Intel IA-64.
Интересная тема. Вот как раз может быть это замечание послужит поводом расрыть следующий вопрос. Читал главу из вашей книги "Библиотечный и системный вызов из процесса" - http://rus-linux.net/MyLDP/BOOKS/Moduli ... -02.html#1, и решил разобрать пример (mp.c) дабы освежить в памяти синтаксис Inline Assembler. После запуска программы пришёл в замешательство. Вывод был неожиданным:
getpid return : -14
string for write length = 23
Что удивило - ладно пусть программа завершается неожиданно, но почему нет сообщений об ошибке? Взял её strace'ом - вывод натолкнул на размышления:
getpid() = -1 EFAULT (Bad address)
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fcc25c77000
write(1, "getpid return : -14\n", 20getpid return : -14
) = 20
write(1, "string for write length = 23\n", 29string for write length = 23
) = 29
write(1, 0x1, 23 <unfinished ... exit status 1>
Т.е. в первом случае (getpid) - -1 EFAULT (Bad address), во втором (write) - unfinished ... exit status 1. Смутило ещё значение второго аргумента в write (0x1)....
Вобщем, гугл как всегда знает всё. Выяснилось, что у x86 и x86_64 (моя рабочая машина на которой я выполнял код) разные механизмы системного вызова.

Пришлось изменить участки кода с Inline Assembler:
например

Код: Выделить всё

int write_call( int fd, const char* str, int len ) {
   long __res;
   __asm__ volatile ( "int $0x80":
      "=a" (__res):"0"(__NR_write),"b"((long)(fd)),"c"((long)(str)),"d"((long)(len)) );
   return (int) __res;
}
изменил на

Код: Выделить всё

int write_call( int fd, const char* str, int len ) {
   long __res = 0;
   __asm__ __volatile__ (
		   "syscall":
		   "=a" (__res):
		   "a"(__NR_write),"D"((long)(fd)),"S"((long)(str)),"d"((long)(len))
	);
   return (int) __res;
}
Вопрос решён, но в голове остался сумбур в виде кучи вопросов. Олег, вы как то можете осветить эту тему (касательно этих механизмов), или ссылкой кинуть где данный вопрос раскрыт.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: inline assembler gcc

Непрочитанное сообщение Olej » 29 фев 2012, 16:05

bose писал(а): Вобщем, гугл как всегда знает всё. Выяснилось, что у x86 и x86_64 (моя рабочая машина на которой я выполнял код) разные механизмы системного вызова.
А это безусловно!
В тексте по ядру Linux это как-то где-то отмечалось ... может оно смазано прозвучало :(
Там даже регистры по-другому будут записываться: %eax -> %rax
bose писал(а): Пришлось изменить участки кода с Inline Assembler:
...
изменил на

Код: Выделить всё

int write_call( int fd, const char* str, int len ) {
   long __res = 0;
   __asm__ __volatile__ (
		   "syscall":
		   "=a" (__res):
		   "a"(__NR_write),"D"((long)(fd)),"S"((long)(str)),"d"((long)(len))
	);
   return (int) __res;
}
Вопрос решён, но в голове остался сумбур в виде кучи вопросов. Олег, вы как то можете осветить эту тему (касательно этих механизмов), или ссылкой кинуть где данный вопрос раскрыт.
вообще то, этот мой код - это только иллюстрация, так делать не следует:
- и "int $0x80" использовалось только до определённого времени, а потом "sysenter" (я имеено sysenter видел в коде Linux, а у вас syscall? можете сказать что-то по этому поводу?)
- и это механизм непереносимый, и на другой платформе всё будет совсем по-другому...
- есть гораздо более цивильный способ непрямого системного вызова:

Код: Выделить всё

   int n = syscall( __NR_write, str, strlen( str ) );
- особенно это нормально для своих, новых системных вызовов ... плюс это переносимо между платформами.

bose
Писатель
Сообщения: 107
Зарегистрирован: 23 фев 2012, 14:41
Откуда: Киев
Контактная информация:

Re: inline assembler gcc

Непрочитанное сообщение bose » 29 фев 2012, 16:49

Olej писал(а): Там даже регистры по-другому будут записываться: %eax -> %rax
Как видно из изменённого участка кода - на 64 в системном вызове учавствуют даже другие регистры (*SI,*DI вместо *BX,*CX)
Olej писал(а): (я имеено sysenter видел в коде Linux, а у вас syscall? можете сказать что-то по этому поводу?)
Могу только развести руками, так как сам в недоумении (тоже читал что sysenter, но когда незаработало поменял на syscall и, как говорят французы, voila).
Вкратце, что нарыл по вопросу (прежде скажу что у меня на рабочей машине - Intel(R) Core(TM)2 Duo CPU E8500, 3.0.0-16-generic #28-Ubuntu SMP x86_64 x86_64 x86_64 GNU/Linux):
  • Для X86: sysenter - I think this instruction is specific to Intel CPUs. syscall - This instruction is specific to AMD CPUs. Для x64 (aka X86_64, amd64): syscall - Both AMD and Intel use the syscall instruction. Взято от сюда http://esec-lab.sogeti.com/post/2011/07 ... yscall-ABI
  • On Pentium II there is the sysenter instruction. Also AMD has a syscall instruction. Взято от сюда - http://www.win.tue.nl/~aeb/linux/lk/lk-4.html
  • Documentation/x86/entry_64.txt - бесспорно, я не силён в английском, но думаю в данном послании тема не расскрывается.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: inline assembler gcc

Непрочитанное сообщение Olej » 07 май 2014, 14:02

bose писал(а):Вопрос решён, но в голове остался сумбур в виде кучи вопросов. Олег, вы как то можете осветить эту тему (касательно этих механизмов), или ссылкой кинуть где данный вопрос раскрыт.
Там вообще произошли какие-то новшества, даже в синтаксисе записи инлайн ассемблерных вставок GCC.
Мне в новой группе семинара по модулям ядра подсказали: ARM GCC Inline Assembler Cookbook.
Это ARM архитектура, но большого значения не имеет ... зато 2014 год ;-)
Но я ещё это обстоятельно не смотрел.

Кроме того, оттуда ссылка на шикарную подборку документации по GCC самой разнообразной: GCC online documentation.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: inline assembler gcc

Непрочитанное сообщение Olej » 27 май 2016, 19:09

Новая (30 апреля 2016) большая публикация по ассемблерным вставкам Ассемблерные вставки в GCC (это 1-я страница, а там их последовательно 5):
Хоть и немного сумбурно, но зато обстоятельно ;-)

Ответить

Вернуться в «Linux изнутри»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 0 гостей