在system_call中保存在堆栈上的寄存器

时间:2015-06-29 12:38:14

标签: linux-kernel system-calls

当调用system_call函数时,它应该检查一些参数并根据eax中传递的参数调用系统调用表中指向的函数。这是保存寄存器的部分:

system_call:
pushl %eax
SAVE_ALL
movl $0xffffe000, %ebx /* or 0xfffff000 for 4-KB stacks */
andl %esp, %ebx

为什么它会两次保存eax? (在命令pushl%eax和宏SAVE_ALL中也保存eax)。

1 个答案:

答案 0 :(得分:1)

x86-32上的标准C调用约定使用%eax从函数返回值。 Linux系统调用还将其返回值传递回%eax中的用户空间。如何在x86-32上完成?

arch/x86/entry/entry_32.S中的系统调用入口点调用系统调用处理函数,然后覆盖存储的%eax(由SAVE_ALL存储的值)堆栈及其返回值。之后,当返回到用户空间时,所有寄存器的存储值将从堆栈弹出到寄存器中。由于%eax存储的SAVE_ALL值被所需的返回值覆盖,因此当用户代码恢复执行时,自然会在%eax中找到系统调用的返回值。

但有时内核需要找到原始保存的%eax值。即使SAVE_ALL保存的值已被覆盖,它仍然可以查看第一个pushl %eax保存的值。在内核代码中,此值称为orig_eax。 (Grep内核源代码,你会在几个地方找到它。)

查看RESTORE_REGS中的arch/x86/entry/entry_32.S宏,您会看到它需要一个pop参数,该参数用于在将所有已保存的寄存器值弹回寄存器后调整堆栈。您将在系统调用返回用户空间时找到RESTORE_REGS 4。那个“4”是为了摆脱你所询问的pushl %eax所推动的价值,也被称为orig_eax