default(缺省)与 effective(有效)


1. default(缺省)概念

default size 包括:

它们是指令在缺省情况下的 size,这个缺省情况是在未 override(改写)的情形下

这个 default size 是来自 CS.D 标志位(CS 寄存器的 D 标志位):

 

2. effective(有效)概念

effective size 包括:

指令最终的 operand size 和 address size 取决于两方面:

  1. 指令的 default operand/address size
  2. 指令的 effective operand/address size
当没有进行 override 时,指令最终的 operand/address size 就是 default operand/address size

但是:当进行 override 时,指令最终的 operand/address size 依赖于 effective size,effective size 是指令所能接受的 size 范围,并且根据 override 情况得到指令最终的 size

 

3. default operand size 与 effective operand size

表1: operand size 表

模式
default operand size
effective operand size
operand size override
描述
66H
REX
64 位
64
64
no
忽略
default = 64
 64 :忽略 REX prefix,不能加 66H prefix
16
yes
忽略 REX.W = 0
 16 :必须加 66H prefix,忽略 REX.W = 0
32
64
忽略
yes
default = 32
 64 :必须加 REX.W = 1,忽略 66H
32
no
忽略 REX.W = 0
 32 :不能加 66H,忽略 REX.W = 0
16
yes
忽略 REX.W = 0
 16 :必须加 66H,忽略 REX.W = 0
compatibility 模式
protected 模式
V8086 模式
real mode
32
32
no
no
default = 32
 32 : 不能加 66H 和 REX
16
yes
no
 16 : 必须 66H prefix,不能加 REX
16
32
yes
no
default = 16
 32 : 必须 66H prefix,不能加 REX
16
no
no
 16 :不能加 66H 和 REX

这个表描述的情况是:

(1)在 64 位下,一部分指令的 default operand size 是 64 位,一部分指令的 default operand size 是 32 位。

(2)当 default operand size 是 64 位时,它的 effective operand size 只有 64 位和 16 位,而不存在 32 位的 effective operand size

(3)表中的 “yes”表示:必须要加该 prefix; “no”表示:不能加该 prefix; “忽略”表示:该 prefix 将被忽略。

(4)“忽略 REX.W = 0”表示:当 REX.W = 0 时,将被忽略,而当 REX.W = 1 时,是不允许的。

 

operand size override 示例表:

default operand size
原指令
原指令 encodes
effective operand size
调整后的指令
operand size override
66H prefix
REX prefix
64
call rax
ff d0
64
---
---
40 ff d0 (忽略 REX.W = 0)
16
call ax
66 ff d0
66 40 ff d0 (忽略 REX.W = 0)
32
inc eax
ff c0
64
inc rax
66 48 ff c0(66H 被忽略)
48 ff c0
32
---
---
40 ff c0(忽略 REX.W = 0)
16
inc ax
66 ff c0
66 40 ff c0(忽略 REX.W = 0)
32
inc eax
40
32
---
---
---
16
inc ax
66 40
---
16
inc ax
40
32
inc eax
66 40
---
16
---
---
---

上表描述的情况是:

(1)当 66H prefix 和 REX prefix 起冲突时,取 REX prefix 有效,而忽略 66H prefix

(2)当使用 REX.W = 0(使用 default operand size)进行编码时,将被忽略

 

4. default address size 与 effective address size

表2: address size 表

模式
default address size
effective address size
67H prefix
64
64
64
no
32
yes
compatibility、protected、real
32
32
no
16
yes
16
32
yes
16
no

上表描述的情况是:

(1)在 64 位下,default address size 是 64 位,可以使用 67H prefix 进行 address size override 为 32 位。

(2)在 compaitibility/protected 模式下,default address size 是 32 位,可使用 67H prefix 进行 address size override 为 16 位。

(3)在 real 模式下,default address size 是 16 位,可使用 67H prefix 进行 address size override 为 32 位。

 

address size override 示例表:

模式
default address size
示例指令
示例编码
effective address size
override(67H prefix)
调整后的指令形式
64
64
mov rax, qword ptr [rax]
 48 8b 00
64
---
---
32
67 48 8b 00
 mov rax, qword ptr [eax]
compatibility、protected、real
32
mov eax, dword ptr [eax]
 8b 00
32
---
---
16
67 8b 00
 mov eax, dword ptr [bx + si]
16
mov ax, word ptr [bx + si]
 8b 00
32
67 8b 00
 mov ax, word ptr [eax]
16
---
---

 

5. default(缺省)与 effective(有效)的运用

(1)default operand/address size 表示指令原本的 operand/address size,这个 default size 由 CS.D 指示,

  而 CS.D 是由 code segment descriptor 的 D 属性位加载而来的:

★ 在 real mode 下:CS.D = 0 指示 default operand size 为 16 位,default address size 是 16 位。

★ 在 protected mode 下: CS.D = 1 指示 default operand size 为 32 位, default address size 是 32 位。

★ 在 64 位模式下: CS.L = 1 & CS.D = 0 指示 default operand size 为 32 位,而 default address size 是 64 位。(在大多数指令中)

  但是在一部分指令中,它的 default operand size 是 64 位的。

 

(2)effective operand/address size 表示指令可接受的 operand/address size

★ 通过 operand size override prefix - 66H 可以改变指令的 operand size

★ 通过 address size override prefix - 67H 可以改变指令的 address size(或说寻址模式)

★ 通过 REX prefix - 40H ~ 4FH 可以扩展指令可寻址 registers 数以及提供 64 位 operand size

 

(3)上面 2 个表详细列明了各个模式下 default 与 effective 下的情况。

在没有冲突的情况下,66H prefix 和 REX prefix 可同时出现,当起冲突时,以 REX prefix 为准,并忽略 66H prefix

★ 当 REX.W = 0 代表使用 default operand size 这时与 66H prefix 并没冲突,所以最终结果是 operand size override 即:以 66H prefix 为准。

★ 但是,若 REX.W = 1 指示使用 64 位 operand size,这时与 66H prefix 起冲突了,最终结果是 extended operand size 即:以 REX prefix 为准。

★ 最后一种情况是:指令的 default operand size 是 64 位,这不需要 REX prefix,而出现了 REX prefix 将被忽略。

  同样,若 REX.W = 1 与 66H prefix 同时出现,将忽略 66H prefix。 REW.W = 0 与 66H prefix 同时出现,则忽略 REX prefix。

 

 

6、 default 与 effective 在指令层上的表现

  在指令属性描述里,v 和 z 都依赖于 effective operand size

operand size 属性
指令的 operand size
effective operand size
v
64
64
32
32
16
16
z
32
64 或 32
16
16

可以看出 v 与 z 的不同点:

v 表明:指令的 operand size 是等于 effective operand size(default 和 override 情况下)

z 表明:指令的 operand size 受制于 effective operand size,但并不完全等于 effective operand size

  当 effective operand size 是 64 位以及 32 位时,operand size 是 32,在 z 属性指明没有 64 位的 operand size

 

与 z 类似的 operand size 属性还有 s 与 p,详见:operand size 表

 

示例:

(1)指令 PUSH Iz (Opcode - 68H)

  在 64 位下,它的 default operand size 是 64 位的,它的 operand 类型是 I(immediate),size 是 z

  因此,immediate 值要么是 16 位,要么是 32 位。取決于 effective operand size

  由于,它是 z 属性,最终 immediate 会 signed-extended 到 64 位


例1:指令 push 0x11223344

  它的 encodes 是 68 44 33 22 11

  这个 immediate 的 operand size 是 32 位值,但是具有 z 属性的 immediate ,在此例里:最终它将要 sign-extended 到 64 位。

另一方面:

  它的指令形式是 PUSH Iz 因此,可以使用 66H prefix 进行 operand size override

  经过 operand size override 后,它的 encode 是 66 68 44 33

  在汇编语句上,变成了 push 0x3344

 

有关 sign-extended(符号扩展)详见:immediate 的符号

 

例2:上一条指令的 encode:68 44 33 22 11

  如果这个 encode 使用了 66H prefix 进行 operand size override 到 16 位 operand size 的话:66 68 44 33 22 11

  那么,它指令形式将变成 push 0x3344 它被使用了 66H prefix 进行 override,而后面的 22 11 成为下一条指令 encode

 

由上 2 例可见,在 operand size 为 64 和 16 的情况下,这就是 z 属性指令中的 immediate 值:

★ effective operand size = 16 ====> operand size = 16

★ effective operand size = 64 ====> operand size = 32

 

 

(2)指令 JMP Jb(Opcode - EBH)

  这条指令的 size 属性是 b,它表明 immediate 是 byte 不会依赖于 effective operand size

  在 64 位下,它的 immediate 值也是 byte

 

例1: jmp .+0xfe

  这条指令形式等同于 jmp $(死循环),它的 encode 是 eb fe

  同样,这个 immediate 会被 sign-extended 到 64 位值,变成 0xfffffffffffffffe,然后加上 rip,成为新的 rip 值。

如果:

  这个 encode 加上 REX prefix 进行 override 的话,即:48 eb fe

  这里企图使用 REX prefix 调整到 64 位 operand size,由于 b 属性是固定 byte,这个 48 REX prefix 会被忽略,不起任何作用,operand size 依然是 byte

 

(3)指令 CALL Ev(Opcode - FF /2)

  这条指令的 operand size 属性是 v(effective operand size)

  在 64 位下,它的 default operand size 是 64 位,它的 default address size 也是 64 位。

 

那么,指令: call qword ptr [rax]

  指令形式中使用了 64 位的 operand 和 64 位的 address。 它的 encode 是 ff 10 00

  由于指令本身(default)的 operand size 和 address size 都是 64 位,因此,它不需要使用 REX prefix 进行 override

  这种情况下,operand size 使用的是 default operand size


版权 mik 所有,转载注明出处