Lua基本语法

前言:推荐一个工具Luadec,此工具有个功能可以反编译Lua代码生成Lua字节码,这篇博客使用了-dis 命令。

D:\luadec>luadec.exe
luadec.exe: no input files given
LuaDec by Hisham Muhammad
 Ongoing port to Lua 5.1 by Zsolt Sz. Sztupak (http://winmo.sztupy.hu)
usage: luadec.exe [options] [filename].  Available options are:
  -        process stdin
  -d       output information for debugging the decompiler
  -dis     don't decompile, just disassemble
  -f num   decompile only num-th function (0=main block)
  -l LDS   declare locals as defined by LDS
  -l2 LDS2 declare locals as defined by LDS2
  -dg      disable built-in local guessing
  -pg      don't run just print out the LDS2 string used
  -a       always declare all register as locals
  --       stop handling options

 

1.赋值语句

Lua有一个奇葩的赋值方式,先把值读入寄存器,再赋值给变量,这使得 a,b=b,a;这种脚本可以交换a和b 的值。我们看下下面的代码:

a=10;
b=5;
a,b=b,a;
print(a);
print(b);

x,y= 0;
print(x);
print(y);

--[[
D:\luadec>luadec.exe -dis test_exec.lua
; This file has been disassembled using luadec 2.0 standard by sztupy (http://l
adec51.luaforge.net)
; Command line was: -dis test_exec.lua

; Name:
; Defined at line: 0
; #Upvalues:       0
; #Parameters:     0
; Is_vararg:       2
; Max Stack Size:  2

  1 [-]: LOADK     R0 K1        ; R0 := 10
  2 [-]: SETGLOBAL R0 K0        ; a := R0
  3 [-]: LOADK     R0 K3        ; R0 := 5
  4 [-]: SETGLOBAL R0 K2        ; b := R0
  5 [-]: GETGLOBAL R0 K2        ; R0 := b
  6 [-]: GETGLOBAL R1 K0        ; R1 := a
  7 [-]: SETGLOBAL R1 K2        ; b := R1
  8 [-]: SETGLOBAL R0 K0        ; a := R0
  9 [-]: GETGLOBAL R0 K4        ; R0 := print
 10 [-]: GETGLOBAL R1 K0        ; R1 := a
 11 [-]: CALL      R0 2 1       ; R0(R1)
 12 [-]: GETGLOBAL R0 K4        ; R0 := print
 13 [-]: GETGLOBAL R1 K2        ; R1 := b
 14 [-]: CALL      R0 2 1       ; R0(R1)
 15 [-]: RETURN    R0 1         ; return
]]--

注释中是lua生成的字节码,从字节码的1~2行可以看出:给a赋值的操作,是通过一个R0的存储区来操作的,可能是一个寄存器,也可能是其他的,5~8行字节码可以看出,a和b的值,分别赋值给了R1和R0,然后R1和R0再分别赋值给b和a,以达到交换的目的。

2.Local变量

这个比较好理解,java代码中有int a;这种定义语句,但是lua中不需要,这就导致一个问题,代码块中,如何申明一个临时变量呢?lua是通过local这个关键字来做的。

i=20;
x=10;
if i < 20 then
    local x = 5;
    print(x)
end

if i < 20 then
    x = 5;
    print(x)
end
--[[
D:\luadec>luadec.exe -dis test_local.lua
; This file has been disassembled using luadec 2.0 standard by sztupy (http://lu
adec51.luaforge.net)
; Command line was: -dis test_local.lua

; Name:
; Defined at line: 0
; #Upvalues:       0
; #Parameters:     0
; Is_vararg:       2
; Max Stack Size:  3

  1 [-]: LOADK     R0 K1        ; R0 := 20
  2 [-]: SETGLOBAL R0 K0        ; i := R0
  3 [-]: LOADK     R0 K3        ; R0 := 10
  4 [-]: SETGLOBAL R0 K2        ; x := R0
  5 [-]: GETGLOBAL R0 K0        ; R0 := i
  6 [-]: LT        0 R0 K1      ; if R0 >= 20 then PC := 12
  7 [-]: JMP       12           ; PC := 12
  8 [-]: LOADK     R0 K4        ; R0 := 5
  9 [-]: GETGLOBAL R1 K5        ; R1 := print
 10 [-]: MOVE      R2 R0        ; R2 := R0
 11 [-]: CALL      R1 2 1       ; R1(R2)
 12 [-]: GETGLOBAL R0 K0        ; R0 := i
 13 [-]: LT        0 R0 K1      ; if R0 >= 20 then PC := 20
 14 [-]: JMP       20           ; PC := 20
 15 [-]: LOADK     R0 K4        ; R0 := 5
 16 [-]: SETGLOBAL R0 K2        ; x := R0
 17 [-]: GETGLOBAL R0 K5        ; R0 := print
 18 [-]: GETGLOBAL R1 K2        ; R1 := x
 19 [-]: CALL      R0 2 1       ; R0(R1)
 20 [-]: RETURN    R0 1         ; return

]]--

可以在字节码第8行和16行的区别看出,8行local语句使编译器选择了一个新的临时变量,而在16行则使用了SETGLOBAL语句。不过这个和C语言系列的没啥区别,不算是陷阱。 

 

posted @ 2017-08-10 11:42  身带吴钩  阅读(2011)  评论(0编辑  收藏  举报