Bootstrap

lua 调用文件中的函数调用_深入Lua:调用相关的指令

前言

这一节我们来深入解析与调用相关的指令,这些指令是:

  • OP_CALL 调用
  • OP_TAILCALL 尾调用
  • OP_VARARG 可变参数
  • OP_RETURN 返回

解析这些指令的过程中,最重要的是时刻跟踪栈的变化情况。

简单调用

  • OP_CALL 的语法是:R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1))
    • R(A)为要调用的函数本身
    • 如果B=1,表示没有参数,如果B>1,表示有B-1个参数,这些参数从寄存器R(A+1)开始。
    • 函数调用完之后,如果C=1,表示没有返回值,如果C>1,表示有C-1个返回值,这些返回值会存到寄存器R(A)和它后面。从这里可以看出,本来存函数的R(A)最后被替换为返回值。
  • OP_RETURN 函数返回指令,语法是:return R(A), ... ,R(A+B-2)
    • 如果B=1,表示没有返回值,如果B>1,表示有B-1个返因值,这些返回值就存在寄存器R(A)和它后面。这和OP_CALL是相呼应的。

有了上面两个指令,就可以进行函数调用,先看下面的Lua代码:

1 
2 local function add(a, b)
3     return a + b
4 end
5 
6 local function div(a, b)
7     return a // b, a % b
8 end
9 
10 local function main()
11     local s = add(10, 20)
12     local d, v = div(s, 8)
13     print(d, v)
14 end
15 
16 main()

通过luac查看上面几个函数的操作码,在每行操作码的最后,我加上了栈的内容,用<>括起来,栈从函数对象开始,函数对象的后面为base, 操作码中的数字大多相对于base,比如0表示base自己,1表示base+1。

下面是main函数:

1       [11]    GETUPVAL        0 0     ; add  -- <main|add>
2       [11]    LOADK           1 -1    ; 10   -- <main|add|10>
3       [11]    LOAD
;