【发布时间】:2010-03-17 20:59:51
【问题描述】:
当程序集有类似 jmp f 的指令时,堆栈和帧指针会发生什么情况?
我的意思是 - f 是记忆中的标签,对吗?我们如何跳转到内存中的不同地址而不更新我们的帧和堆栈指针...
编辑:我说的是英特尔 x86 程序集,是的 :)
【问题讨论】:
当程序集有类似 jmp f 的指令时,堆栈和帧指针会发生什么情况?
我的意思是 - f 是记忆中的标签,对吗?我们如何跳转到内存中的不同地址而不更新我们的帧和堆栈指针...
编辑:我说的是英特尔 x86 程序集,是的 :)
【问题讨论】:
堆栈和帧指针处理数据的位置。 jmp 指令处理代码的位置。除非发生了剧烈的事情,否则一个人不应影响另一个人。这是一个激烈的事情清单:
jmp 试图非法更改权限。 就是这样。甚至那些情况也会改变堆栈,因为它们涉及某种上下文切换,要么切换到新任务,要么切换到某个异常处理程序。
还请注意,据我所知,没有任何操作系统使用 CPU 的任务切换功能。它通常在软件中实现。
【讨论】:
我猜你说的是英特尔指令?在这种情况下,任何堆栈/帧指针都不会发生任何事情,代码只是在相同的上下文中继续执行,但在新地址处。
我想这个答案有一些注意事项 - 可能会使用 jmp 指令导致任务切换,在这种情况下可能会发生各种疯狂的事情。您可能需要阅读文档以了解所有详细信息。 Intel Software Developer's Manual 包含所有详细信息:
jmp 第 2A 卷中的文档编辑:参考您关于跳跃而不更新的问题。
您必须能够在不修改堆栈和帧指针的情况下跳转您的代码。例如,它与 C 代码中的 goto 相同 - 您可以在函数中跳转,根本不需要修改执行上下文。
【讨论】:
我们怎样才能跳转到内存中的不同地址而不更新我们的帧和堆栈指针...
因为指令指针 (eip) 与帧和堆栈指针 (esp, ebp) 存储在不同的寄存器中。更改一个不会影响其他(通常)。
【讨论】:
请注意:在 x86 中,有多种“jmp”指令。最常见的是“本地” jmp,它只是改变 EIP 寄存器的值,因此根本不触及堆栈帧,正如 Carl 指出的那样。我假设您正在谈论这种类型的 jmp,因为它是汇编程序使用如下语法生成的:
jmp label
...
label:
但也有“远”跳转,它也会影响 CS 段寄存器。如果处理器处于实模式,它仍然只是 CS:IP 寄存器的变化(只是“更大”的跳转),但在保护模式下,CS 段具有非常不同且更复杂的功能:它被解释为描述符到 CALL/TASK/INTERRUPT 门,即描述符表中的索引,它定义了许多事情,如特权级别、任务......根据特定的描述符,可能会发生特权级别升级,或者也可能发生“硬件任务”切换。这可能会产生上下文变化。在保护模式下,您通常不会发现远跳,除非您正在对操作系统的核心进行编程。创建段描述符几乎总是内核的工作。
问候
【讨论】:
JMP 是程序集的goto,这意味着。
有时您只需要从不同的地址开始执行。
【讨论】: