在llimits.h文件中定义了指令的类型。其实就是32个字节。

typedef lu_int32 Instruction;

上节说到变量最终会存入proto的数组k中,返回的索引放在expdesc *var->u.s.info。那么这个索引就是用来生成中间码的指令。如下。

int e = luaK_exp2anyreg(fs, ex);//返回寄存器索引
luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info);//生成指令

首先讲一下lua指令的构造,如图。简单来说就是把32位字节分割一下,低位的6个字节表示的是哪一种操作指令, 即opcode; 后面的分为2个参数和三个参数的情况。参数代表的计算在寄存器中的索引,寄存器可以想象成一个数组。

例如,如果指令的三段分别代表,“add  0   1”.表示的意思是对两个数求和,两个数分别在寄存器中,索引为0 和 1 的地方。

lopcodes.h定义了相关方法。其实就是些二进制的操作,可以获取指定范围内的比特值。不熟悉的同学可以先学习C语言的二进制运算。

#define GET_OPCODE(i)    (cast(OpCode, ((i)>>POS_OP) & MASK1(SIZE_OP,0)))
#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \
((cast(Instruction, o)<<POS_OP)&MASK1(SIZE_OP,POS_OP))))

lopcodes.c中定义了相关参数的比特长度:

enum OpMode {iABC, iABx, iAsBx};  /* basic instruction format */
/*
** size and position of opcode arguments.
*/
#define SIZE_C 9
#define SIZE_B 9
#define SIZE_Bx (SIZE_C + SIZE_B)
#define SIZE_A 8
#define SIZE_OP 6
#define POS_OP 0
#define POS_A (POS_OP + SIZE_OP)
#define POS_C (POS_A + SIZE_A)
#define POS_B (POS_C + SIZE_C)
#define POS_Bx POS_C

生成指令时,主要依据以下的格式:

#define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m))

const lu_byte luaP_opmodes[NUM_OPCODES] = {
/* T A B C mode opcode */
opmode(, , OpArgR, OpArgN, iABC) /* OP_MOVE */
,opmode(, , OpArgK, OpArgN, iABx) /* OP_LOADK */
,opmode(, , OpArgU, OpArgU, iABC) /* OP_LOADBOOL */
,opmode(, , OpArgR, OpArgN, iABC) /* OP_LOADNIL */
,opmode(, , OpArgU, OpArgN, iABC) /* OP_GETUPVAL */
,opmode(, , OpArgK, OpArgN, iABx) /* OP_GETGLOBAL */
,opmode(, , OpArgR, OpArgK, iABC) /* OP_GETTABLE */
,opmode(, , OpArgK, OpArgN, iABx) /* OP_SETGLOBAL */
......
}

#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3))
#define getBMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3))
#define getCMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3))
#define testAMode(m) (luaP_opmodes[m] & (1 << 6))
#define testTMode(m) (luaP_opmodes[m] & (1 << 7))

 

生成指令后,那么寄存器的地址和函数类型proto是如何对应的呢,如下图

至此,生成中间码指令的过程就分析完了。下一步重点关注lua本身的数据结构。

done。

lua源码学习篇四:字节码指令的更多相关文章

  1. JVM学习笔记:字节码执行引擎

    JVM学习笔记:字节码执行引擎 移步大神贴:http://rednaxelafx.iteye.com/blog/492667  

  2. JVM 字节码(一)字节码规范

    JVM 字节码(一)字节码规范 JVM 学习资源 Java ClassFile 字节码规范(Oracle) Java 虚拟机规范(Java SE 7 中文版) (周志明等译) Java 反编译工具 - ...

  3. lua源码学习篇一:环境部署

    研究生即将毕业,答辩完成后,这几天有些时间.开始写一些自己的东西,记录自己的学习历程. --前言 本着学习和交流的原则,本文的内容仅供参考,而不是权威版本,如有任何问题,欢迎指出. --声明 跨专业考 ...

  4. lua源码学习篇三:赋值表达式解析的流程

    上节说到表达式的解析问题,exprstate函数用于解析普通的赋值表达式.lua语言支持多变量赋值.本文先从单变量赋值表达式讲起. a = b = c = a + b 对于简单的两个数的求和过程,lu ...

  5. mongo源码学习(四)服务入口点ServiceEntryPoint

    在上一篇博客mongo源码学习(三)请求接收传输层中,稍微分析了一下TransportLayer的作用,这篇来看下ServiceEntryPoint是怎么做的. 首先ServiceEntryPoint ...

  6. OpenJDK源码研究笔记(七)–Java字节码文件(.class)的结构

    最近在看OpenJDK源码的过程中,顺便看了Java编译器(javac)的源码. 为了理解javac的源码,需要先搞懂Java字节码文件(.class)的结构. 于是,我就认真看了下OpenJDK中J ...

  7. 【JVM学习笔记】字节码文件结构实例

    上一篇笔记的内容大部分没有实际动手操作,因此决定完成这个完整的练习并记录下来. 另注,idea环境下有jclasslib插件用于更好的查看类似于javap结果的内容. 源代码如下: package c ...

  8. 【JVM学习笔记】字节码文件结构

    https://www.cnblogs.com/heben/p/11468285.html  比这篇笔记更好一点 新建一个Java类 package com.learn.jvm; public cla ...

  9. 《深入理解Java虚拟机》学习笔记之字节码执行引擎

    Java虚拟机的执行引擎不管是解释执行还是编译执行,根据概念模型都具有统一的外观:输入的是字节码文件,处理过程是字节码解析的等效过程,输出的是执行结果. 运行时栈帧结构 栈帧(Stack Frame) ...

随机推荐

  1. JSON.parse()与JSON.stringify()和eval()使用方法详解

    在和后端对接口的时候,遇到了一个问题 就是series里面数据变量进行拼接的时候,data数据里面全部是数值int类型的 但是因为某些需求需要让他进行某个数据之前的数据都为空 我试过用空字符串和und ...

  2. Flask开发系列之模板

    Flask开发系列之模板 本文对<FlaskWeb开发:基于python的Web应用开发实战>模板一节做的总结. Jinja2模板引擎 模板 模板是一个包含响应文本的文件,其中包含用占位变 ...

  3. 【ZIP】打包过滤指定目录和文件

    zip -r project.zip project/ -x@exclude.lst #目录过滤 # 直接目录,如 public public/* # 嵌套目录 如 node_modules */no ...

  4. ARM工作模式寻址

    用户模式(User)                 usr 快速中断模式(FIQ) fiq 普通终端模式(IRQ)     irq 保护模式(Supervisor) svc 数据访问终止模式(Abo ...

  5. .net中对象序列化技术

    序列化是将对象状态转换为可保持或传输的格式的过程.与序列化相对的是反序列化,它将流转换为对象.这两个过程结合起来,可以轻松地存储和传输数据.例如,可以序列化一个对象,然后使用 HTTP 通过 Inte ...

  6. php扩展安装,指定新的openssl

    1 自己从源码编译一个新的openssl 下载源码下来解压到 /mnt/soft/openssl-1.0.2m (openssl 安装到) ./config -h /usr/bin/perl ./Co ...

  7. jquery 查找元素,并判断隐藏或显示

    html <div class="panel-heading"> <h4 class="panel-title"> <a data ...

  8. 【转】Linux逻辑卷管理

    一. 前言 LVM是逻辑卷管理(Logical Volume Manager)的简称,它是建立在物理存储设备之上的一个抽象层,允许你生成逻辑存储卷,与直接使用物理存储在管理上相比,提供了更好灵活性.L ...

  9. 【curl】cookie的分隔符

    cookie是以分号作为分隔符的. ex: curl --silent -H "Host: xxx.com" "172.172.178.9:80/item/comm?pi ...

  10. python4---打印长方形

    1:方法1for i in range(6): for j in range(3): print("*", end=" ") print() 2:输入显示长方形 ...