asm__volatile () в ядре Linux - PullRequest
       21

asm__volatile () в ядре Linux

2 голосов
/ 07 апреля 2011

может кто-нибудь объяснить, что именно делает эта функция, я пытался гуглить, но ничего не нашел:

long __res; //some variable

__asm__ volatile (
"movl $244, %%eax;"
"movl %1, %%ebx;"
"movl %2, %%ecx;"
"movl %3, %%edx;"
"int $0x80;"
"movl %%eax,%0"
: "=m" (__res) //from here can't understand
: "m" (a), "m" (b) , "m" (c)
: "%eax","%ebx","%ecx", "%edx",
);

заранее спасибо за любое объяснение

Ответы [ 3 ]

4 голосов
/ 07 апреля 2011

Шаг за шагом:

long __res; //some variable

__asm__ volatile (
"movl $244, %%eax;"

... системные вызовы для 32-разрядной Linux x86 выбираются значением в %eax.Это номер системного вызова get_thread_area.См. arch/x86/include/asm/unistd_32.h (по крайней мере, в последних ядрах) для списка номеров системных вызовов.(Примечание: номера системных вызовов не одинаковы между 32-разрядными и 64-разрядными.)

"movl %1, %%ebx;"
"movl %2, %%ecx;"
"movl %3, %%edx;"

... параметры для системных вызовов передаются в регистрах.Для 32-разрядных систем x86 в регистры передается до пяти параметров в следующем порядке: %ebx, %ecx, %edx, %esi, %edi (6-й аргумент для тех немногих системных вызовов, которым это необходимо,передается в стек пользователя).%1, %2, %3 относятся ко 2-му, 3-му и 4-му пунктам, упомянутым в «ограничениях» для встроенного ассемблера (см. Ниже).

(кстати, это кажется немного странным: get_thread_area системный вызов нужен только один аргумент ...)

"int $0x80;"

... вызывает системный вызов.

"movl %%eax,%0"

... возврат системных вызововрезультат в %eax;%0 относится к первому элементу, упомянутому в ограничениях.

: "=m" (__res) //from here can't understand

... «ограничения» указывают gcc, где он может поместить входные и выходные значения, которые используются и генерируются встроенным блоком ассемблера,Этот первый раздел (после первого :) предназначен для выходов."=m" здесь говорит, что __res должно храниться в памяти ("m") и что оно доступно только для записи, т.е. любое предыдущее значение будет перезаписано ("=").Операнды в ограничениях могут именоваться числами во встроенном сборочном блоке (например, %0), начиная с 0 для появления первого.

: "m" (a), "m" (b) , "m" (c)

... этот следующий раздел предназначен для входных данных.Это говорит о том, что все они будут помещены в память.

: "%eax","%ebx","%ecx", "%edx",

... в этом последнем разделе указаны «засоренные» регистры, т. Е. Те, которые будут перезаписаны в результате выполнения кода внутри встроенного блока ассемблера.GCC поместит встроенный блок ассемблера в середину другого кода, который он генерирует, но он не знает, что на самом деле делают инструкции внутри блока - поэтому вы должны сказать ему, что любые значения, которые могли быть в этих регистрах допосле этого блок больше не будет действительным.

);
3 голосов
/ 07 апреля 2011

Эта функция выполняет системный вызов (из-за x86 int 0x80).

Помеченная вами деталь - это встроенные помощники ассемблера GCC, которые позволяют GCC заменять заполнители (% 0-% 3) на фактические значения, заданные именем C, в данном случае __res, a, b, c.

Точный синтаксис встроенного ассемблера вы можете прочитать здесь:

http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html

0 голосов
/ 07 апреля 2011

Вы можете найти всю необходимую информацию о синтаксисе встроенной сборки gcc здесь:

http://www.ibm.com/developerworks/linux/library/l-ia.html

...