今天研究了三块语句:
1、
if i > 0 then
i = 300
elseif i == 0 then
i = 100
else
i = 0
end
指令:
1 [1] GETTABUP 0 0 -1 ; _ENV "i"
2 [1] LT 0 -2 0 ; 0 -
3 [1] JMP 0 2 ; to 6
4 [2] SETTABUP 0 -1 -3 ; _ENV "i" 300
5 [2] JMP 0 6 ; to 12
6 [3] GETTABUP 0 0 -1 ; _ENV "i"
7 [3] EQ 0 0 -2 ; - 0
8 [3] JMP 0 2 ; to 11
9 [4] SETTABUP 0 -1 -4 ; _ENV "i" 100
10 [4] JMP 0 1 ; to 12
11 [6] SETTABUP 0 -1 -2 ; _ENV "i" 0
12 [7] RETURN 0 1
JMP 5 10行都跳向12行,这里用
luaK_concat函数将指令连起来,最后再修正指令偏移参数
2、
while i > 0 do
i = 200
if i > 100 then
break
end
end
指令:
1 [1] GETTABUP 0 0 -1 ; _ENV "i"
2 [1] LT 0 -2 0 ; 0 -
3 [1] JMP 0 5 ; to 9
4 [2] SETTABUP 0 -1 -3 ; _ENV "i" 200
5 [3] GETTABUP 0 0 -1 ; _ENV "i"
6 [3] LT 1 -4 0 ; 100 -
7 [3] JMP 0 1 ; to 9
8 [5] JMP 0 -8 ; to 1
9 [6] RETURN 0 1
源码中把while循环中的break转成goto break,并在第7行生成一个JMP指令。在循环结束后,创建一个break Label把前面的goto break生成的JMP指令偏移修正到下一个指令的位置
3、
while i > 0 do
i = 200
if i > 100 then
i = 100
break
else
i = 0
end
end
指令:
1 [1] GETTABUP 0 0 -1 ; _ENV "i"
2 [1] LT 0 -2 0 ; 0 -
3 [1] JMP 0 9 ; to 13
4 [2] SETTABUP 0 -1 -3 ; _ENV "i" 200
5 [3] GETTABUP 0 0 -1 ; _ENV "i"
6 [3] LT 0 -4 0 ; 100 -
7 [3] JMP 0 3 ; to 11
8 [4] SETTABUP 0 -1 -4 ; _ENV "i" 100
9 [4] JMP 0 3 ; to 13
10 [5] JMP 0 -10 ; to 1
11 [7] SETTABUP 0 -1 -2 ; _ENV "i" 0
12 [8] JMP 0 -12 ; to 1
13 [9] RETURN 0 1
本来第10行的JMP应该跳到第12行,但因第12行也是跳转指令,第10行的JMP就直接回到了第1行指令。这中间是精妙的luaK_jump函数,把指令链接起来,后面一同修正