三、虚拟机(2)
虚拟机指令处理函数。
我们找一个结构清晰一点的函数作为例子,例如 VM_FN_FONTINFO
该指令让yst脚本可以获取字体相关的信息。
先进去看 VM_PrepareInstructionCode 这个函数:
这个函数里有一个循环,解析了一个虚拟机函数中的所有指令。
这个循环里,将每个指令:是否执行、所需参数、所需数据,等相关信息都存储到了数组里。
gInstDataOffsetMap[ ] 指令所需的数据在DataSection中的偏移量
gInstDataLengthMap[ ] 指令所需的数据的长度
INST_CTX_INT_BUF[ ] 指令的一个简单整型参数
INST_CTX_DBL_BUF[ ] 指令的int64型参数
INST_CTX_STR_BUF[ ] 指令的字符串型参数
等等。
此外,加载指令参数,还需要通过一系列函数进行加载,而不是简单的读取数据。
指令可以指定任意一种方式加载参数。
例如,加载一个字符串型的参数
跟进VM_LoadData
其中,gDataPtr就是上面的 gInstDataOffsetMap[ j ] 指定该参数的数据在DataSection中的偏移量
数据长度 length 同理。
此外还可以看到,VM_LoadData 加载数据,实际上调用了VM_STACK_FN_TABLE里的函数,
并且,VM_LoadData 是在循环里调用 这些函数的,也就是说,当加载一个指令的参数时,不仅可以直接加载数值或者字符串,还可以在加载后进行一些计算和判断,并且这些Load函数中,有一些是获取引擎当前的数据的。
这个参数加载的处理,可以说挺花哨的了。
加载一个64位数值到虚拟机栈里。
以下是简单反汇编的脚本,其中只包含了虚拟机函数和其函数指令,没有包含指令数据加载的反汇编。
可以看到还是勉强能看到一个执行流程的