上一节我们描述了jvm是通过一个死循环不断执行指令直至循环结束;
接下来我们将描述每一条指令
package base
import "HandWritingJVM/rtda"
//指令通用接口
type Instruction interface {
FetchOperands(reader *BytecodeReader)
Execute(frame *rtda.frame)
}
//对应无操作数指令,如return, add, mul...
type NoOperandsInstruction struct {
}
func (self *NoOperandsInstruction) FetchOperands(reader *BytecodeReader) {
//...
}
//分支跳转指令
type BranchInstruction struct {
Offset int
}
func (self *BranchInstruction) FetchOperands(reader *BytecodeReader) {
self.Offset = int(reader.ReadInt16())
}
//操作数长度为8的相关指令
type Index8Instruction struct {
Index uint
}
func (self *Index8Instruction) FetchOperands(reader *BytecodeReader) {
self.Index = uint(reader.ReadUint8())
}
//操作数长度为16的相关指令
type Index16Instruction struct {
Index uint
}
func (self *Index16Instruction) FetchOperands(reader *BytecodeReader) {
self.Index = uint(reader.ReadUint16())
}
4.2.读取字节码相关操作
package base
type BytecodeReader struct {
code []byte
pc int
}
//重置当前栈帧的pc以及将要执行的方法
func (self *BytecodeReader) Reset(code []byte, pc int) {
self.code = code
self.pc = pc
}
func (self *BytecodeReader) PC() int {
return self.pc
}
//获取当前代码块中pc所指向的字节码指令
func (self *BytecodeReader) ReadUint8() uint8 {
i := self.code[self.pc]
self.pc++
return i
}
func (self *BytecodeReader) ReadInt8() int8 {
return int8(self.ReadUint8())
}
func (self *BytecodeReader) ReadUint16() uint16 {
byte1 := uint16(self.ReadUint8())
byte2 := uint16(self.ReadUint8())
return (byte1 << 8) | byte2
}
func (self *BytecodeReader) ReadInt16() int16 {
return int16(self.ReadUint16())
}
func (self *BytecodeReader) ReadInt32() int32 {
byte1 := int32(self.ReadUint8())
byte2 := int32(self.ReadUint8())
byte3 := int32(self.ReadUint8())
byte4 := int32(self.ReadUint8())
return (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4
}
func (self *BytecodeReader) ReadInt32s(count int32) []int32 {
ret := make([]int32, count)
for i := 0; i < int(count); i++ {
ret[i] = self.ReadInt32()
}
return ret
}
func (self *BytecodeReader) SkipPadding() {
for self.pc%4 != 0 {
self.ReadUint8()
}
}
4.3.常量指令
4.3.1.nop
解释:
package constants
import (
"HandWritingJVM/instructions/base"
"HandWritingJVM/rtda"
)
type NOP struct {
base.NoOperandsInstruction
}
func (self *NOP) Execute(frame *rtda.frame) {
//...
}
4.3.2.const
解释:将一个值推入操作数栈中
package constants
import (
"HandWritingJVM/instructions/base"
"HandWritingJVM/rtda"
)
//将null推入操作数栈顶
type ACONST_NULL struct {
base.NoOperandsInstruction
}
func (self *ACONST_NULL) Execute(frame *rtda.frame) {
frame.OperandStack().PushRef(nil)
}
type DCONST_0 struct {
base.NoOperandsInstruction
}
//将double 0推入操作数栈顶,其他以此类推
func (self *DCONST_0) Execute(frame *rtda.frame) {
frame.OperandStack().PushDouble(0.0)
}
//将double 1推入操作数栈顶
type DCONST_1 struct {
base.NoOperandsInstruction
}
func (self *DCONST_1) Execute(frame *rtda.frame) {
frame.OperandStack().PushDouble(1.0)
}
//将float 0推入栈顶,其他以此类推
type FCONST_0 struct {
base.NoOperandsInstruction
}
func (self *FCONST_0) Execute(frame *rtda.frame) {
frame.OperandStack().PushFloat(0.0)
}
type FCONST_1 struct {
base.NoOperandsInstruction
}
func (self *FCONST_1) Execute(frame *rtda.frame) {
frame.OperandStack().PushFloat(1.0)
}
type FCONST_2 struct {
base.NoOperandsInstruction
}
func (self *FCONST_2) Execute(frame *rtda.frame) {
frame.OperandStack().PushFloat(2)
}
//将int -1 推入栈顶,其他以此类推
type ICONST_M1 struct {
base.NoOperandsInstruction
}
func (self *ICONST_M1) Execute(frame *rtda.frame) {
frame.OperandStack().PushInt(-1)
}
//将int 0推入栈顶,其他以此类推
type ICONST_0 struct {
base.NoOperandsInstruction
}
func (self *ICONST_0) Execute(frame *rtda.frame) {
frame.OperandStack().PushInt(0)
}
type ICONST_1 struct {
base.NoOperandsInstruction
}
func (self *ICONST_1) Execute(frame *rtda.frame) {
frame.OperandStack().PushInt(1)
}
type ICONST_2 struct {
base.NoOperandsInstruction
}
func (self *ICONST_2) Execute(frame *rtda.frame) {
frame.OperandStack().PushInt(2)
}
type ICONST_3 struct {
base.NoOperandsInstruction
}
func (self *ICONST_3) Execute(frame *rtda.frame) {
frame.OperandStack().PushInt(3)
}
type ICONST_4 struct {
base.NoOperandsInstruction
}
func (self *ICONST_4) Execute(frame *rtda.frame) {
frame.OperandStack().PushInt(4)
}
type ICONST_5 struct {
base.NoOperandsInstruction
}
func (self *ICONST_5) Execute(frame *rtda.frame) {
frame.OperandStack().PushInt(5)
}
//将long 0推入栈顶,其他以此类推
type LCONST_0 struct {
base.NoOperandsInstruction
}
func (self *LCONST_0) Execute(frame *rtda.frame) {
frame.OperandStack().PushLong(0)
}
type LCONST_1 struct {
base.NoOperandsInstruction
}
func (self *LCONST_1) Execute(frame *rtda.frame) {
frame.OperandStack().PushLong(1)
}
4.3.3.ipush
解释:读取一个值并推入操作数栈中
package constants
import (
"HandWritingJVM/instructions/base"
"HandWritingJVM/rtda"
)
type BIPUSH struct {
val int8
}
//从操作数中获取一个byte类型数据,扩展成int,然后推入栈顶
func (self *BIPUSH) FetchOperands(reader *base.BytecodeReader) {
self.val = reader.ReadInt8()
}
func (self *BIPUSH) Execute(frame *rtda.frame) {
i := int32(self.val)
frame.OperandStack().PushInt(i)
}
type SIPUSH struct {
val int16
}
//从操作数中获取一个short类型数据,扩展成int,然后推入栈顶
func (self *SIPUSH) FetchOperands(reader *base.BytecodeReader) {
self.val = reader.ReadInt16()
}
func (self *SIPUSH) Execute(frame *rtda.frame) {
frame.OperandStack().PushInt(int32(self.val))
}
4.3.4.ldc
解释:从运行时常量池中取出元素并推入操作数栈顶
package constants
import (
"HandWritingJVM/instructions/base"
"HandWritingJVM/rtda"
"HandWritingJVM/rtda/heap"
)
//从常量池中取出元素然后推入操作数栈中,下标长度为8
//且推入的元素类型为int, float, string, classRef
type LDC struct {
base.Index8Instruction
}
//从常量池中取出元素然后推入操作数栈中,下标长度为16
//且推入的元素类型为int, float, string, classRef
type LDC_W struct {
base.Index16Instruction
}
//从常量池中取出元素然后推入操作数栈中,下标长度为16
//且推入的元素类型为long,double
type LDC2_W struct {
base.Index16Instruction
}
func (self *LDC) Execute(frame *rtda.frame) {
_ldc(frame, self.Index)
}
func (self *LDC_W) Execute(frame *rtda.frame) {
_ldc(frame, self.Index)
}
func _ldc(frame *rtda.frame, index uint) {
stack := frame.OperandStack()
clazz := frame.Method().Class()
cp := clazz.ConstantPool()
c := cp.GetConstant(index)
switch c.(type) {
case int32:
stack.PushInt(c.(int32))
case float32:
stack.PushFloat(c.(float32))
case string:
internedStr := heap.JString(clazz.Loader(), c.(string))
stack.PushRef(internedStr)
case *heap.ClassRef:
classRef := c.(*heap.ClassRef)
classObj := classRef.ResolvedClass().JClass()
stack.PushRef(classObj)
default:
panic("todo: ldc!")
}
}
func (self *LDC2_W) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
cp := frame.Method().Class().ConstantPool()
c := cp.GetConstant(self.Index)
switch c.(type) {
case int64:
stack.PushLong(c.(int64))
case float64:
stack.PushDouble(c.(float64))
default:
panic("java.lang.ClassFormatError")
}
}
4.4.加载指令
解释:从局部变量表中取出指定下标的元素然后推入操作数栈中
4.4.1.aload解释:从局部变量表中取出指定下标的元素然后推入操作数栈中(该元素类型需为引用类型)
package loads
import (
"HandWritingJVM/instructions/base"
"HandWritingJVM/rtda"
)
//取出局部变量表第index个元素,然后推入操作数栈中
type ALOAD struct {
base.Index8Instruction
}
func (self *ALOAD) Execute(frame *rtda.frame) {
_aload(frame, uint(self.Index))
}
//取出局部变量表第0个元素,然后推入操作数栈中
type ALOAD_0 struct {
base.NoOperandsInstruction
}
func (self *ALOAD_0) Execute(frame *rtda.frame) {
_aload(frame, 0)
}
//取出局部变量表中第一个元素然后推入操作数栈中
type ALOAD_1 struct {
base.NoOperandsInstruction
}
func (self *ALOAD_1) Execute(frame *rtda.frame) {
_aload(frame, 1)
}
//取出局部变量表第2个元素然后推入操作数栈中
type ALOAD_2 struct {
base.NoOperandsInstruction
}
func (self *ALOAD_2) Execute(frame *rtda.frame) {
_aload(frame, 2)
}
//取出局部变量表第3个元素然后推入操作数栈中
type ALOAD_3 struct {
base.NoOperandsInstruction
}
func (self *ALOAD_3) Execute(frame *rtda.frame) {
_aload(frame, 3)
}
func _aload(frame *rtda.frame, index uint) {
ref := frame.LocalVars().GetRef(index)
frame.OperandStack().PushRef(ref)
}
4.4.2.dload
解释:从局部变量表中取出指定下标的元素然后推入操作数栈中(该元素类型需为double类型)
package loads
import (
"HandWritingJVM/instructions/base"
"HandWritingJVM/rtda"
)
type DLOAD struct {
base.Index8Instruction
}
func (self *DLOAD) Execute(frame *rtda.frame) {
_dload(frame, uint(self.Index))
}
type DLOAD_0 struct {
base.NoOperandsInstruction
}
func (self *DLOAD_0) Execute(frame *rtda.frame) {
_dload(frame, 0)
}
type DLOAD_1 struct {
base.NoOperandsInstruction
}
func (self *DLOAD_1) Execute(frame *rtda.frame) {
_dload(frame, 1)
}
type DLOAD_2 struct {
base.NoOperandsInstruction
}
func (self *DLOAD_2) Execute(frame *rtda.frame) {
_dload(frame, 2)
}
type DLOAD_3 struct {
base.NoOperandsInstruction
}
func (self *DLOAD_3) Execute(frame *rtda.frame) {
_dload(frame, 3)
}
func _dload(frame *rtda.frame, index uint) {
val := frame.LocalVars().GetDouble(index)
frame.OperandStack().PushDouble(val)
}
4.4.3.fload
解释:从局部变量表中取出指定下标的元素然后推入操作数栈中(该元素类型需为float类型)
package loads
import (
"HandWritingJVM/instructions/base"
"HandWritingJVM/rtda"
)
type FLOAD struct {
base.Index8Instruction
}
func (self *FLOAD) Execute(frame *rtda.frame) {
_fload(frame, uint(self.Index))
}
type FLOAD_0 struct {
base.NoOperandsInstruction
}
func (self *FLOAD_0) Execute(frame *rtda.frame) {
_fload(frame, 0)
}
type FLOAD_1 struct {
base.NoOperandsInstruction
}
func (self *FLOAD_1) Execute(frame *rtda.frame) {
_fload(frame, 1)
}
type FLOAD_2 struct {
base.NoOperandsInstruction
}
func (self *FLOAD_2) Execute(frame *rtda.frame) {
_fload(frame, 2)
}
type FLOAD_3 struct {
base.NoOperandsInstruction
}
func (self *FLOAD_3) Execute(frame *rtda.frame) {
_fload(frame, 3)
}
func _fload(frame *rtda.frame, index uint) {
val := frame.LocalVars().GetFloat(index)
frame.OperandStack().PushFloat(val)
}
4.4.4.iload
解释:从局部变量表中取出指定下标的元素然后推入操作数栈中(该元素类型需为int类型)
package loads
import (
"HandWritingJVM/instructions/base"
"HandWritingJVM/rtda"
)
//获取局部变量表中元素并放入操作数栈中
func _iload(frame *rtda.frame, index uint) {
val := frame.LocalVars().GetInt(index)
frame.OperandStack().PushInt(val)
}
type ILOAD struct {
base.Index8Instruction
}
func (self *ILOAD) Execute(frame *rtda.frame) {
_iload(frame, self.Index)
}
type ILOAD_0 struct {
base.NoOperandsInstruction
}
func (self *ILOAD_0) Execute(frame *rtda.frame) {
_iload(frame, 0)
}
type ILOAD_1 struct {
base.NoOperandsInstruction
}
func (self *ILOAD_1) Execute(frame *rtda.frame) {
_iload(frame, 1)
}
type ILOAD_2 struct {
base.NoOperandsInstruction
}
func (self *ILOAD_2) Execute(frame *rtda.frame) {
_iload(frame, 2)
}
type ILOAD_3 struct {
base.NoOperandsInstruction
}
func (self *ILOAD_3) Execute(frame *rtda.frame) {
_iload(frame, 3)
}
4.4.5.lload
解释:从局部变量表中取出指定下标的元素然后推入操作数栈中(该元素类型需为long类型)
package loads
import (
"HandWritingJVM/instructions/base"
"HandWritingJVM/rtda"
)
type LLOAD struct {
base.Index8Instruction
}
func (self *LLOAD) Execute(frame *rtda.frame) {
_lload(frame, uint(self.Index))
}
type LLOAD_0 struct {
base.NoOperandsInstruction
}
func (self *LLOAD_0) Execute(frame *rtda.frame) {
_lload(frame, 0)
}
type LLOAD_1 struct {
base.NoOperandsInstruction
}
func (self *LLOAD_1) Execute(frame *rtda.frame) {
_lload(frame, 1)
}
type LLOAD_2 struct {
base.NoOperandsInstruction
}
func (self *LLOAD_2) Execute(frame *rtda.frame) {
_lload(frame, 2)
}
type LLOAD_3 struct {
base.NoOperandsInstruction
}
func (self *LLOAD_3) Execute(frame *rtda.frame) {
_lload(frame, 3)
}
func _lload(frame *rtda.frame, index uint) {
val := frame.LocalVars().GetLong(index)
frame.OperandStack().PushLong(val)
}
4.4.6.xaload
解释:从局部变量表中取出指定下标的数组中的元素然后推入操作数栈中(该元素类型需为数组类型)
package loads
import (
"HandWritingJVM/instructions/base"
"HandWritingJVM/instructions/constants"
"HandWritingJVM/rtda"
"HandWritingJVM/rtda/heap"
)
//load ref from array
type AALOAD struct {
base.NoOperandsInstruction
}
//按索引取出数组元素值
func (self *AALOAD) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
index := stack.PopInt()
arrRef := stack.PopRef()
checkNotNil(arrRef)
refs := arrRef.Refs()
checkIndex(len(refs), index)
stack.PushRef(refs[index])
}
type BALOAD struct {
base.NoOperandsInstruction
}
func (self *BALOAD) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
index := stack.PopInt()
arrRef := stack.PopRef()
checkNotNil(arrRef)
bytes := arrRef.Bytes()
checkIndex(len(bytes), index)
stack.PushInt(int32(bytes[index]))
}
type CALOAD struct {
base.NoOperandsInstruction
}
func (self *CALOAD) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
index := stack.PopInt()
arrRef := stack.PopRef()
checkNotNil(arrRef)
chars := arrRef.Chars()
checkIndex(len(chars), index)
stack.PushInt(int32(chars[index]))
}
type DALOAD struct {
base.NoOperandsInstruction
}
func (self *DALOAD) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
index := stack.PopInt()
arrRef := stack.PopRef()
checkNotNil(arrRef)
doubles := arrRef.Doubles()
checkIndex(len(doubles), index)
stack.PushDouble(doubles[index])
}
type FALOAD struct {
base.NoOperandsInstruction
}
func (self *FALOAD) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
index := stack.PopInt()
arrRef := stack.PopRef()
checkNotNil(arrRef)
floats := arrRef.Floats()
checkIndex(len(floats), index)
stack.PushFloat(floats[index])
}
type IALOAD struct {
base.NoOperandsInstruction
}
func (self *IALOAD) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
index := stack.PopInt()
arrRef := stack.PopRef()
checkNotNil(arrRef)
ints := arrRef.Ints()
checkIndex(len(ints), index)
stack.PushInt(ints[index])
}
type LALOAD struct {
base.NoOperandsInstruction
}
func (self *LALOAD) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
index := stack.PopInt()
arrRef := stack.PopRef()
checkNotNil(arrRef)
longs := arrRef.Longs()
checkIndex(len(longs), index)
stack.PushLong(longs[index])
}
type SALOAD struct {
base.NoOperandsInstruction
}
func (self *SALOAD) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
index := stack.PopInt()
arrRef := stack.PopRef()
checkNotNil(arrRef)
shorts := arrRef.Shorts()
checkIndex(len(shorts), index)
stack.PushInt(int32(shorts[index]))
}
func checkNotNil(ref *heap.Object) {
if ref == nil {
panic(constants.NullPointerException)
}
}
func checkIndex(arrLen int, index int32) {
if index < 0 || index > int32(arrLen) {
panic(constants.ArrayIndexOutOfBoundsException)
}
}
4.5.存储指令
解释:将栈顶元素存储到指定的局部变量表的指定位置;
4.5.1.astore//将栈顶元素存储到局部变量表指定位置
//该元素类型需为ref
package stores
import (
"HandWritingJVM/instructions/base"
"HandWritingJVM/rtda"
)
type ASTORE struct {
base.Index8Instruction
}
func (self *ASTORE) Execute(frame *rtda.frame) {
_astore(frame, uint(self.Index))
}
type ASTORE_0 struct {
base.NoOperandsInstruction
}
func (self *ASTORE_0) Execute(frame *rtda.frame) {
_astore(frame, 0)
}
type ASTORE_1 struct {
base.NoOperandsInstruction
}
func (self *ASTORE_1) Execute(frame *rtda.frame) {
_astore(frame, 1)
}
type ASTORE_2 struct {
base.NoOperandsInstruction
}
func (self *ASTORE_2) Execute(frame *rtda.frame) {
_astore(frame, 2)
}
type ASTORE_3 struct {
base.NoOperandsInstruction
}
func (self *ASTORE_3) Execute(frame *rtda.frame) {
_astore(frame, 3)
}
func _astore(frame *rtda.frame, index uint) {
ref := frame.OperandStack().PopRef()
frame.LocalVars().SetRef(index, ref)
}
4.5.2.dstore
//将栈顶元素存储到局部变量表指定位置
//该元素类型需为double
package stores
import (
"HandWritingJVM/instructions/base"
"HandWritingJVM/rtda"
)
type DSTORE struct {
base.Index8Instruction
}
func (self *DSTORE) Execute(frame *rtda.frame) {
_dstore(frame, uint(self.Index))
}
type DSTORE_0 struct {
base.NoOperandsInstruction
}
func (self *DSTORE_0) Execute(frame *rtda.frame) {
_dstore(frame, 0)
}
type DSTORE_1 struct {
base.NoOperandsInstruction
}
func (self *DSTORE_1) Execute(frame *rtda.frame) {
_dstore(frame, 1)
}
type DSTORE_2 struct {
base.NoOperandsInstruction
}
func (self *DSTORE_2) Execute(frame *rtda.frame) {
_dstore(frame, 2)
}
type DSTORE_3 struct {
base.NoOperandsInstruction
}
func (self *DSTORE_3) Execute(frame *rtda.frame) {
_dstore(frame, 3)
}
func _dstore(frame *rtda.frame, index uint) {
val := frame.OperandStack().PopDouble()
frame.LocalVars().SetDouble(index, val)
}
4.5.3.fstore
//将栈顶元素存储到局部变量表指定位置
//该元素类型需为float
package stores
import (
"HandWritingJVM/instructions/base"
"HandWritingJVM/rtda"
)
type FSTORE struct {
base.Index8Instruction
}
func (self *FSTORE) Execute(frame *rtda.frame) {
_fstore(frame, uint(self.Index))
}
type FSTORE_0 struct {
base.Index8Instruction
}
func (self *FSTORE_0) Execute(frame *rtda.frame) {
_fstore(frame, 0)
}
type FSTORE_1 struct {
base.Index8Instruction
}
func (self *FSTORE_1) Execute(frame *rtda.frame) {
_fstore(frame, 1)
}
type FSTORE_2 struct {
base.Index8Instruction
}
func (self *FSTORE_2) Execute(frame *rtda.frame) {
_fstore(frame, 2)
}
type FSTORE_3 struct {
base.Index8Instruction
}
func (self *FSTORE_3) Execute(frame *rtda.frame) {
_fstore(frame, 3)
}
func _fstore(frame *rtda.frame, index uint) {
val := frame.OperandStack().PopFloat()
frame.LocalVars().SetFloat(index, val)
}
4.5.4.istore
//将栈顶元素存储到局部变量表指定位置
//该元素类型需为 int
package stores
import (
"HandWritingJVM/instructions/base"
"HandWritingJVM/rtda"
)
type ISTORE struct {
base.Index8Instruction
}
func (self *ISTORE) Execute(frame *rtda.frame) {
_istore(frame, uint(self.Index))
}
type ISTORE_0 struct {
base.NoOperandsInstruction
}
func (self *ISTORE_0) Execute(frame *rtda.frame) {
_istore(frame, 0)
}
type ISTORE_1 struct {
base.NoOperandsInstruction
}
func (self *ISTORE_1) Execute(frame *rtda.frame) {
_istore(frame, 1)
}
type ISTORE_2 struct {
base.NoOperandsInstruction
}
func (self *ISTORE_2) Execute(frame *rtda.frame) {
_istore(frame, 2)
}
type ISTORE_3 struct {
base.NoOperandsInstruction
}
func (self *ISTORE_3) Execute(frame *rtda.frame) {
_istore(frame, 3)
}
func _istore(frame *rtda.frame, index uint) {
val := frame.OperandStack().PopInt()
frame.LocalVars().SetInt(index, val)
}
4.5.5.lstore
//将栈顶元素存储到局部变量表指定位置
//该元素类型需为 long
package stores
import (
"HandWritingJVM/instructions/base"
"HandWritingJVM/rtda"
)
//将变量从操作数栈栈顶弹出并存入局部变量表
func _lstore(frame *rtda.frame, index uint) {
val := frame.OperandStack().PopLong()
frame.LocalVars().SetLong(index, val)
}
type LSTORE struct {
base.Index8Instruction
}
func (self *LSTORE) Execute(frame *rtda.frame) {
_lstore(frame, uint(self.Index))
}
type LSTORE_0 struct {
base.NoOperandsInstruction
}
func (self *LSTORE_0) Execute(frame *rtda.frame) {
_lstore(frame, 0)
}
type LSTORE_1 struct {
base.NoOperandsInstruction
}
func (self *LSTORE_1) Execute(frame *rtda.frame) {
_lstore(frame, 1)
}
type LSTORE_2 struct {
base.NoOperandsInstruction
}
func (self *LSTORE_2) Execute(frame *rtda.frame) {
_lstore(frame, 2)
}
type LSTORE_3 struct {
base.NoOperandsInstruction
}
func (self *LSTORE_3) Execute(frame *rtda.frame) {
_lstore(frame, 2)
}
4.5.6.xastore
//将元素存储到数组指定下标位置
package stores
import (
"HandWritingJVM/instructions/base"
"HandWritingJVM/instructions/constants"
"HandWritingJVM/rtda"
"HandWritingJVM/rtda/heap"
)
//数组
type AASTORE struct {
base.Index8Instruction
}
func (self *AASTORE) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
ref := stack.PopRef()
index := stack.PopInt()
arrRef := stack.PopRef()
checkNotNil(arrRef)
refs := arrRef.Refs()
checkIndex(len(refs), index)
refs[index] = ref
}
type BASTORE struct {
base.NoOperandsInstruction
}
func (self *BASTORE) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
val := stack.PopInt()
index := stack.PopInt()
arrRef := stack.PopRef()
checkNotNil(arrRef)
bytes := arrRef.Bytes()
checkIndex(len(bytes), index)
bytes[index] = int8(val)
}
type CASTORE struct {
base.NoOperandsInstruction
}
func (self *CASTORE) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
val := stack.PopInt()
index := stack.PopInt()
arrRef := stack.PopRef()
checkNotNil(arrRef)
chars := arrRef.Chars()
checkIndex(len(chars), index)
chars[index] = uint16(val)
}
type DASTORE struct {
base.NoOperandsInstruction
}
func (self *DASTORE) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
val := stack.PopDouble()
index := stack.PopInt()
arrRef := stack.PopRef()
checkNotNil(arrRef)
doubles := arrRef.Doubles()
checkIndex(len(doubles), index)
doubles[index] = float64(val)
}
type FASTORE struct {
base.NoOperandsInstruction
}
func (self *FASTORE) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
val := stack.PopFloat()
index := stack.PopInt()
arrRef := stack.PopRef()
checkNotNil(arrRef)
floats := arrRef.Floats()
checkIndex(len(floats), index)
floats[index] = val
}
type IASTORE struct {
base.NoOperandsInstruction
}
func (self *IASTORE) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
val := stack.PopInt()
index := stack.PopInt()
arrRef := stack.PopRef()
checkNotNil(arrRef)
ints := arrRef.Ints()
checkIndex(len(ints), index)
ints[index] = int32(val)
}
type LASTORE struct {
base.NoOperandsInstruction
}
func (self *LASTORE) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
val := stack.PopLong()
index := stack.PopInt()
arrRef := stack.PopRef()
checkNotNil(arrRef)
longs := arrRef.Longs()
checkIndex(len(longs), index)
longs[index] = int64(val)
}
type SASTORE struct {
base.NoOperandsInstruction
}
func (self *SASTORE) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
val := stack.PopInt()
index := stack.PopInt()
arrRef := stack.PopRef()
checkNotNil(arrRef)
shorts := arrRef.Shorts()
checkIndex(len(shorts), index)
shorts[index] = int16(val)
}
func checkNotNil(ref *heap.Object) {
if ref == nil {
panic(constants.NullPointerException)
}
}
func checkIndex(arrLen int, index int32) {
if index < 0 || index >= int32(arrLen) {
panic(constants.ArrayIndexOutOfBoundsException)
}
}
4.6.栈指令
4.6.1.dup
解释:栈中元素的复制
package stack
import (
"HandWritingJVM/instructions/base"
"HandWritingJVM/rtda"
)
// ... 1 -> ... 1 1
type DUP struct {
base.NoOperandsInstruction
}
//复制栈顶的变量
func (self *DUP) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
slot := stack.PopSlot()
stack.PushSlot(slot)
stack.PushSlot(slot)
}
//复制栈顶的下一个元素
// ... 2 1 -> ... 1 2 1
type DUP_X1 struct {
base.NoOperandsInstruction
}
func (self *DUP_X1) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
slot1 := stack.PopSlot()
slot2 := stack.PopSlot()
stack.PushSlot(slot1)
stack.PushSlot(slot2)
stack.PushSlot(slot1)
}
// ... 3 2 1 -> ... 1 3 2 1
type DUP_X2 struct {
base.NoOperandsInstruction
}
func (self *DUP_X2) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
slot1 := stack.PopSlot()
slot2 := stack.PopSlot()
slot3 := stack.PopSlot()
stack.PushSlot(slot1)
stack.PushSlot(slot3)
stack.PushSlot(slot2)
stack.PushSlot(slot1)
}
// ... 2 1 -> ... 2 1 2 1
type DUP2 struct {
base.NoOperandsInstruction
}
func (self *DUP2) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
slot1 := stack.PopSlot()
slot2 := stack.PopSlot()
stack.PushSlot(slot2)
stack.PushSlot(slot1)
stack.PushSlot(slot2)
stack.PushSlot(slot1)
}
//... 3 2 1 -> ... 2 1 3 2 1
type DUP2_X1 struct {
base.NoOperandsInstruction
}
func (self *DUP2_X1) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
slot1 := stack.PopSlot()
slot2 := stack.PopSlot()
slot3 := stack.PopSlot()
stack.PushSlot(slot2)
stack.PushSlot(slot1)
stack.PushSlot(slot3)
stack.PushSlot(slot2)
stack.PushSlot(slot1)
}
// ... 4 3 2 1 -> ... 2 1 4 3 2 1
type DUP2_X2 struct {
base.NoOperandsInstruction
}
func (self *DUP2_X2) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
slot1 := stack.PopSlot()
slot2 := stack.PopSlot()
slot3 := stack.PopSlot()
slot4 := stack.PopSlot()
stack.PushSlot(slot2)
stack.PushSlot(slot1)
stack.PushSlot(slot4)
stack.PushSlot(slot3)
stack.PushSlot(slot2)
stack.PushSlot(slot1)
}
4.6.2.pop
解释:弹出栈顶元素
package stack
import (
"HandWritingJVM/instructions/base"
"HandWritingJVM/rtda"
)
//弹出一个元素
type POP struct {
base.NoOperandsInstruction
}
func (self *POP) Execute(frame *rtda.frame) {
frame.OperandStack().PopSlot()
}
//弹出2个元素
type POP2 struct {
base.NoOperandsInstruction
}
func (self *POP2) Execute(frame *rtda.frame) {
frame.OperandStack().PopSlot()
frame.OperandStack().PopSlot()
}
4.6.3.SWAP
解释:交换栈顶前2个元素
package stack
import (
"HandWritingJVM/instructions/base"
"HandWritingJVM/rtda"
)
// ... 2 1 -> ... 1 2
type SWAP struct {
base.NoOperandsInstruction
}
func (self *SWAP) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
slot1 := stack.PopSlot()
slot2 := stack.PopSlot()
stack.PushSlot(slot2)
stack.PushSlot(slot1)
}
4.7.数学指令
4.7.1.add
解释:从栈中弹出2个元素相加后重新推入栈中
package math
import (
"HandWritingJVM/instructions/base"
"HandWritingJVM/rtda"
)
type DADD struct {
base.NoOperandsInstruction
}
func (self *DADD) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
v1 := stack.PopDouble()
v2 := stack.PopDouble()
res := v1 + v2
stack.PushDouble(res)
}
type FADD struct {
base.NoOperandsInstruction
}
func (self *FADD) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
v1 := stack.PopFloat()
v2 := stack.PopFloat()
res := v1 + v2
stack.PushFloat(res)
}
type IADD struct {
base.NoOperandsInstruction
}
func (self *IADD) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
v1 := stack.PopInt()
v2 := stack.PopInt()
res := v1 + v2
stack.PushInt(res)
}
type LADD struct {
base.NoOperandsInstruction
}
func (self *LADD) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
v1 := stack.PopLong()
v2 := stack.PopLong()
res := v1 + v2
stack.PushLong(res)
}
4.7.2.and
解释:从栈顶弹出2个元素相&后推入栈中
package math
import (
"HandWritingJVM/instructions/base"
"HandWritingJVM/rtda"
)
type IAND struct {
base.NoOperandsInstruction
}
func (self *IAND) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
v2 := stack.PopInt()
v1 := stack.PopInt()
result := v1 & v2
stack.PushInt(result)
}
type LAND struct {
base.NoOperandsInstruction
}
func (self *LAND) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
l2 := stack.PopLong()
l1 := stack.PopLong()
result := l1 & l2
stack.PushLong(result)
}
4.7.3.div
解释:从栈中弹出2个元素相除后将结果推入栈中
package math
import (
"HandWritingJVM/instructions/base"
"HandWritingJVM/rtda"
)
type DDIV struct {
base.NoOperandsInstruction
}
func (self *DDIV) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
v2 := stack.PopDouble()
v1 := stack.PopDouble()
res := v1 / v2
stack.PushDouble(res)
}
type FDIV struct {
base.NoOperandsInstruction
}
func (self *FDIV) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
v2 := stack.PopFloat()
v1 := stack.PopFloat()
res := v1 / v2
stack.PushFloat(res)
}
type IDIV struct {
base.NoOperandsInstruction
}
func (self *IDIV) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
v2 := stack.PopInt()
v1 := stack.PopInt()
res := v1 / v2
stack.PushInt(res)
}
type LDIV struct {
base.NoOperandsInstruction
}
func (self *LDIV) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
v2 := stack.PopLong()
v1 := stack.PopLong()
res := v1 / v2
stack.PushLong(res)
}
4.7.4.iinc
解释:将局部变量表中指定下标的元素加上某一值
package math
import (
"HandWritingJVM/instructions/base"
"HandWritingJVM/rtda"
)
type IINC struct {
base.Index8Instruction
Const int32
}
func (self *IINC) FetchOperands(reader *base.BytecodeReader) {
self.Index = uint(reader.ReadUint8())
self.Const = int32(reader.ReadInt8())
}
func (self *IINC) Execute(frame *rtda.frame) {
localVars := frame.LocalVars()
val := localVars.GetInt(self.Index)
val += self.Const
localVars.SetInt(self.Index, val)
}
4.7.5.mul
解释:从栈中弹出2个元素后相乘后再推入栈中;
package math
import (
"HandWritingJVM/instructions/base"
"HandWritingJVM/rtda"
)
type DMUL struct {
base.NoOperandsInstruction
}
func (self *DMUL) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
v1 := stack.PopDouble()
v2 := stack.PopDouble()
res := v1 * v2
stack.PushDouble(res)
}
type FMUL struct {
base.NoOperandsInstruction
}
func (self *FMUL) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
v1 := stack.PopFloat()
v2 := stack.PopFloat()
res := v1 * v2
stack.PushFloat(res)
}
type IMUL struct {
base.NoOperandsInstruction
}
func (self *IMUL) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
v1 := stack.PopInt()
v2 := stack.PopInt()
res := v1 * v2
stack.PushInt(res)
}
type LMUL struct {
base.NoOperandsInstruction
}
func (self *LMUL) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
v1 := stack.PopLong()
v2 := stack.PopLong()
res := v1 * v2
stack.PushLong(res)
}
4.7.6.neg
解释:弹出栈顶元素取反后重新推入栈中
package math
import (
"HandWritingJVM/instructions/base"
"HandWritingJVM/rtda"
)
type DNEG struct {
base.NoOperandsInstruction
}
func (self *DNEG) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
val := stack.PopDouble()
stack.PushDouble(-val)
}
type FNEG struct {
base.NoOperandsInstruction
}
func (self *FNEG) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
stack.PushFloat(-stack.PopFloat())
}
type INEG struct {
base.NoOperandsInstruction
}
func (self *INEG) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
stack.PushInt(-stack.PopInt())
}
type LNEG struct {
base.NoOperandsInstruction
}
func (self *LNEG) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
stack.PushLong(-stack.PopLong())
}
4.6.7.or
解释:弹出栈中的2个元素相或后重新推入栈中
package math
import (
"HandWritingJVM/instructions/base"
"HandWritingJVM/rtda"
)
type IOR struct {
base.NoOperandsInstruction
}
func (self *IOR) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
v2 := stack.PopInt()
v1 := stack.PopInt()
res := v1 | v2
stack.PushInt(res)
}
type LOR struct {
base.NoOperandsInstruction
}
func (self *LOR) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
v2 := stack.PopLong()
v1 := stack.PopLong()
res := v1 | v2
stack.PushLong(res)
}
4.6.8.rem
解释:弹出栈顶2个元素,取余后将结果重新推入栈中
package math
import (
"HandWritingJVM/instructions/base"
"HandWritingJVM/rtda"
"math"
)
type DREM struct {
base.NoOperandsInstruction
}
func (self *DREM) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
v2 := stack.PopDouble()
v1 := stack.PopDouble()
result := math.Mod(v1, v2)
stack.PushDouble(result)
}
type IREM struct {
base.NoOperandsInstruction
}
func (self *IREM) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
v2 := stack.PopInt()
v1 := stack.PopInt()
if v2 == 0 {
panic("java.lang.ArithmeticException: / by zero")
}
result := v1 % v2
stack.PushInt(result)
}
type FREM struct {
base.NoOperandsInstruction
}
func (self *FREM) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
v2 := stack.PopFloat()
v1 := stack.PopFloat()
if v2 == 0 {
panic("java.lang.ArithmeticException: / by zero")
}
result := float32(math.Mod(float64(v1), float64(v2)))
stack.PushFloat(result)
}
type LREM struct {
base.NoOperandsInstruction
}
func (self *LREM) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
v2 := stack.PopLong()
v1 := stack.PopLong()
if v2 == 0 {
panic("java.lang.ArithmeticException: / by zero")
}
result := v1 % v2
stack.PushLong(result)
}
4.6.9.sh
解释:弹出栈顶2个元素,一个是值,一个是位移距离;
package math
import (
"HandWritingJVM/instructions/base"
"HandWritingJVM/rtda"
)
//int左移位
type ISHL struct {
base.NoOperandsInstruction
}
func (self *ISHL) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
v2 := stack.PopInt()
v1 := stack.PopInt()
s := uint32(v2) & 0x1f
result := v1 << s
stack.PushInt(result)
}
//int 右移位
type ISHR struct {
base.NoOperandsInstruction
}
func (self *ISHR) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
v2 := stack.PopInt()
v1 := stack.PopInt()
s := uint32(v2) & 0x1f
result := v1 >> s
stack.PushInt(result)
}
//int 无符号右移位
type IUSHR struct {
base.NoOperandsInstruction
}
func (self *IUSHR) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
v2 := stack.PopInt()
v1 := stack.PopInt()
s := uint32(v2) & 0x1f
result := int32(uint32(v1) >> s)
stack.PushInt(result)
}
//long 左移位
type LSHL struct {
base.NoOperandsInstruction
}
func (self *LSHL) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
v2 := stack.PopInt()
v1 := stack.PopLong()
s := uint32(v2) & 0x3f
result := v1 << s
stack.PushLong(result)
}
//long右移位
type LSHR struct {
base.NoOperandsInstruction
}
func (self *LSHR) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
v2 := stack.PopInt()
v1 := stack.PopLong()
s := uint32(v2) & 0x3f
result := v1 >> s
stack.PushLong(result)
}
//long 无符号右移位
type LUSHR struct {
base.NoOperandsInstruction
}
func (self *LUSHR) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
v2 := stack.PopInt()
v1 := stack.PopLong()
s := uint32(v2) & 0x3f
result := int64(uint64(v1) >> s)
stack.PushLong(result)
}
4.6.10.sub
解释:弹出栈顶2个元素,相减后将结果推入栈中
package math
import (
"HandWritingJVM/instructions/base"
"HandWritingJVM/rtda"
)
type DSUB struct {
base.NoOperandsInstruction
}
func (self *DSUB) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
v2 := stack.PopDouble()
v1 := stack.PopDouble()
res := v1 - v2
stack.PushDouble(res)
}
type FSUB struct {
base.NoOperandsInstruction
}
func (self *FSUB) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
v2 := stack.PopFloat()
v1 := stack.PopFloat()
res := v1 - v2
stack.PushFloat(res)
}
type ISUB struct {
base.NoOperandsInstruction
}
func (self *ISUB) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
v2 := stack.PopInt()
v1 := stack.PopInt()
res := v1 - v2
stack.PushInt(res)
}
type LSUB struct {
base.NoOperandsInstruction
}
func (self *LSUB) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
v2 := stack.PopLong()
v1 := stack.PopLong()
res := v1 - v2
stack.PushLong(res)
}
4.6.11.xor
解释:弹出栈顶2个元素,相异或后将结果推入栈中
package math
import (
"HandWritingJVM/instructions/base"
"HandWritingJVM/rtda"
)
type IXOR struct {
base.NoOperandsInstruction
}
func (self *IXOR) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
v1 := stack.PopInt()
v2 := stack.PopInt()
res := v1 ^ v2
stack.PushInt(res)
}
type LXOR struct {
base.NoOperandsInstruction
}
func (self *LXOR) Execute(frame *rtda.frame) {
stack := frame.OperandStack()
v1 := stack.PopLong()
v2 := stack.PopLong()
res := v1 ^ v2
stack.PushLong(res)
}
4.7.类型转换指令
//待续



