原文

nameargsdesc
OP_ADDA B CR(A) := RK(B) + RK(C)
OP_SUBA B CR(A) := RK(B) - RK(C)
OP_MULA B CR(A) := RK(B) * RK(C)
OP_DIVA B CR(A) := RK(B) / RK(C)
OP_MODA B CR(A) := RK(B) % RK(C)
OP_POWA B CR(A) := RK(B) ^ RK(C)

上表中的指令都是与lua本身的二元操作符一一对应的标准3地址指令。B和C两个操作数计算的结果存入A中。

local a = 1;
a = a + 1;
a = a - 1;
a = a * 1;
a = a / 1;
a = a % 1;
a = a ^ 1;
main <test.lua:0,0> (8 instructions at 0x80048eb0)
0+ params, 2 slots, 1 upvalue, 1 local, 1 constant, 0 functions
	1	[1]	LOADK    	0 -1	; 1
	2	[2]	ADD      	0 0 -1	; - 1
	3	[3]	SUB      	0 0 -1	; - 1
	4	[4]	MUL      	0 0 -1	; - 1
	5	[5]	DIV      	0 0 -1	; - 1
	6	[6]	MOD      	0 0 -1
	7	[7]	POW      	0 0 -1	; - 1
	8	[7]	RETURN   	0 1
constants (1) for 0x80048eb0:
	1	1
locals (1) for 0x80048eb0:
	0	a	2	9
upvalues (1) for 0x80048eb0:
	0	_ENV	1	0  

可以看到,生成的指令没有多余的操作,每个指令都对应一个完整的二元计算操作。

nameargsdesc
OP_UNMA BR(A) := -R(B)
OP_NOTA BA B R(A) := not R(B)

上表中指令对应'-'和'not'一元操作符,表示将B取反或not后放入A中。

local a = 1;
local b = not a;
local c = -a;
	1	[1]	LOADK    	0 -1	; 1
	2	[2]	NOT      	1 0
	3	[3]	UNM      	2 0
	4	[3]	RETURN   	0 1 

在编译和指令生成阶段,lua还支持所有一元和二元操作符表达式的常量表达式折叠”(const expression folding)优化。也就是如果计算操作数如果都是数字常量,可以在编译期计算出结果,就直接使用这个结果值,而不用生成计算指令。

local a = 1 + 1;
local b = not 1;
	1	[1]	LOADK    	0 -1	; 2
	2	[2]	LOADBOOL 	1 0 0
	3	[2]	RETURN   	0 1
从生成的结果可以看到1+1并没有生成对应的OP_ADD,而是直接把结果2赋值给了a。并且也没有为not 1生成OP_NOT指令,而是直接将false赋值给了b。

nameargsdesc
OP_LENA BR(A) := length of R(B)

LEN直接对应'#'操作符,返回B对象的长度,并保存到A中。

local a = #"foo";
	1	[1]	LOADK    	0 -1	; "foo"
	2	[1]	LEN      	0 0
	3	[1]	RETURN   	0 1 

nameargsdesc
OP_CONCATA B CR(A) := R(B).. ... ..R(C)

CONCAT将B和C指定范围内的字符串按顺序传接到一起,将结果存入到A。

local a = "foo1".."foo2".."foo3";
	1	[1]	LOADK    	0 -1	; "foo1"
	2	[1]	LOADK    	1 -2	; "foo2"
	3	[1]	LOADK    	2 -3	; "foo3"
	4	[1]	CONCAT   	0 0 2
	5	[1]	RETURN   	0 1 


Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐