Ядерная нестыковочка

Aug 14, 2017 13:54

В процессе программирования модулей ядра Linux нередко приходится прибегать к помощи ассемблера. Традиционно разработчики ядра используют встроенный ассемблер GCC (который по сути является шлюзом в GAS), но у этого подхода есть куча недостатков, что вызывает желание использовать посторонний ассемблер и раздельную трансляцию. Кстати, знаменитый Свен Шрайбер в своей книги по ядру Винды пишет, что он на этом пути наловил столько BSOD'ов, что в итоге остановился на встроенном же ассемблере. А встроенный ассемблер в Visual C++ имхо намного лучше своего аналога в GCC. Да и раздельная трансляция (как и вообще написание модулей ядра) в Linuxe намного проще.
Но я сначала решил просто поэкспериментировать и написать простенькую функцию на асме и интегрировать её в код на Си.
Пишем функцию:


  1. madd:

  2. push ebp

  3. mov ebp, esp

  4. mov eax, [ebp+8]

  5. add eax, [ebp+12]

  6. pop ebp

  7. ret

Этот простенький "сумматор" вставляем в код нашего модуля:


  1. #include

  2. #include

  3. extern int madd(int, int);

  4. int init_module(void)

  5. {

  6. printk(KERN_ALERT "Summa 11 i 6 ravna %d\n", madd(11,6));

  7. return 0;

  8. }

После компиляции и загрузки модуля все срабатывает, но результат получается сильно не похожим на 17.
Дизассемблер выдаёт нечто совершенно невменяемое. А именно, вызов функции madd осуществляется вот так:


  1. mov eax, 6

  2. mov edx, 0Bh

  3. call madd

То есть вызов, вопреки ожиданиям, никак не соответствует си-соглашению, о чём вызываемая функция конечно не догадывается, возвращая в итоге "винигрет".
Скорее всего проблема в оптимизации, но как заставить GCC НЕ оптимизировать этот участок кода? Фактически мне удалось решить эту проблему, заменив объявление функции madd, незаконно приписав ей переменное число параметров.


  1. extern int madd(int, ...);

В итоге компилятор утихомирился и передал параметры как положено - через стек.
Но никто не гарантирует этого в общем случае, поэтому очень хотелось бы знать, как обязать GCC следовать строго соглашению cdecl.

непонятки, #include, *nix, быдлокодинг

Previous post Next post
Up