Linux 内核中的 asm__volatile()

发布于 2024-10-31 03:54:51 字数 348 浏览 0 评论 0原文

有人可以解释一下这个函数到底在做什么吗?我尝试用谷歌搜索,但什么也没找到:

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

提前感谢您的任何解释

can somebody please explain what exactly this function is doing, I tried to google it, but found nothing:

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

thanks in advance for any explanation

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

饮惑 2024-11-07 03:54:51

逐步执行此操作:

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 系统调用 只需要一个参数...)

"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 会将内联汇编器块放入它生成的其他代码的中间,但它不知道块内的指令实际执行的操作 - 因此您必须告诉它在这些寄存器中可能存在的任何值此后区块将不再有效。

);

Taking this step by step:

long __res; //some variable

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

... system calls for 32-bit x86 Linux are selected by the value in %eax. This is the number of the get_thread_area syscall. See arch/x86/include/asm/unistd_32.h (in recent kernels at least) for the list of syscall numbers. (Note: syscall numbers are not the same between 32-bit and 64-bit.)

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

... parameters to system calls are passed in registers. For 32-bit x86, up to five parameters are passed in registers, in the order %ebx, %ecx, %edx, %esi, %edi (the 6th argument, for the few syscalls that need it, is passed on the user stack). %1, %2, %3 refer to the 2nd, 3rd and 4th items mentioned in the "constraints" for the inline assembler (see below).

(This seems slightly odd, by the way: the get_thread_area syscall only needs one argument...)

"int $0x80;"

... invokes the syscall.

"movl %%eax,%0"

... syscalls return a result in %eax; the %0 refers to the first item mentioned in the constraints.

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

... "constraints" tell gcc where it can put the input and output values that are used and produced by the inline assembler block. This first section (after the first :) is for outputs. "=m" here says that __res should be held in memory ("m") and that it is write-only, i.e. any previous value will be overwritten ("="). Operands in constraints can be referred to by numbers in the inline assembly block (e.g. %0), starting from 0 for the first to appear.

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

... this next section is for inputs. This says that they will all be placed in memory.

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

... this final section indicates "clobbered" registers, i.e. those that will be overwritten as a result of code inside the inline assembler block. GCC will put the inline assembler block into the middle of other code that it generates, but it doesn't know what the instructions inside the block actually do - so you have to tell it that any values that may have been in those registers before the block will no longer be valid afterwards.

);
智商已欠费 2024-11-07 03:54:51

该函数正在执行系统调用(由于 x86 int 0x80)。

您标记的部分是 GCC 内联汇编器帮助程序 - 它允许 GCC 将占位符 (%0-%3) 更改为 C 名称给出的实际值,在本例中为 __res, a, b, c< /代码>。

您可以在此处阅读有关确切的内联汇编器语法的信息:

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

That function is performing a syscall (due to the x86 int 0x80).

The part you flagged is the GCC inline assembler helpers - which allows GCC to change the placeholders (%0-%3) to actual values as given by a C name, in this case, __res, a, b, c.

You can read about the exact inline assembler syntax here:

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

梦在深巷 2024-11-07 03:54:51

您可以在这里找到有关 gcc 内联汇编语法所需的所有信息:

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

You can find all the info you need about the gcc inline assembly syntax here:

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文