LDS, LES, LFS, LGS, LSS
装入远指针
stableVMJITAOTinstruction
编码
| 操作码 | 指令 | Op/En | 64 位 | 兼容/传统 | 说明 |
|---|---|---|---|---|---|
C5 /r | LDS r16,m16:16 | RM | 无效 | 有效 | 装入 DS: r16 与内存相距很远的指针. |
C5 /r | LDS r32,m16:32 | RM | 无效 | 有效 | 装入 DS: r32 与内存相距很远的指针. |
0F B2 /r | LSS r16,m16:16 | RM | 有效 | 有效 | 装入 SS:r16 并装入远离内存的指针. |
0F B2 /r | LSS r32,m16:32 | RM | 有效 | 有效 | 装入 SS:r32 并装入远离内存的指针. |
REX.W + 0F B2 /r | LSS r64,m16:64 | RM | 有效 | 不可编码 | 装入 SS:r64 并装入远离内存的指针. |
C4 /r | LES r16,m16:16 | RM | 无效 | 有效 | 装入 ES:r16 并带有远离内存的指针. |
C4 /r | LES r32,m16:32 | RM | 无效 | 有效 | 装入 ES:r32 并带有远离内存的指针. |
0F B4 /r | LFS r16,m16:16 | RM | 有效 | 有效 | 装入 FS:r16 带有远离内存的指针. |
0F B4 /r | LFS r32,m16:32 | RM | 有效 | 有效 | 装入 FS:r32 带有远离内存的指针. |
REX.W + 0F B4 /r | LFS r64,m16:64 | RM | 有效 | 不可编码 | 装入 FS:r64 带有远离内存的指针. |
0F B5 /r | LGS r16,m16:16 | RM | 有效 | 有效 | 装入 GS:r16 并带有远离内存的指针. |
0F B5 /r | LGS r32,m16:32 | RM | 有效 | 有效 | 装入 GS:r32 并带有远离内存的指针. |
REX.W + 0F B5 /r | LGS r64,m16:64 | RM | 有效 | 不可编码 | 装入 GS:r64 并带有远离内存的指针. |
操作数编码
每个模式对应上表 Op/En 列的一个取值,说明各操作数按书写顺序分别编码在指令的哪个字段,以及指令对它是读、是写还是两者兼有。
RM
modrm.regescrituraModRM 字节的 reg 字段(第 5-3 位)modrm.rmlecturaModRM 字节的 r/m 字段(第 2-0 位);当 mod 字段要求时,还包括 SIB 字节和位移
实测开销
正在从 arch-data 加载实测数据...
说明
从第二行(source opeond)装入一个分块寄存器和第一行(destination opeond)中装入一个远指针(分区选择器和偏移器). 源操作数根据当前设置的操作数大小属性(分别为32位或16位),在内存中指定一个48位或32位指针. 指令 操作码 和 目标操作数 指定一个分段寄存器/ 通用寄存器 配对. 源操作数的16位段选择子被装入与操作码(DS,SS,ES,FS,或GS)指定的区段寄存器. 32位或16位偏移被加载到目标操作数指定的寄存器中.
如果这些指令之一在 保护模式 中执行,则来自 段选择子 在 源操作数 中指向的段描述符的额外信息会被装入所选段寄存器的隐藏部分.
同样在保护模式中,一个NULL选择器(值000至0003)可以装入DS,ES,FS或GS注册,而不会造成保护例外. (以后任何提及其对应的片段寄存器被装入NULL选择器的片段,都会引起一般保护例外(#GP),并且不会发生对片段的内存引用. )
在64位模式下,指令的默认操作大小为32位. 使用REX前缀的形式为REX.W促进操作,以指定源操作数在内存中引用一个80位指针(16位选择器,64位偏移). 使用REX的前缀形式为REX.R,允许访问额外的注册(R8-R15). 参见本节开头的汇总图,用于编码数据和限制.
行动
64-BIT_MODE
IF SS is loaded
THEN
IF SegmentSelector = NULL and ( (RPL = 3) or
(RPL 3 and RPL CPL) )
THEN #GP(0);
ELSE IF descriptor is in non-canonical space
THEN #GP(selector); FI;
ELSE IF Segment selector index is not within descriptor table limits
or segment selector RPL CPL
or access rights indicate nonwritable data segment
or DPL CPL
THEN #GP(selector); FI;
ELSE IF Segment marked not present
THEN #SS(selector); FI;
FI;
SS := SegmentSelector(SRC);
SS := SegmentDescriptor([SRC]);
ELSE IF attempt to load DS, or ES
THEN #UD;
ELSE IF FS, or GS is loaded with non-NULL segment selector
THEN IF Segment selector index is not within descriptor table limits
or access rights indicate segment neither data nor readable code segment
or segment is data or nonconforming-code segment
and ( RPL > DPL or CPL > DPL)
THEN #GP(selector); FI;
ELSE IF Segment marked not present
THEN #NP(selector); FI;
FI;
SegmentRegister := SegmentSelector(SRC) ;
SegmentRegister := SegmentDescriptor([SRC]);
FI;
ELSE IF FS, or GS is loaded with a NULL selector:
THEN
SegmentRegister := NULLSelector;
SegmentRegister(DescriptorValidBit) := 0; FI; (* Hidden flag;
not accessible by software *)
FI;
DEST := Offset(SRC);
PREOTECTED MODE OR COMPATIBILITY MODE;
IF SS is loaded
THEN
IF SegementSelector = NULL
THEN #GP(0);
ELSE IF Segment selector index is not within descriptor table limits
or segment selector RPL CPL
or access rights indicate nonwritable data segment
or DPL CPL
THEN #GP(selector); FI;
ELSE IF Segment marked not present
THEN #SS(selector); FI;
FI;
SS := SegmentSelector(SRC);
SS := SegmentDescriptor([SRC]);
ELSE IF DS, ES, FS, or GS is loaded with non-NULL segment selector
THEN IF Segment selector index is not within descriptor table limits
or access rights indicate segment neither data nor readable code segment
or segment is data or nonconforming-code segment
and (RPL > DPL or CPL > DPL)
THEN #GP(selector); FI;
ELSE IF Segment marked not present
THEN #NP(selector); FI;
FI;
SegmentRegister := SegmentSelector(SRC) AND RPL;
SegmentRegister := SegmentDescriptor([SRC]);
FI;
ELSE IF DS, ES, FS, or GS is loaded with a NULL selector:
THEN
SegmentRegister := NULLSelector;
SegmentRegister(DescriptorValidBit) := 0; FI; (* Hidden flag;
not accessible by software *)
FI;
DEST := Offset(SRC);
Real-Address or Virtual-8086 Mode
SegmentRegister := SegmentSelector(SRC); FI;
DEST := Offset(SRC);受影响的旗帜
None.
异常
保护模式
#UD | 如果 源操作数 不是 内存位置。如果使用 LOCK 前缀 。 |
#GP(0) | 如果 NULL 选择器被装入 SS 注册器中。 如果 内存操作数 的有效地址位于 CS, DS, ES, FS, 或 GS 分部限制之外, 如果使用 DS, ES, FS, 或 GS 注册器访问内存, 并包含 NULL 段选择子 。 |
#GP(selector) | 如果正在装入SS寄存器,且有以下任一内容是真实的: 段选择子指数不在描述表限制范围内, 段选择子 RPL不等于CPL,则该片段为不可写数据段,或 DPL不等于CPL. 如果DS,ES,FS,或GS寄存器被装入非NULL 段选择子,且以下任一内容都是真实的: 段选择子指数不在描述表限制之内,该片段既不是数据,也不是可读代码段,或该片段为数据或非编译-代码段,且RPL和CPL均大于DPL. |
#SS(0) | 如果 内存操作数 的有效地址在 SS 段限制之外。 |
#SS(selector) | 如果正在装入党卫军登记册,且没有标记段。 |
#NP(selector) | 如果DS,ES,FS,或GS寄存器被装入非NULL 段选择子,且该片段没有标记. #PF(fault-code) 如果发生页面错误. |
#AC(0) | 如果启用了对齐检查,并且在当前特权级别为3时会给出不对齐的内存引用. |
实地址模式
#GP | 如果内存操作数的有效地址在CS,DS,ES,FS或GS段限制之外. |
#SS | 如果 内存操作数 的有效地址在 SS 段限制之外。 |
#UD | 如果 源操作数 不是 内存位置。如果使用 LOCK 前缀 。 |
虚拟 8086 模式
#UD | 如果 源操作数 不是 内存位置。如果使用 LOCK 前缀 。 |
#GP(0) | 如果内存操作数的有效地址在CS,DS,ES,FS或GS段限制之外. |
#SS(0) | 如果 内存操作数 有效地址在 SS 段限制之外. #PF(fault-code) 如果 页面错误 发生. |
#AC(0) | 如果启用对齐检查, 并使用不对齐的内存引用 。 |
兼容模式
| 与保护模式中的例外相同. |
64 位模式
#GP(0) | 如果内存地址是非冠状的。 如果试图在兼容模式下将 NULL 选择器装入 SS 注册器。 如果试图将 NULL 选择器装入 CPL3 和 64 位模式下的 SS 注册器。 如果试图将 NULL 选择器装入 非 CPL3 和 64 位模式下的 SS 注册器,其 RPL 不等于 CPL 。 |
#GP(Selector) | 如果FS,或GS寄存器正在装入一个非NULL 段选择子,且以下任一内容都是真实的: 段选择子指数不在描述表限制之内,描述表的内存地址是非坎语的,片段既不是一个数据,也不是可读的代码段,或者片段是一个数据或不兼容的代码段,且RPL和CPL都大于DPL. 如果SS寄存器正在装,且以下任一内容都是真实的: 段选择子指数不在描述表限制之内,描述表的内存地址是非坎语的,段选择子 RPL不等于CPL,片段是一个不可读的数据段,或者DPL不等于CPL. |
#SS(0) | 如果 内存操作数 有效地址为非坎语 |
#SS(Selector) | 如果正在装入党卫军登记册,且没有标记段。 |
#NP(selector) | 如果FS,或GS寄存器正在装入一个非NULL 段选择子,且该片段没有标记. #PF(fault-code) 如果发生页面错误. |
#AC(0) | 如果启用了对齐检查,并且在当前特权级别为3时会给出不对齐的内存引用. |
#UD | 如果 源操作数 不是 内存位置。如果使用 LOCK 前缀 。 |