因此,在汇编中,STI启用中断,而RET从堆栈中获取一个数字,并将其放入IP中,然后在指令IP处恢复执行。IRET同时做了这两件事,对吧?那么为什么我不能只使用STI和RET呢?或者我可以一直使用IRET吗?
发布于 2019-12-31 18:42:51
iret
很复杂-它的行为取决于很多东西(CPU模式,返回信息等),在某些情况下,它可能会进行全硬件任务切换(更改每个通用寄存器和cr3/虚拟地址空间)。
最简单的iret
将从堆栈加载CS、IP/EIP/RIP和FLAGS/EFLAGS;但通常它也会加载SS和SP/ESP/RSP;所有段寄存器加载(CS、SS)都会导致GDT或LDT查找和保护检查(这会增加开销)。
另请注意,加载FLAGS/EFLAGS会恢复其先前的值。如果在启动中断处理程序之前禁用可屏蔽中断(这对于软件中断和异常是可能的),则保存在堆栈上的标志/EFLAGS将具有“中断标志清除”,并且IRET
将恢复“中断标志清除”,而不会导致“中断标志设置”。
ret
仅从堆栈加载IP/EIP/RIP。它不加载CS或标志/EFLAGS。
sti
不加载标志/EFLAGS,仅设置一位,这包括不恢复所有其他标志(例如进位、溢出等)。这可能是一个非常重要的区别(例如,你不希望IRQ在未知/随机时间丢弃算术标志,并在任何地方导致不可预测的失败)。
这意味着sti
然后ret
与(最简单的) IRET
有很大的不同-它做的更少,行为(涉及标志/EFLAGS)也非常不同。
模拟iret
行为的最接近的序列将是popf
(用于将标志/EFLAGS恢复到其先前的值),然后是retf
(用于加载CS和IP/EIP/RIP);并且这可以具有相同的复杂行为(例如,可以或可以不引起特权级别改变,可以或可以不引起硬件任务切换)。
然而,即使在这种“尽可能接近IRET”的情况下,它也是不同的,因为两个单独的指令是分开的-存在在popf
之后但在retf
之前出现IRQ的风险。
https://stackoverflow.com/questions/59539016
复制相似问题