一步一步来:
long __res; //some variable
__asm__ volatile (
"movl $244, %%eax;"
... 32 位 x86 Linux 的系统调用由 %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 系统调用only needs one argument...)
"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 会将内联汇编程序块放入它生成的其他代码的中间,但它不知道块内的指令实际上是做什么的 - 所以你必须告诉它在这些寄存器中可能存在的任何值之前块之后将不再有效。
);