8. immediate 值


上一页 返回目录 下一页

 

immediate 部分为指令提供一个 immediate operand。

immediate 寻址分为两种:需要 ModRM 字节引导和直接嵌在 opcode 中。

但是:

  ModRM 字节本身是不提供 immediate 寻址的,这个 ModRM 字节除了提供 register 和 memory 寻址外,只是起了对 Opcode 进行补充的作用,即:这个 Opcode 是一个 Group Opcode

  而 immediate 实际上还是嵌在 Opcode 中。

 

 

1、使用 immediate 的方式

上面已经说了,提供 immediate 的方式为:

(1)operand 寻址在 opcode 中嵌入,即:encode 中直接提供 immediate 值

  这一类指令很多,也很常用,如:call/jmp,mov/push 等等..

例:指令 mov al, 1

  它的 encode 是:b0 01 这种就是典型的指令,operand 寻址方式是嵌在 opcode 中的。



(2)operand 寻址需要 ModRM 引导

  基于这种寻址方式,可肯定这个 opcode 是 Group 属性的 opcode

★ ModRM.reg 对 opcode 进行补充确定,而 ModRM.r/m 是提供 register 或者 memory 寻址。

 

例: 指令 mov dword ptr [eax], 1

  这条指令的 opcode 就是典型的 Group 属性的 opcode,它的 目的操作数(first operand)是 memory,源操作数(second operand) 是 immediate。

  它的最终 encode 是: c7 00 01 00 00 00

  它的 ModRM 字节中:ModRM.reg = 000 是确定 C7 opcode,ModRM.r/m 提供对 [eax] 的寻址,immediate 部分是 01 00 00 00

 

 

2、 immediate 的符号

 同样 immediate 也分 singed(符号数) 与 unsigned(无符号数)情况


(1)immediate 是 signed(符号数)

★ immediate 用于算术运算时:它是 signed(符号数),当 immediate 小于 operand size 时,它被 sign-extended(符号扩展)到 operand size 大小。

★ immediate 是基于 rip 寄存器的偏移时:它是 signed(符号数)。同样会被做 sign-extended(符号扩展)处理。

★ immediate 被 push 入 stack 时:它是 signed(符号数)。同样会被做 sign-extended(符号扩展)处理。

 

add rax, 0xf3

  这条指令的 immediate 是 8 位,它的其中一种编码是: 48 83 c0 f3

  它的 immediate 是 0xf3 只有 1 byte,因此 0xf3 会被符号扩展到 64位数 0xffffffff_fffffff3 然后与 rax 相加。

 

jmp $

  指令中 $ 代表当前指令的位置,这条指令会产生死循环。

  它是其中一种编码是: eb fe

  它的 immediate 是 0xfe,只有 1 byte 因此,它也会被 sign-extended 为 64 位 0xffffffff_fffffffe(假设当前为 64 位),然后与 rip 相加得出新的 rip 值。

 

push 0xf3

  这是一条 push 指令,immediate 是 0xf3,它的编码为:6a f3

  同样 immediate 0xf3 会被符号扩展为 64 位 0xffffffff_fffffff3(假设当前为 64 位),然后入栈。

 

 

3、immediate 的长度

  在 64 位下:immediate 可为 8 位、16 位、32 位以及 64 位

  与 displacement 情形一样,immediate 只有少数指令才能使用 64 位的 immediate

关于 displacement 这方面的论述,详见:displacement 的长度

指令
编码
说明
mov al, 1
  b0 01
8 位 immediate
mov ax, 1
  66 b8 01 00
使用 operand size override 达到 16 位 immediate
mov eax, 1
  b8 01 00 00 00
32 位 immediate
mov rax, 1
  48 b8 01 00 00 00 00 00 00 00
使用 REX prefix 达到 64 位 immediate

上表是在 64 位模式下,使用 4 种 immediate 长度的示例

 

3.1 使用 64 位的 immediate 值

  只有当 immediate 操作数的属性是 Iv 的情形下,immediate 才可能有 64 位。

  x64 体系中规定,只有在将 immediate 赋给 GPRs 时,才能使用 64 位的 immediate

  这种情况下,immediate operand 的属性是 Iv,表示可以使用 64 位的 effective operand size

 

mov rax, 0x1122334455667788

  这条指令是正确的,它的 encode 是:48 b8 88 77 66 55 44 33 22 11

  这条指令形式是:MOV rAX, Iv,因此,immediate 是可以使用 64 位的 immediate 值 

  而像这条指令: mov qword ptr [rax], 0x112233445566778 是不正确的,编译器要么将 immediate 截断为 32 位,要么提示出错。

 

 

3.2 使用 64 位的 immediate 值的本质(具有 Iv 属性的本质)

  immediate operand 只有具有 Iv 属性时,才可以使用 64 位的 immediate 值,与 displacement 情形一样,同样须有两个前提:

★ operand 不依赖于 ModRM 寻址,换句说说:operand 是嵌在 Opcode 里的。

★ 使用 64 位 displacement 第 2 个前提条件是:指令长度不能超过 15 bytes

 

例子: mov qword ptr [rax + rcx * 8 + 0x11223344], 0x12345678

  这个例子是前面多次提到过,它的 encode 是:48 c7 84 c8 44 33 22 11 78 56 34 12 (共 12 个 bytes)

  同样,如果使用 64 位 immediate 指令长度超过了 15 bytes。

  实际上,这条指令中,opcode 指示它的 immediate operand 属性是 Iz 也就是:immediate 要 signed-extended 到 64 位

 

关于 64 位的限制,参见:x64 体系 64 位下的 displacement

 

上一页 返回目录 下一页


mik(deng zhi)写于 2008-11-26 15:40