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語言系列的沒啥區別,不算是陷阱。 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM