lua指令集与虚拟机

lua_int32 Instruction 指令结构介绍与解析方法

----------------------目录-----------------------

(a)lu_int32 指令类型
(b)Instruction 指令结构
(c)OpMode 操作码类型
(d)MAXARGlimit限制
(e)GET_/SET_OPCODE 操作
(f)操作码分类校验
(j)OpCode 指令枚举
(h)OpArgMask
(i)Opmode 指令解析方法

(j)OP顺序调整加密

---------------------------------------------------

(a)lu_int32 指令类型

关于它的定义:typedef unsigned LUA_INT32 lu_int32;

LUA_INT32 可以通过设置 LUAI_BITSINT 的值来控制值 int类型还是long类型


(b)Instruction 指令结构

在lopcodes.h中有相关于指令的介绍

前6bits(低位):所有指令的opcode

之后会存在

A:8 bits

B:9 bits

C:9 bits

或者

Ax:26 bits(A、B、C组合在一起)

Bx:18 bits(A和B组合在一起)

sBx:18 bits(有符号的Bx)


(c)OpMode 操作码类型

{iABC,iABx,iAsBx,iAx}这个是代表组合的类型

#define SIZE_C 9
#define SIZE_B 9
#define SIZE_Bx (SIZE_C + SIZE_B)
#define SIZE_A 8
#define SIZE_Ax (SIZE_C + SIZE_B + SIZE_A)


#define SIZE_OP 6


#define POS_OP 0
#define POS_A (POS_OP + SIZE_OP)
#define POS_C (POS_A + SIZE_A)
#define POS_B (POS_C + SIZE_C)

#define POS_BxPOS_C

#define POS_AxPOS_A

上述定义说你名了关于Instruction的相关结构介绍


(d)MAXARG limit限制

系列参数定义,定义所有指令参数的限制条件,这里不做详细的介绍了,可以参考lopcodes.h中相关定义学习

(e)GET_/SET_OPCODE 操作

这一部分是为了获取、设置OPCode和相对应的参数,也就是指令集解析操作,在lopcodes.h GET_OPCODE之后是相应的指令定义
MASK1 制作1的掩码,协助下方操作获取相应的数值
MASK0 制作0的掩码,协助下方操作设置相应的数值
GET_OPCODE 获取opcode
SET_OPCODE 设置opcode
getarg 获取参数方法,协助下方获取参数操作
setarg 设置参数方法,协助下方设置参数操作

GETARG_A
SETARG_A
……
这一部分就是相关的参数操作定义了

CREATE_ABC
这一部分是用来创建各个mode组合的指令,创建好之后就可以设置参数了!

(f)操作码分类校验

* opmode校验
{iABC,iABx,iAsBx,iAx}OpMode分为这四个种类
主要是用来给指令分类别,好对应相应的解析执行操作
这部分的讲解请参见(i)部分

* RK校验
由于lua中会需要将常量加载到寄存器中,这个时候我们就需要校验一下参数是常量的缩影还是寄存器的索引
lua源码中,在操作码枚举声明后的注释也说明了所有操作码对应的操作:

其中:
R()表示这是一个寄存器索引
RK()表示这有可能是一个寄存器索引,也可能是一个常量索引,由参数的高位来决定是哪一种
Kst()表示这是一个常量索引

BITRK 如果得到的是1 表示常量,0 表示寄存器
ISK() 检测是不是constant,也就是是不是常量
INDEXK() 获取常量的index
MAXINDEXRK() 最大数值(limit)
RKASK 把一个常量的索引标记成RK类型,也就是对高位表示进行处理

NO_REG 这里表示没有用到这个参数

(j)OpCode 指令枚举

typedef enum {
/*----------------------------------------------------------------------
name argsdescription
------------------------------------------------------------------------*/
OP_MOVE,/* A B R(A) := R(B)*/
OP_LOADK,/* A Bx R(A) := Kst(Bx)*/
OP_LOADKX,/* R(A) := Kst(extra arg)*/
OP_LOADBOOL,/*A B C R(A) := (Bool)B; if (C) pc++*/
OP_LOADNIL,/* A B R(A), R(A+1), ..., R(A+B) := nil*/
OP_GETUPVAL,/*A B R(A) := UpValue[B]*/


OP_GETTABUP,/*A B C R(A) := UpValue[B][RK(C)]*/
OP_GETTABLE,/*A B C R(A) := R(B)[RK(C)]*/


OP_SETTABUP,/*A B C UpValue[A][RK(B)] := RK(C)*/
OP_SETUPVAL,/*A B UpValue[B] := R(A)*/
OP_SETTABLE,/*A B C R(A)[RK(B)] := RK(C)*/


OP_NEWTABLE,/*A B C R(A) := {} (size = B,C)*/


OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)]*/


OP_ADD,/* A B C R(A) := RK(B) + RK(C)*/
OP_SUB,/* A B C R(A) := RK(B) - RK(C)*/
OP_MUL,/* A B C R(A) := RK(B) * RK(C)*/
OP_DIV,/* A B C R(A) := RK(B) / RK(C)*/
OP_MOD,/* A B C R(A) := RK(B) % RK(C)*/
OP_POW,/* A B C R(A) := RK(B) ^ RK(C)*/
OP_UNM,/* A B R(A) := -R(B)*/
OP_NOT,/* A B R(A) := not R(B)*/
OP_LEN,/* A B R(A) := length of R(B)*/


OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C)*/


OP_JMP,/* A sBx pc+=sBx; if (A) close all upvalues >= R(A) + 1*/
OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++*/
OP_LT,/* A B C if ((RK(B) <  RK(C)) ~= A) then pc++*/
OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++*/


OP_TEST,/* A C if not (R(A) <=> C) then pc++*/
OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++*/


OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
OP_TAILCALL,/*A B C return R(A)(R(A+1), ... ,R(A+B-1))*/
OP_RETURN,/* A B return R(A), ... ,R(A+B-2)(see note) */


OP_FORLOOP,/* A sBx R(A)+=R(A+2);
if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/
OP_FORPREP,/* A sBx R(A)-=R(A+2); pc+=sBx*/


OP_TFORCALL,/*A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2));*/
OP_TFORLOOP,/*A sBx if R(A+1) ~= nil then { R(A)=R(A+1); pc += sBx }*/


OP_SETLIST,/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B*/


OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx])*/


OP_VARARG,/* A B R(A), R(A+1), ..., R(A+B-2) = vararg*/


OP_EXTRAARG/* Ax extra (larger) argument for previous opcode*/
} OpCode;

 
  
 

#define NUM_OPCODES(cast(int, OP_EXTRAARG) + 1)

这里定义了指令的数量,调整这里的舜玺,可以调整opcode码,做到一定的操作码混淆,有一定的加密功能


(h)OpArgMask

enum OpArgMask {
  OpArgN,  没有用到的参数
  OpArgU,  在使用的参数
  OpArgR,  寄存器参数或者跳转
  OpArgK
    R或者RK
};
   
这个是用来协助操作码解析的,分类参数类型,保证最高效率解析指令

(i)Opmode指令解析方法

LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
/*       T  A    B       C     mode    opcode*/
  opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */
 ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */
 ,opmode(0, 1, OpArgN, OpArgN, iABx) /* OP_LOADKX */
 ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */
 ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_LOADNIL */
 ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */
 ,opmode(0, 1, OpArgU, OpArgK, iABC) /* OP_GETTABUP */
 ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */
 ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABUP */
 ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */
 ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */
 ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */
 ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */
 ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */
 ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */
 ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */
 ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */
 ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */
 ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */
 ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */
 ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */
 ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */
 ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */
 ,opmode(0, 0, OpArgR, OpArgN, iAsBx) /* OP_JMP */
 ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */
 ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */
 ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */
 ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TEST */
 ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */
 ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */
 ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */
 ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */
 ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */
 ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */
 ,opmode(0, 0, OpArgN, OpArgU, iABC) /* OP_TFORCALL */
 ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_TFORLOOP */
 ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */
 ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */
 ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */
 ,opmode(0, 0, OpArgU, OpArgU, iAx) /* OP_EXTRAARG */
};

这里定义了全部的操作指令的定义,
#define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m))
在这里针对opmode进行调整编码顺序,例如t,a,b,c书序或者便宜量,可以起到一定的加密作用

接下来,通过
getOpMode 获取指令Mode,通过OpMode处理获取
getBMode 获取B的类型,通过OpArgMask处理获取
getCMode 获取C 的类型,通过OpArgMask处理获取
getAMode
testAMode 第六位(lua里面默认的设置,上面的a),用来判断当前指令是否会修改寄存器A
testTmode 第七位,用来判断当前指令是否涉及一次条件跳转,增加这个标记可以用来检测分支指令这一个打的类别,这样简化了指令集,当遇到跳转指令的时候,可以 回到前一条指令来看看那是否是条件跳转

#define LFIELDS_PER_FLUSH50

(j)op顺序调整加密
需要调整的位置
lopcodes.h enum{}opCode
lopcodes.c LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1],这里也需要调整顺序

猜你喜欢

转载自blog.csdn.net/Hello_YJQ/article/details/78342672