Шаг за шагом:
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 поместит встроенный блок ассемблера в середину другого кода, который он генерирует, но он не знает, что на самом деле делают инструкции внутри блока - поэтому вы должны сказать ему, что любые значения, которые могли быть в этих регистрах допосле этого блок больше не будет действительным.
);