x86 指令笔记

Posted by HX on 2019-01-09 | 👓

最近在写一个辣鸡 x86 反汇编器,做点笔记。

概述

x86 指令有 6 部分,并不是每条指令都要有全部部分:

  • 指令前缀(0 - 4 字节)
  • 指令码(opcode,1 - 2 字节)
  • ModR/M(0 - 1 字节)
  • SIB(0 - 1 字节)
  • 偏移(0/1/2/4 字节)
  • 立即数(0/1/2/4 字节)

指令前缀

有 4 组前缀,一条指令在每组中最多只能取其中 1 个前缀,4 组就是 4 个前缀,各来自不同组。

  • 第一组:锁与重复
    • 0xf0: lock
    • 0xf2: repne
    • 0xf3: rep
  • 第二组:段跨越(segment override)
    • 0x26: es:
    • 0x2e: cs:
    • 0x36: ss:
    • 0x3e: ds:
    • 0x64: fs:
    • 0x65: gs:
  • 第三组:操作数长度覆盖(operand-size override)
    • 0x66: 改变操作数长度,16 位机默认长度为 16 位,32 位机默认长度为 32 位,改变后互换。
  • 第四组:地址长度覆盖(address-size override)
    • 0x67: 改变地址长度,16 位机默认长度为 16 位,32 位机默认长度为 32 位,改变后互换。

指令码

The Intel Manual and the x86 Opcode and Instruction Reference are your friends.

ModR/M

ModR/M 指出操作数的寻址方式(addressing mode),其高 2 位为 Mod,中间 3 位为 Reg/Opcode,低 3 位为 R/M。

若 Mod == 11(二进制),则第一操作数为寄存器寻址,否则为存储器寻址。

Reg/Opcode 有两种意义:

  1. 有的指令需要第二操作数,由这个字段给出。
  2. 有的指令用这个字段作为扩展指令码(opcode extension),即指令码部分和 Reg/Opcode 字段共同决定该指令是什么指令。

R/M 和 Mod 一起决定第一操作数更具体的寻址方式,见1

若为存储器寻址,且 R/M == 100(二进制),则后面还有 SIB 字节指明具体寻址方式。

SIB

SIB 是 scale-index-base(比例-变址-基址)的意思,其高 2 位为 scale,中间 3 位为 index,低 3 位为 base。

SIB 寻址的汇编形如 [base+index*scale]

scale 为 00、01、10、11(二进制)分别表示比例因子为 1、2、4、8,乘在变址寄存器上。

index 为 0 - 7 分别代表(32 位情况)eaxecxedxebx、无变址寄存器、ebpesiedi

base 为 0 - 7 分别代表(32 位情况)eaxecxedxebxesp、[*]、esiedi

其中 [*] 表示:

  • 若 Mod == 00(二进制),则无基址寄存器。
  • 若 Mod == 01 || Mod == 10,则为 ebp

位移和立即数

有些指令或寻址方式要求给出偏移或立即数,请查手册。

参考资料