Lua源碼閱讀四——lua虛擬機器指令系統

來源:互聯網
上載者:User

本篇文章,主要探討一下lua中的指令系統(涉及到的檔案 lopcodes.c )。

 

在lua中,用32位的unsigned int類型來表示一條指令作業碼,32位值包含了6位的作業碼和26位的指令欄位兩部分內容。

  All instructions have an opcode in the first 6 bits.
  Instructions can have the following fields:
 `A' : 8 bits
 `B' : 9 bits
 `C' : 9 bits
 `Bx' : 18 bits (`B' and `C' together)
 `sBx' : signed Bx

 

 

 

enum OpMode {iABC, iABx, iAsBx};  /* basic instruction format */

依據上面的枚舉值,指令碼目前有三種形式,即iABC,iABx,iAsBx,結構圖如下:

 

 

對於指令欄位A,B,C,有以下三種形式的取值來源:

/*
** R(x) - register
** Kst(x) - constant (in constant table)
** RK(x) == if ISK(x) then Kst(INDEXK(x)) else R(x)
*/
其中,用R來表示寄存器值,Kst表示常量表,RK表示可能是常量表或者寄存器。

 

 

 

lua5.14中總共擁有38條指令作業碼,作業碼名稱如下:

const char *const luaP_opnames[NUM_OPCODES+1] = {<br /> "MOVE",<br /> "LOADK",<br /> "LOADBOOL",<br /> "LOADNIL",<br /> "GETUPVAL",<br /> "GETGLOBAL",<br /> "GETTABLE",<br /> "SETGLOBAL",<br /> "SETUPVAL",<br /> "SETTABLE",<br /> "NEWTABLE",<br /> "SELF",<br /> "ADD",<br /> "SUB",<br /> "MUL",<br /> "DIV",<br /> "MOD",<br /> "POW",<br /> "UNM",<br /> "NOT",<br /> "LEN",<br /> "CONCAT",<br /> "JMP",<br /> "EQ",<br /> "LT",<br /> "LE",<br /> "TEST",<br /> "TESTSET",<br /> "CALL",<br /> "TAILCALL",<br /> "RETURN",<br /> "FORLOOP",<br /> "FORPREP",<br /> "TFORLOOP",<br /> "SETLIST",<br /> "CLOSE",<br /> "CLOSURE",<br /> "VARARG",<br /> NULL<br />};<br />

 

 

作業碼枚舉值,和上面的作業碼名稱一一對應,方便調用:

typedef enum {<br />/*----------------------------------------------------------------------<br />nameargsdescription<br />------------------------------------------------------------------------*/<br />OP_MOVE,/*A BR(A) := R(B)*/<br />OP_LOADK,/*A BxR(A) := Kst(Bx)*/<br />OP_LOADBOOL,/*A B CR(A) := (Bool)B; if (C) pc++*/<br />OP_LOADNIL,/*A BR(A) := ... := R(B) := nil*/<br />OP_GETUPVAL,/*A BR(A) := UpValue[B]*/</p><p>OP_GETGLOBAL,/*A BxR(A) := Gbl[Kst(Bx)]*/<br />OP_GETTABLE,/*A B CR(A) := R(B)[RK(C)]*/</p><p>OP_SETGLOBAL,/*A BxGbl[Kst(Bx)] := R(A)*/<br />OP_SETUPVAL,/*A BUpValue[B] := R(A)*/<br />OP_SETTABLE,/*A B CR(A)[RK(B)] := RK(C)*/</p><p>OP_NEWTABLE,/*A B CR(A) := {} (size = B,C)*/</p><p>OP_SELF,/*A B CR(A+1) := R(B); R(A) := R(B)[RK(C)]*/</p><p>OP_ADD,/*A B CR(A) := RK(B) + RK(C)*/<br />OP_SUB,/*A B CR(A) := RK(B) - RK(C)*/<br />OP_MUL,/*A B CR(A) := RK(B) * RK(C)*/<br />OP_DIV,/*A B CR(A) := RK(B) / RK(C)*/<br />OP_MOD,/*A B CR(A) := RK(B) % RK(C)*/<br />OP_POW,/*A B CR(A) := RK(B) ^ RK(C)*/<br />OP_UNM,/*A BR(A) := -R(B)*/<br />OP_NOT,/*A BR(A) := not R(B)*/<br />OP_LEN,/*A BR(A) := length of R(B)*/</p><p>OP_CONCAT,/*A B CR(A) := R(B).. ... ..R(C)*/</p><p>OP_JMP,/*sBxpc+=sBx*/</p><p>OP_EQ,/*A B Cif ((RK(B) == RK(C)) ~= A) then pc++*/<br />OP_LT,/*A B Cif ((RK(B) < RK(C)) ~= A) then pc++ */<br />OP_LE,/*A B Cif ((RK(B) <= RK(C)) ~= A) then pc++ */</p><p>OP_TEST,/*A Cif not (R(A) <=> C) then pc++*/<br />OP_TESTSET,/*A B Cif (R(B) <=> C) then R(A) := R(B) else pc++*/ </p><p>OP_CALL,/*A B CR(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */<br />OP_TAILCALL,/*A B Creturn R(A)(R(A+1), ... ,R(A+B-1))*/<br />OP_RETURN,/*A Breturn R(A), ... ,R(A+B-2)(see note)*/</p><p>OP_FORLOOP,/*A sBxR(A)+=R(A+2);<br />if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/<br />OP_FORPREP,/*A sBxR(A)-=R(A+2); pc+=sBx*/</p><p>OP_TFORLOOP,/*A CR(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2));<br /> if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++*/<br />OP_SETLIST,/*A B CR(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B*/</p><p>OP_CLOSE,/*A close all variables in the stack up to (>=) R(A)*/<br />OP_CLOSURE,/*A BxR(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n))*/</p><p>OP_VARARG/*A BR(A), R(A+1), ..., R(A+B-1) = vararg*/<br />} OpCode;<br />

 

 

 

38條作業碼對應的操作模式如下:

 

 #define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m))</p><p>const lu_byte luaP_opmodes[NUM_OPCODES] = {<br />/* T A B C mode opcode*/<br /> opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */<br /> ,opmode(0, 1, OpArgK, OpArgN, iABx)/* OP_LOADK */<br /> ,opmode(0, 1, OpArgU, OpArgU, iABC)/* OP_LOADBOOL */<br /> ,opmode(0, 1, OpArgR, OpArgN, iABC)/* OP_LOADNIL */<br /> ,opmode(0, 1, OpArgU, OpArgN, iABC)/* OP_GETUPVAL */<br /> ,opmode(0, 1, OpArgK, OpArgN, iABx)/* OP_GETGLOBAL */<br /> ,opmode(0, 1, OpArgR, OpArgK, iABC)/* OP_GETTABLE */<br /> ,opmode(0, 0, OpArgK, OpArgN, iABx)/* OP_SETGLOBAL */<br /> ,opmode(0, 0, OpArgU, OpArgN, iABC)/* OP_SETUPVAL */<br /> ,opmode(0, 0, OpArgK, OpArgK, iABC)/* OP_SETTABLE */<br /> ,opmode(0, 1, OpArgU, OpArgU, iABC)/* OP_NEWTABLE */<br /> ,opmode(0, 1, OpArgR, OpArgK, iABC)/* OP_SELF */<br /> ,opmode(0, 1, OpArgK, OpArgK, iABC)/* OP_ADD */<br /> ,opmode(0, 1, OpArgK, OpArgK, iABC)/* OP_SUB */<br /> ,opmode(0, 1, OpArgK, OpArgK, iABC)/* OP_MUL */<br /> ,opmode(0, 1, OpArgK, OpArgK, iABC)/* OP_DIV */<br /> ,opmode(0, 1, OpArgK, OpArgK, iABC)/* OP_MOD */<br /> ,opmode(0, 1, OpArgK, OpArgK, iABC)/* OP_POW */<br /> ,opmode(0, 1, OpArgR, OpArgN, iABC)/* OP_UNM */<br /> ,opmode(0, 1, OpArgR, OpArgN, iABC)/* OP_NOT */<br /> ,opmode(0, 1, OpArgR, OpArgN, iABC)/* OP_LEN */<br /> ,opmode(0, 1, OpArgR, OpArgR, iABC)/* OP_CONCAT */<br /> ,opmode(0, 0, OpArgR, OpArgN, iAsBx)/* OP_JMP */<br /> ,opmode(1, 0, OpArgK, OpArgK, iABC)/* OP_EQ */<br /> ,opmode(1, 0, OpArgK, OpArgK, iABC)/* OP_LT */<br /> ,opmode(1, 0, OpArgK, OpArgK, iABC)/* OP_LE */<br /> ,opmode(1, 1, OpArgR, OpArgU, iABC)/* OP_TEST */<br /> ,opmode(1, 1, OpArgR, OpArgU, iABC)/* OP_TESTSET */<br /> ,opmode(0, 1, OpArgU, OpArgU, iABC)/* OP_CALL */<br /> ,opmode(0, 1, OpArgU, OpArgU, iABC)/* OP_TAILCALL */<br /> ,opmode(0, 0, OpArgU, OpArgN, iABC)/* OP_RETURN */<br /> ,opmode(0, 1, OpArgR, OpArgN, iAsBx)/* OP_FORLOOP */<br /> ,opmode(0, 1, OpArgR, OpArgN, iAsBx)/* OP_FORPREP */<br /> ,opmode(1, 0, OpArgN, OpArgU, iABC)/* OP_TFORLOOP */<br /> ,opmode(0, 0, OpArgU, OpArgU, iABC)/* OP_SETLIST */<br /> ,opmode(0, 0, OpArgN, OpArgN, iABC)/* OP_CLOSE */<br /> ,opmode(0, 1, OpArgU, OpArgN, iABx)/* OP_CLOSURE */<br /> ,opmode(0, 1, OpArgU, OpArgN, iABC)/* OP_VARARG */<br />};</p><p>

 

 

操作模式計算公式如下:

#define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m))

用8位值來表示

/*
** masks for instruction properties. The format is:
** bits 0-1: op mode
** bits 2-3: C arg mode
** bits 4-5: B arg mode
** bit 6: instruction set register A
** bit 7: operator is a test
*/ 

依次從低位到高位表示如下含義:

第0,1位表示作業碼模式,取值於 enum OpMode {iABC, iABx, iAsBx};  /* basic instruction format */

第2,3位表示參數C模式,取值於 enum OpArgMask {
  OpArgN,  /* argument is not used */
  OpArgU,  /* argument is used */
  OpArgR,  /* argument is a register or a jump offset */
  OpArgK   /* argument is a constant or register/constant */
};

其中OpArgN表示未用參數,OpArgU表示可用參數,OpArgR表示寄存器參數或者跳轉指令,OpArgK表示常量表或者寄存器參數,

第4,5位表示參數B模式,取值於C取值範圍一致。

第6位表示寄存器參數A是否被設定。

第7位表示是否測試操作。

 

 

 

 

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.