本文简单介绍一下如何阅读lua的字节码。
有以下lua源码:
--文件名:main.lua
local a = 123
local b = 456
function foo()
local c = 1
return 1, 123, a
end
我们使用luac这个工具(使用lua源码可以编译出来)可以查看这段代码对应的字节码是怎样的,使用以下命令(windows下):luac.exe -l -l -p main.lua
下图是生成的字节码信息:
说明一下:
- Lua是以函数为单位来生成字节码的。每个函数有自己的指令表、常量表、局部变量表和upvalue表。
- 对于同一个函数,常量在常量表中是唯一的,上面的代码中,foo函数的常量表中只有一个常量1,第4,第5行的1使用的都是同一个常量。但不同函数的常量不共享,比如main函数中的常量123和foo函数中的常量123不是同一个常量。
- 只有函数中使用了外部的局部变量,该局部变量才会变成upvalue,比如foo中的a就是upvalue,但b不是,b不会在foo函数的upvalue表中。
- 指令参数一般有2至3列,分别对应该指令各个参数的值,比如foo中的GETUPVAL这条指令,它的指令格式是iABC,但实际上参数C没有使用,所以这里显示的参数只有两条,分别对应A和B。一般来说,A的值为寄存器索引,用于保存数值。这里A的值为3,表示使用索引号为3的寄存器(索引号从0开始,3就是第4个寄存器。头部信息中的slots为4,表示foo函数只用了4个寄存器)。B的值为0,查看GETUPVAL这条指令参数B的含义可知,B表示upvalue表中的索引,即变量a。所以GETUPVAL这条指令的执行结果就是将a的值保存到3号寄存器上。
- LOADK指令的参数B的值为什么是负数?这是因为参数B的类型是opArgK,它可以表示常量表中的索引,也可以表示寄存器的索引,这里显示负数表示它是常量表中的索引,要到常量表中去找值。所以-1表示常量表中的第1个值,-2表示第2个。也解释了为什么局部变量表和upvalue表的索引是从0开始,而常量表中的索引是从1开始,因为如果从0开始,那显示时就会是-0,看起来很怪异。
本文详细介绍了如何阅读和理解Lua的字节码。通过luac工具查看lua源码编译后的字节码信息,强调了lua以函数为单位生成字节码,每个函数拥有独立的指令表、常量表、局部变量表和upvalue表。重点解析了GETUPVAL和LOADK指令的参数含义,并解释了常量表索引从1开始的原因。

3125

被折叠的 条评论
为什么被折叠?



