c - Linux 内核中的 asm__volatile()

标签 c gcc x86 linux-kernel inline-assembly

谁能解释一下这个函数到底在做什么,我试着用谷歌搜索它,但什么也没找到:

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",
);

提前感谢任何解释

最佳答案

一步一步来:

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指的是内联汇编的“constraints”中提到的第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 可以将内联汇编程序 block 使用和产生的输入和输出值放在哪里。第一部分(在第一个 : 之后)用于输出。 "=m" 表示 __res 应该保存在内存中 ("m") 并且它是只写的,即任何以前的值将被覆盖 ("=")。约束中的操作数可以通过内联汇编 block 中的数字引用(例如 %0),从第一个出现的 0 开始。

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

... 下一部分用于输入。这表示它们将全部放在内存中。

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

...这最后一部分表示“被破坏的”寄存器,即那些将被内联汇编程序 block 内的代码覆盖的寄存器。 GCC 会将内联汇编程序 block 放入它生成的其他代码的中间,但它不知道 block 内的指令实际上做了什么 - 所以你必须告诉它在这些寄存器中可能已经存在的任何值之后 block 将不再有效。

);

关于c - Linux 内核中的 asm__volatile(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5572832/

相关文章:

c++ - 我需要帮助来理解这个 openMP 示例

c - 运行程序时出错 "Segmentation fault core dumped"

python - 如何将质询密码编码到证书请求中

c - GCC 链接器无法找到库

c++ - 使用 Eigen 的插件在第二次运行时崩溃

c++ - 使用 XNAMATH 优化堆栈分配的对象

c - 删除 1 0's from an array, replaces 10' 和 0 的函数。将所有剩余元素移至数组开头

c - 相当于 LD_PRELOAD 的 gcc 标志?

assembly - 在汇编程序中交换最高有效字节和最低有效字节

c - 启用/禁用硬件锁省略