本章节继续学习指令集和解释器。
存储指令
和加载指令刚好相反,存储指令把变量从操作数栈顶弹出,然后存入局部变量表。和加载指令一样,存储指令也可以分为6类。存储指令相关代码位于/instructions/stores包下。下面以lstore系列指令为例来学习下,其实现代码位于lstore.go文件中:
|
|
栈指令
栈指令直接对操作数栈进行操作,共9条:pop和pop2指令将栈顶变量弹出,dup系列指令复制栈顶变量,swap指令交换栈顶的两个变量。栈指令实现代码位于/instructions/stack包下。和其他类型的指令不同,栈指令并不关心变量类型。为了实现栈指令,需要给OperandStack结构体添加两个方法,修改/rtdata/operand_stack.go文件:
pop和pop2指令
pop指令相关代码位于pop.go文件中:
dup指令
dup指令相关代码位于dup.go文件中:
swap指令
swap指令相关代码位于swap.go文件中:
数学指令
数学指令大致对应Java语言中的加、减、乘、除等数学运算符。数学指令包括算数指令、位移指令和布尔运算指令等,共37条,本节将全部实现,其实现代码位于/instructions/math包下。
算数指令
算数指令又可以进一步分为加法(add)指令、减法(sub)指令、乘法(mul)指令、除法(dive)指令、求余(rem)指令和取反(reg)指令6种。下面以稍微复杂一些的求余指令为例来演示下,其余算数指令代码参照项目源码。求余指令实现代码位于rem.go文件中:
位移指令
位移指令可以分为左移和右移两种,右移指令有可以分为算数右移(有符号右移)和逻辑右移(无符号右移)两种。算数右移和逻辑右移的区别仅在于是否保留符号位,如下面Java代码所示:
位移指令实现代码位于sh.go文件中:
布尔运算指令
布尔运算指令只能操作int和long变量,分别安慰与(and)、按位或(or)、按位异或(xor)3种。下面以按位与为例来学习下,相关代码位于and.go文件中:
iinc指令
iinc指令给局部变量表中的int变量增加常量值,局部变量表索引和常量值都由指令的操作数提供。其实现代码位于iinc.go文件中:
下节继续。。。