1. default(缺省)概念
default size 包括:
它们是指令在缺省情况下的 size,这个缺省情况是在未 override(改写)的情形下
这个 default size 是来自 CS.D 标志位(CS 寄存器的 D 标志位):
effective size 包括:
指令最终的 operand size 和 address size 取决于两方面:
当没有进行 override 时,指令最终的 operand/address size 就是 default operand/address size |
但是:当进行 override 时,指令最终的 operand/address size 依赖于 effective size,effective size 是指令所能接受的 size 范围,并且根据 override 情况得到指令最终的 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