我希望这个问题不是愚蠢的,因为它看似显而易见。 在我对缓冲区溢出进行一些研究时,我偶然发现了一个简单的问题:
在呼叫/返回/跳转后转到新的指令地址: CPU是否会在该地址执行OP代码,然后将一个字节移动到下一个地址并执行下一个OP代码,依此类推,直到达到下一个调用/返回/跳转?或者是否涉及更棘手的事情?
答案 0 :(得分:1)
call
指令将指令的地址保存(堆栈)到堆栈后。在那之后,它只是跳跃。它没有明确地告诉cpu寻找return
指令,因为这将通过弹出(从堆栈)call
首先保存的返回地址来处理。这允许多次调用和返回,或简单地说,嵌套调用。
答案 1 :(得分:1)
有点夸张的解释(与那些评论相同):
CPU具有专用寄存器指令指针 eip
,它指向下一条要执行的指令。
jmp
,call
,ret
等在内部结束,类似于:
mov eip,<next_instruction_address>
。
当CPU正在处理指令时,它会将eip
增加适当大小的上一次执行指令自动(除非被其中一个jmp
/ {{1}覆盖} / j[condition]
/ call
/ ret
/ ...说明)。
无论你指向int
(通过何种方式),CPU都会尝试将该内存的内容作为下一个指令操作码执行,而不知道任何上下文(where / why)它来自这个新的eip
)。实际上这种健忘症发生在执行的每条指令之前(我默默地忽略了现代内部x86架构,其中包含各种预执行队列和分支预测,转换为微指令等等......)...这是实施细节,对程序员来说非常隐蔽,通常只有通过糟糕的性能才能看到,如果你通过无意识地跳转来扰乱这种架构。所以它的CPU,eip
和这里&amp; now ,其他并不多。
注意:x86上的某些上下文可以通过监督代码(如OS)定义内存布局来提供,即。将某些内存区域标记为不可执行。 CPU检测到它eip
指向这样的区域将发出故障信号,并进入陷阱&#34;处理程序(通常由OS管理,杀死干扰过程)。
答案 2 :(得分:0)
当CPU处理指令时,它会增加eip by 最后执行的指令的适当大小(除非 被其中一个jmp / j [condition] / call / ret / int / ...指令覆盖。
这就是我想知道的。
我很清楚他们的东西更多(NX Bit,Pipelining ect)。
感谢大家的回复