【问题标题】:Why does a syscall clobber rcx and r11? [duplicate]为什么系统调用会破坏 rcx 和 r11? [复制]
【发布时间】:2018-11-07 08:05:10
【问题描述】:

Low-Level Programming: C, Assembly, and Program Execution on Intel® 64 Architecture 的书中说,

关于系统调用参数 系统调用的参数存储在与函数不同的一组寄存器中。第四个参数存储在 r10 中,而函数接受 rcx 中的第四个参数!

原因是syscall指令隐式使用rcx。系统调用不能接受超过六个 论据。

你可以看到这个Stack Overflow post也提到了这个,

系统调用是通过 syscall 指令完成的。这会破坏 %rcx 和 %r11,以及 %rax,但会保留其他寄存器。

我理解破坏 rax 来存储返回码,但为什么 rcxr11syscall 中被破坏?是否有破坏 rcx/r11 的特定系统调用的列表?有没有关于破坏的约定?它们在任何系统调用中都被认为是安全的吗?

【问题讨论】:

  • syscall 这样做。没有堆栈切换,内核来不及了。

标签: linux assembly x86-64 system-calls


【解决方案1】:

syscall指令使用rcx存储下一条返回指令的地址,r11保存rflags寄存器的值。然后这些值将由sysret 指令恢复。

这是由 CPU 在执行 CPU 指令时完成的,因此任何特定于操作系统的调用约定都需要避免使用这些寄存器将参数传递给系统调用。

【讨论】:

  • 将rflags的值保存在r11中的目的是什么,而不是直接放在那里?
  • @EvanCarroll 调用返回时会恢复到 rflags。我认为这样做是为了恢复一些可能被内核代码更改的更重要的标志。
  • @EvanCarroll sysret 在将控制权交给操作系统之前也会屏蔽 (AND) rflags。如果不先保存rflags,那将是不可能的。您可以查看syscall 手册条目以获取更多信息。
猜你喜欢
  • 2018-06-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多