Assembly SYSRET与SYSRETQ的区别和兼容模式

Assembly SYSRET与SYSRETQ的区别和兼容模式,assembly,x86,x86-64,intel,cpu-architecture,Assembly,X86,X86 64,Intel,Cpu Architecture,我将介绍SYSCALL/SYSRET指令的英特尔实现。如果我读得正确,与SYSCALL不同,只能从64位长模式调用英特尔版本。对吗 但是,如果我阅读英特尔的文档,了解附带的指令SYSRET,它有两种风格: SYSRET0F 07=“从快速系统调用返回到兼容模式” SYSRETQ48 0F 07=“从快速系统调用返回64位模式” 所以我只是想理解一下,如果不能从SYSCALL调用它,那么在什么时候将使用SYSRET(0F 07)返回到兼容模式?虽然英特尔版本的SYSCALL不能在兼容模式下使用

我将介绍SYSCALL/SYSRET指令的英特尔实现。如果我读得正确,与SYSCALL不同,只能从64位长模式调用英特尔版本。对吗

但是,如果我阅读英特尔的文档,了解附带的指令SYSRET,它有两种风格:

  • SYSRET
    0F 07
    =“从快速系统调用返回到兼容模式”

  • SYSRETQ
    48 0F 07
    =“从快速系统调用返回64位模式”


所以我只是想理解一下,如果不能从
SYSCALL
调用它,那么在什么时候将使用
SYSRET
0F 07
)返回到兼容模式?

虽然英特尔版本的SYSCALL不能在兼容模式下使用,但SYSRET指令可以从64位模式使用到“返回”到兼容模式。SYSRET指令不需要以前的SYSCALL指令才能工作,就像RET指令不需要以前的CALL指令一样

《英特尔64和IA-32体系结构软件开发人员手册》对SYSRET指令的操作作了如下说明:

如果(CS.L≠ 1)或(IA32_EFER.LMA)≠ 1) 或(IA32_EFER.SCE≠ 1) (*不在 IA32中未启用64位模式或SYSCALL/SYSRET*)
然后#UD;FI
IF(CPL≠ 0)或(RCX不是规范的)然后#GP(0);FI
IF(操作数大小为64位)
然后(*返回64位模式*)
裂开← RCX
ELSE(*返回兼容模式*)
裂开← ECX
FI
RFLAGS← (R11&3C7FD7H)| 2;(*清除RF、VM、保留位;设置位2*)

IF(操作数大小为64位)
然后是CS.Selector← IA32_星[63:48]+16
其他CS.选择器← IA32_星[63:48]
FI
CS.选择器← CS.选择器或3;(*RPL强制为3*)
(*将CS的其余部分设置为固定值*)
CS.Base>← 0; (*平段*)
CS.限制← fffff-h;(*粒度为4-KByte,表示有4-GByte限制*)
CS.类型← 11; (*执行/读取代码,已访问*)
政务司司长← 1;
CS.DPL← 3;
政务司司长← 1;
如果(操作数大小>64位)
然后(*返回64位模式*)
政务司司长← 1.(*64位代码段*)
政务司司长← 0; (*如果CS.L=1*,则为必填项)
ELSE(*返回兼容模式*)
政务司司长← 0; (*兼容模式*)
政务司司长← 1.(*32位代码段*)
FI
政务司司长← 1.(*4-KByte粒度*)
CPL← 3;
[……]

正如您所看到的,根据操作数大小,操作之间存在差异。值得注意的是,对于32位操作数大小,CS.L和CS.D标志设置为0和1,这意味着CPU开始在32位兼容模式下,在ECX给定的地址执行指令。无论内核(特权级别0)是如何输入的,它都会执行此操作


虽然在英特尔CPU上,32位操作数大小的SYSRET版本不能以最明显的方式使用,以恢复执行使用SYSCALL进入内核的32位兼容模式任务,但它仍有其他用途。比如开始执行新的32位任务,或者甚至可能通过其他方式恢复进入内核的任务。

兼容模式是64位长模式的子集。@RossRidge:是的,我知道。顺便问一下,32位用户模式代码如何进入64位内核模式?(让我们以Windows为例)我假设通过一个远程调用到一个特权间调用门,对吧。我想在这种情况下,内核例程可以调整堆栈并使用
sysret
。尽管整个“调整”代码可能会完全否定使用
sysret
而不是仅仅使用普通的
retf
所获得的效率。无论如何,我需要重新进入Windows上的Wow64,看看他们在那里做什么。谢谢。@MikeF通过中断(软件或硬件)、异常、通过门的远调用/jmp或syscenter指令。Windows使用syscenter进行系统调用,而据我所知,没有使用far-call/jmp-through-gates进行任何操作。@MikeF 64位Windows进程使用
syscall
进入内核,在64位Windows(WoW64)上的32位进程首先在用户模式下对64位代码段执行far-call,然后使用
syscall
。因此,
sysret
的返回兼容模式功能不在Windows上使用;它总是返回到64位模式。@HadiBrais Linux在vdso中有
\uu kernel\u vsyscall
函数。因此,根据CPU的能力,它可以使用INT$0x80、SYSCALL或SYSENTER。(尽管实际上32位软件可能只直接使用INT$0x80。)@HadiBrais:32位Linux系统调用通常使用
syscenter
。它的内核部分在中,以及从32位用户空间进入64位内核的其他入口点(另请参阅了解有关
int0x80
)的更多信息。
sysenter
save/restore舞蹈的用户空间端由VDSO页面中的代码完成,内核映射到每个进程中,由glibc调用