有人告诉我,如果我将rsp
其用作通用寄存器,操作系统可能会将寄存器转储到它在中断情况下指向的位置,从而导致有问题的行为。
这是真的吗,如果不是,如果我不需要堆栈,我可以rsp
用作通用寄存器吗?
编辑:在用户空间中运行。
有人告诉我,如果我将rsp
其用作通用寄存器,操作系统可能会将寄存器转储到它在中断情况下指向的位置,从而导致有问题的行为。
这是真的吗,如果不是,如果我不需要堆栈,我可以rsp
用作通用寄存器吗?
编辑:在用户空间中运行。
如果发生中断,您不会搞砸吗?
那些在 DOS 中编程的人可能在这一点上对中断的可能性感到不安。通常,像这样重用堆栈指针是一个非常糟糕的主意,因为您不知道何时可能发生中断,而当一个中断发生时,CPU 会尽职尽责地将当前程序计数器和标志压入堆栈。如果您重用了 ESP,这将导致随机数据结构被丢弃。在这种环境中,ESP 必须始终指向有效且足够的堆栈空间来服务中断,并且当这不成立时,必须禁用中断。长时间禁用中断运行会降低系统响应能力(丢失中断和不良延迟),并且对于大型例程来说不实用。
但是,我们在这里以保护模式运行。
在 Win32 的用户空间中运行时,中断不会压入用户堆栈,而是压入内核堆栈。如果您考虑一下,则不可能使用用户堆栈。如果线程超出堆栈空间,或者甚至只是有一个无效堆栈,当 CPU 尝试推送 EIP 和 EFLAGS 时,它会出现页面错误,并且您不能在中断处理程序中出现页面错误。因此,调度程序可以在无堆栈例程运行时进行任意数量的上下文切换,并且任何指向 ESP 的数据结构都不会受到影响。
是的,您可以在非常可控的情况下,但实际上只使用 SSE2 和/或 MMX。
相关:写在ESP下面是否有效?讨论 Windows 中可以异步使用 32 位代码中的堆栈指针的东西。使用无效的堆栈指针,这些东西会崩溃而不是踩到它下面的空间。(或者如果指向可写内存,则将其用作堆栈空间。)
在 GNU/Linux 中,信号处理程序可以异步使用用户空间堆栈指针,但您可以使用sigaltstack
/SA_ONSTACK
为它们使用备用堆栈。
另请注意,x86-64 保证 SSE2。如果您已经使用了所有 xmm0..15 (SSE) 和 mm0..7 (MMX),通常只需要考虑使用 RSP 作为第 16 个通用寄存器。
对于没有 MMX 的 CPU,将 ESP 用作 32 位 DSP 代码中的第 8 个通用寄存器有时是有意义的;这就是为什么可以在 virtualdub 过滤器的上下文中找到关于它的讨论。
它在 64 位代码中通常没有意义,因为您总是有 16 个 128 位 SIMD 寄存器(以及在它们上使用的 SIMD 指令),以及两倍多的非堆栈指针整数寄存器。以及 8 个 64 位 mmx 寄存器,或 8 个 80 位 x87 寄存器,但您想使用它们。在大多数调用约定中,这些寄存器中的大多数都是调用破坏的,但是您不能在 RSP 不指向堆栈的情况下进行函数调用。