读张秀宏《自己动手实现Lua:虚拟机、编译器和标准库》
2021-08-12 20:07:27 0 举报
AI智能生成
登录查看完整内容
读书笔记
作者其他创作
大纲/内容
6比特
操作码
26比特
操作数
共32比特
它对应 2.3.4.6 每条指令占用4个字节
高级语言的虚拟机是对真实计算的模拟和抽象
使用PUSH类的指令往栈顶推入值
使用POP类的指令从栈顶弹出值
其他的指令都是对栈顶值操作的指令
指令集相对比较大,但是指令平均长度比较短
基于栈
lua5.0版本以前的虚拟机是基于栈的
lua虚拟机,安卓早起使用的虚拟机Dalvik
所以指令比较长
需要把寄存器地址编辑入指令里
可以对寄存器进行寻址
基于寄存器
可按照实现方式分类
如同真实的计算机有一套指令集一样
指令集
定长指令
例如:Java虚拟机
变长指令集
可按照指令长度分类
A 8比特
B--- 9比特
C 9比特
三个操作数
以它居多
iABC
Bx 18比特
两个操作数
iABx
只有它会被解析成带符号的整数
sBx 18比特
iAxBx
占全部的26个比特
一个操作数
iAx
重点:理解高比特位,低比特位
可按照高26个比特分配方式分类
常量加载指令
运算符相关指令
循环和跳转指令
函数相关指令
表操作指令
Upvalue操作指令
分类
5.3版本时 它有47条指令
用于识别指令
它就是 指令的参数
表示目标寄存器 索引
操作数 A
不表示任何信息,也就就不会被使用
OpArgN
表示寄存器索引
表示跳转的偏移
iAsBx
布尔值
整数值
upvalue索引
子函数索引
OpArgU
表示源寄存器地址
OpArgR
常量表的索引
寄存器索引
9个比特中,最高位==1时表示常量索引否则是寄存器索引
OpArgK
可按照表示的信息分类
其他操作数
子主题
指令
可以用GO语言中的uint32l类型表示
编码模式
编码
从指令中提取操作码
Opcode方法
从iABC模式中提取参数
ABC()
从iABx模式中提取参数
ABx()
从iAsBx模式中提取参数
AsBx()
从iAx模式中提取参数
Ax()
5个方法
提取参数的方法
指令解码
指令表
指令的编码格式
第三章 指令集
对于需要使用超过一个字节表示的数据,要考虑大小端的问题
字节
C语言整形叫作cint
C语言size_t,叫作size_t
Lua整形
Lua浮点型
固定长度储存
除字节类型外,都会占用对个字节
数字
实质,是一个字节数组
字节数组的长度也记录在二进制chunk中
短字符串
长字符串
nulll
字符串
cint记录列表的长度
紧接着储存N个列表元素
列表
数据类型
总体而言,分为头部,主函数原型
但还有一个sizeUpvalues字段
总体结构
四个字节
ESC
L U A 的ASCII码
很多二进制格式都会以固定魔数开始
魔数主要起到快速识别文件格式的作用
可以用 xxd命令观察
如果签名不对,就会拒绝加载该文件
签名
签名之后的一个字节
大版本号
小版本号
发布号的增加仅仅意味着bug的修复
发布号
如果版本号与虚拟机本身的版本号不一致,就拒绝加载该文件
5x16+3
5.3.4这个版本号如何记录在chunk文件中
版本号
版本号之后的一个字节
如果和虚拟机本身的格式号不匹配,就决绝加载该文件
lua 官方现在使用的格式号是 0
格式号
格式号之后的6个字节
Lua 1.0 发布的年份
回车符
换行符
替换符
另一个换行符
LUAC_DATA
LUAC_DATA 之后的5个字节
也记录了Lua指令占用的字节数
各种整数类型占用的字节数
LUAC_INT
如果大小端方式与本机不匹配,则拒绝加载
大小端识别信息
LUAC_NUM
如果浮点数格式与本机不匹配,则拒绝加载
浮点数识别信息
头部
第一个字段
只有在main 函数的原型中有这个字段
不是必要的信息 -s选项编译就不存在于二进制chunk文件里了
源文件名
起止行号
固定参数个数
是否是vararg函数
必要的寄存器数量
函数基本信息
行号表
常量表
upvalue表
子函数原形表
局部变量表
Undump()函数
upvalue名列表
调试信息
2.3.4 函数原型
2.3 二进制chunk的格式
读取基本数据类型
检查头部
读取函数原型
2.4 解析二进制chunk
-o选项,对输出文件进行明确指定。
-s选项告诉luac去掉调试信息
-p选项仅仅检查语法是否正确
每个函数都会编译成一个内部结构
再以它为起点进行编译
可以没有子函数,因此反编译输出只有主函数信息
以function开头的说明是个普通函数
第一行以main开头
Lua编译器会自动为脚本添加一个main函数
以函数为单位进行编译
编译lua源文件
但是精简模式
会把常量表,局部变量表,upvalue表信息也打印出来
-l -l 详细模式
-l 选项可以把luac切换到反编译模式
可变参数函数
如果有加号,表示这是个vararg函数
1 固定参数数量
2 必要的寄存器数量
3 upvalue 数量
4 局部变量数量
5 常量数量
6 子函数数量
第二行以此是
指令序号
对应的行号
注释信息
指令列表
查看二进制chunk
2.2 luac命令介绍
Lua并不是直接解释执行chunk,而是先由编译器编译成内部结构
参数数量
局部变量数量
函数的基本信息
字节码
Upvalue表
子函数原型列表
内部结构 叫做Prototype
class文件的格式设计的相当紧凑
它本质是也是一个字节流
2.1 什么是二进制chunk
lua字节码的一个载体
chunk可以很小,小到只有一两句语句
一段可以被Lua解释器执行的代码
什么是chunk
lua版本问题
按照本机的大小端方式生产二级制chunk文件
探测被加载的文件的大小端方式,若与本机不一致则决绝加载
大小端问题
常见问题
第二章 二进制chunk
读张秀宏《自己动手实现Lua:虚拟机、编译器和标准库》
0 条评论
回复 删除
下一页