说说大概的设计,不好之处,忘大神们指出
第一件事情是更具Intel指令手册来建立n张表,表结构的定义:
struct OpcodeMap
{
uint32 Q; // 如何定位到下一张表
uint32 P; //指令是否支持锁前缀
uint32 I1; //是什么指令
uint32 I2; //是什么指令
uint32 C; //解析指令的参数的个数
uint32 at[4]; // 解析指令的参数
};
表的类型,什么一比特的指令,2比特,浮点组之类的:
#define Q_TWOBYTE 1
#define Q_PREFIX 2
#define Q_GRP1 3
#define Q_GRP1A 4
#define Q_GRP2 5
#define Q_GRP11 6
#define Q_ESC 7
#define Q_GRP3 8
#define Q_GRP4 9
#define Q_GRP5 10
#define Q_GRP6 11
#define Q_GRP7 12
........
定义操作参数类型(和指令手册上写的一样):
#define Eb 1
#define Gb 2
#define Ev 3
#define Gv 4
#define AL 5
#define Ib 6
#define eAX 7
..............
要查的表的内容如:
OpcodeMap OneByte[] =
{
/* 00 */ { 0, P_F0, I_ADD, 0, 2, Eb, Gb, 0, 0 },
/* 01 */ { 0, P_F0, I_ADD, 0, 2, Ev, Gv, 0, 0 },
/* 02 */ { 0, 0, I_ADD, 0, 2, Gb, Eb, 0, 0 },
/* 03 */ { 0, 0, I_ADD, 0, 2, Gv, Ev, 0, 0 },
/* 04 */ { 0, 0, I_ADD, 0, 2, AL, Ib, 0, 0 },
/* 05 */ { 0, 0, I_ADD, 0, 2, eAX, Iz, 0, 0 },
.....
}
OpcodeMap TwoByte[] =
{
/* 00 */ { Q_GRP6, 0, 0, 0, 0, 0, 0, 0, 0 },
/* 01 */ { Q_GRP7, 0, 0, 0, 0, 0, 0, 0, 0 },
/* 02 */ { 0, 0, I_LAR, 0, 2, Gv, Ew, 0, 0 },
/* 03 */ { 0, 0, I_LSL, 0, 2, Gv, Ew, 0, 0 },
/* 04 */ { 0, 0, 0, 0, 0, 0, 0, 0, 0 },
/* 05 */ { 0, 0, I_SYSCALL, 0, 0, 0, 0, 0, 0 },
.....
}
OpcodeMap ThreeByte38[] =
{
/* 00 */ { Q_PFX_00_66, 0, 0, 0, 0, 0, 0, 0, 0 },
/* 01 */ { Q_PFX_00_66, 0, 0, 0, 1, 0, 0, 0, 0 },
/* 02 */ { Q_PFX_00_66, 0, 0, 0, 2, 0, 0, 0, 0 },
/* 03 */ { Q_PFX_00_66, 0, 0, 0, 3, 0, 0, 0, 0 },
/* 04 */ { Q_PFX_00_66, 0, 0, 0, 4, 0, 0, 0, 0 },
/* 05 */ { Q_PFX_00_66, 0, 0, 0, 5, 0, 0, 0, 0 },
/* 06 */ { Q_PFX_00_66, 0, 0, 0, 6, 0, 0, 0, 0 },
....
}
OpcodeMap ThreeByte3A[] =
{
/* 00 */ { Q_PFX_66, 0, I_VPERMQ, 0, 3, Vqq, Wqq, Ib, 0 },
/* 01 */ { Q_PFX_66, 0, I_VPERMPD, 0, 3, Vqq, Wqq, Ib, 0 },
/* 02 */ { Q_PFX_66, 0, I_VPBLENDD, 0, 3, Vx, Wx, Ib, 0 },
/* 03 */ { 0, 0, 0, 0, 3, 0, 0, 0, 0 },
/* 04 */ { Q_PFX_66, 0, I_VPERMILPS, 0, 3, Vx, Wx, Ib, 0 },
/* 05 */ { Q_PFX_66, 0, I_VPERMILPD, 0, 3, Vx, Wx, Ib, 0 },
/* 06 */ { Q_PFX_66, 0, I_VPERM2F128, 0, 3, Vqq, Wqq, Ib, 0 },
....
}
等n多表。
然后主要的逻辑:
先看前缀:
memset(If, 0, sizeof(InsFrame));
uint8 fPfx = 0;
uint8 Pfx = 0;
uint32 Prefix[5] = {DEF_SEG, DEF_OPRAND, DEF_ADDRESS, DEF_REPEATLOCK};
uint32 Offset = 0;
OpcodeMap* Map = OneByte + *Code;
for (; ;)
{
if (Map->Q != Q_PREFIX)
{
break;
}
// 前缀长度不超过15
if (Offset > 15)
{
If->I = I_Nul;
return E_UNKOWN;
}
Prefix[Map->at[0]] = Map->at[1];
fPfx = Pfx;
Pfx = *(Code + Offset);
// 查看下一个
if ((Offset + 1) >= Size)
{
return E_LEN;
}
++Offset;
Map = OneByte + *(Code + Offset);
}
再查是几字节的表:
if (Map->Q == Q_TWOBYTE)
{
if ((Offset + 1) >= Size)
{
return E_LEN;
}
++Offset;
Map = TwoByte + *(Code + Offset);
if (Map->Q == Q_66THREEBYTE38)
{
if ((Offset + 1) >= Size)
{
return E_LEN;
}
++Offset;
Map = ThreeByte38 + *(Code + Offset);
}
else if (Map->Q == Q_66THREEBYTE3A)
{
if ((Offset + 1) >= Size)
{
return E_LEN;
}
++Offset;
Map = ThreeByte3A + *(Code + Offset);
}
}
再查具体是那个分组的表:
// 决定查什么表
switch(Map->Q)
{
case Q_GRP1:
if ((Offset + 1) >= Size)
{
return E_LEN;
}
Map = Grp1 + (Map->C * 8) + ((*(Code + Offset + 1) & 0x38) >> 3);
break;
case Q_GRP1A:
if ((Offset + 1) >= Size)
{
return E_LEN;
}
Map = Grp1A + (Map->C * 8) + ((*(Code + Offset + 1) & 0x38) >> 3);
break;
case Q_GRP2:
if ((Offset + 1) >= Size)
{
return E_LEN;
}
Map = Grp2 + (Map->C * 8) + ((*(Code + Offset + 1) & 0x38) >> 3);
break;
具体定位到表后就是解析参数了:
If->I = Map->I1;
if (If->I == I_Nul)
{
return E_UNKOWN;
}
uint32 OffsetModRM = Offset + 1;
If->Op.Size = Map->C;
for (uint32 i = 0; i < Map->C; ++i)
{
uint32 SizeAddress;
uint32 IndexReg;
OpTag* T = &(If->Op.Tag[i]);
switch(Map->at[i])
{
case Eb:
SizeAddress = SIZE_8;
IndexReg = R_INDEXREG8;
goto LabModRM;
break;
case Ew:
SizeAddress = SIZE_16;
IndexReg = R_INDEXREG16;
goto LabModRM;
break;
case Ev:
if (Prefix[INDEX_OPRAND] == OPRAND_66)
{
SizeAddress = SIZE_16;
IndexReg = R_INDEXREG16;
}
else
{
SizeAddress = SIZE_32;
IndexReg = R_INDEXREG32;
}
goto LabModRM;
break;
解析MOD和SIB也使用表,看结构定义:
#define MOD_00 0x0 // mod
#define MOD_01 0x2
#define MOD_10 0x3
#define MOD_11 0x4
#define REG_OP_0 0x0 // Reg/Op
#define REG_OP_1 0x1
#define REG_OP_2 0x2
#define REG_OP_3 0x3
#define REG_OP_4 0x4
#define REG_OP_5 0x5
#define REG_OP_6 0x6
#define REG_OP_7 0x7
#define RM_0 0x0 // RM
#define RM_1 0x1
#define RM_2 0x2
#define RM_3 0x3
#define RM_4 0x4
#define RM_5 0x5
#define RM_6 0x6
#define RM_7 0x7
// ModR/M32表专用宏
#define MODRM32_MEM_FREG 0x1 // 全寄存器寻址
#define MODRM32_MEM_FREG_IMM1 0x2 // 全寄存器加立即数1寻址
#define MODRM32_MEM_SSFREG_IMM1 0x3 // 全寄存器加立即数1寻址
#define MODRM32_MEM_FREG_IMM4 0x4 // 全寄存器加立即数4寻址
#define MODRM32_MEM_SSFREG_IMM4 0x5 // 全寄存器加立即数4寻址
#define MODRM32_MEM_IMM4 0x6 // 立即数4寻址
#define MODRM32_REG 0x7 // 寄存器作为操作数
#define MODRM32_SIB 0x8 // 存在SIB
// ModR/M32表
struct ModRM32
{
uint32 Mode; // 寻址模式
uint32 Mod;
uint32 RegOp;
uint32 RM;
};
// ModR/M16表专用宏
#define MODRM16_MEM_2REG 0x1 // 寄存器寻址 如:Opcode [bx + si], REG
#define MODRM16_MEM_1REG 0x2 // 寄存器寻址 如:Opcode [bx + si], REG
#define MODRM16_MEM_2REG_IMM1 0x3 // 寄存器加立即数1寻址 如:Opcode [bx + si + IMM1], REG
#define MODRM16_MEM_1REG_IMM1 0x4 // 寄存器加立即数1寻址 如:Opcode [bx + si + IMM1], REG
#define MODRM16_MEM_2REG_IMM2 0x5 // 寄存器加立即数2寻址 如:Opcode [bx + si + IMM2], REG
#define MODRM16_MEM_1REG_IMM2 0x6 // 寄存器加立即数2寻址 如:Opcode [bx + si + IMM2], REG
#define MODRM16_MEM_IMM2 0x7 // 立即数2寻址 Opcode [IMM2], REG
#define MODRM16_REG 0x8 // 寄存器作为操作数 如:Opcode REG, REG
struct ModRM16
{
uint32 Mode; // 寻址模式
uint32 Mod;
uint32 RegOp;
uint32 RM;
uint32 Reg1;
uint32 Reg2;
};
// SIB表表专用宏
#define SIB_NATURAL 0x1 // 普通
#define SIB_NO0 0x2 // 无比例因子
#define SIB_NO0_BASE100 0x3 // 无比例因子,使用ss段前缀
#define SIB_NO0_BASE101 0x4 // 无比例因子,要判断MOD是否是00
#define SIB_BASE100 0x5 // 使用ss段前缀
#define SIB_BASE101 0x6 // 要判断MOD是否是00
#define SIB_INDEX100 0x7 // 无索引寄存器,无比例因子
#define SIB_INDEX100_BASE100 0x8 // 无索引寄存器,无比例因子,使用ss段前缀
#define SIB_INDEX100_BASE101 0x9 // 无索引寄存器,无比例因子,要判断MOD是否是00
#define N_00 0x0
#define N_01 0x2
#define N_10 0x4
#define N_11 0x8
#define INDEX_0 0x0
#define INDEX_1 0x1
#define INDEX_2 0x2
#define INDEX_3 0x3
#define INDEX_4 0x4
#define INDEX_5 0x5
#define INDEX_6 0x6
#define INDEX_7 0x7
#define BASE_0 0x0
#define BASE_1 0x1
#define BASE_2 0x2
#define BASE_3 0x3
#define BASE_4 0x4
#define BASE_5 0x5
#define BASE_6 0x6
#define BASE_7 0x7
// SIB表
struct SIB
{
uint32 Mode; // 寻址模式
uint32 N; // 比例因子
uint32 Index; // 索引寄存器索引
uint32 Base; // 基址寄存器索引
};
然后表的内容:
ModRM32 g_TabModRM32[0x100] =
{
/* 0x00 */ { MODRM32_MEM_FREG , MOD_00, REG_OP_0, RM_0 },
/* 0x01 */ { MODRM32_MEM_FREG , MOD_00, REG_OP_0, RM_1 },
/* 0x02 */ { MODRM32_MEM_FREG , MOD_00, REG_OP_0, RM_2 },
/* 0x03 */ { MODRM32_MEM_FREG , MOD_00, REG_OP_0, RM_3 },
/* 0x04 */ { MODRM32_SIB , MOD_00, REG_OP_0, RM_4 },
/* 0x05 */ { MODRM32_MEM_IMM4 , MOD_00, REG_OP_0, RM_5 },
......
}
ModRM16 g_TabModRM16[0x100] =
{
/* 0x0 */ { MODRM16_MEM_2REG , MOD_00, REG_OP_0, RM_0, R_BX, R_SI },
/* 0x1 */ { MODRM16_MEM_2REG , MOD_00, REG_OP_0, RM_1, R_BX, R_DI },
/* 0x2 */ { MODRM16_MEM_2REG , MOD_00, REG_OP_0, RM_2, R_BP, R_SI },
/* 0x3 */ { MODRM16_MEM_2REG , MOD_00, REG_OP_0, RM_3, R_BP, R_DI },
/* 0x4 */ { MODRM16_MEM_1REG , MOD_00, REG_OP_0, RM_4, R_SI, R_NO },
/* 0x5 */ { MODRM16_MEM_1REG , MOD_00, REG_OP_0, RM_5, R_DI, R_NO },
/* 0x6 */ { MODRM16_MEM_IMM2 , MOD_00, REG_OP_0, RM_6, R_NO, R_NO },
/* 0x7 */ { MODRM16_MEM_1REG , MOD_00, REG_OP_0, RM_7, R_BX, R_NO },
....
}
等表。。。
解析mod和sib部分就这样:
// 32位寻址址模式
switch(TabModRM->Mode)
{
// 全寄存器寻址即:Mod == 00, R/M != 100, R/M != 101 如:Opcode [FEG], REG
case MODRM32_MEM_FREG:
{
T->Type = OPERAND_MEM;
T->u.Mem.Type = MEM_REG;
T->u.Mem.Size = SizeAddress;
T->u.Mem.Segment = Prefix[INDEX_SEG];
T->u.Mem.u.Reg = g_TabReg[R_INDEXREG32][TabModRM->RM];
}
break;
// 全寄存器加立即数1寻址即:Mod == 01, R/M != 100 如:Opcode [FEG + IMM1], REG
case MODRM32_MEM_FREG_IMM1:
{
T->Type = OPERAND_MEM;
T->u.Mem.Type = MEM_REGIMM;
T->u.Mem.Size = SizeAddress;
T->u.Mem.Segment = Prefix[INDEX_SEG];
T->u.Mem.u.RegImm.Reg = g_TabReg[R_INDEXREG32][TabModRM->RM];
T->u.Mem.u.RegImm.Imm.Size = IMM8;
T->u.Mem.u.RegImm.Imm.u.Imm8 = *(int8*)(Code + Offset + 1);
++Offset;
}
break;
源码见附件:
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课