-
Notifications
You must be signed in to change notification settings - Fork 4
虚拟机规范
wener edited this page Dec 13, 2015
·
2 revisions
- 以行为单位
指令 | 描述 | 语法 |
---|---|---|
NOP | 无任何操作 | EXIT |
LD | Load 赋值 | LD 数据类型 操作数, 操作数 |
PUSH | 压栈 | PUSH 操作数 |
POP | 出栈 | POP 操作数 |
IN | 系统端口调用 | IN 操作数, 操作数 |
OUT | 系统端口调用 | OUT 操作数, 操作数 |
JMP | Jump - 跳转 | JMP 操作数 |
JPC | Jump compare 条件跳转 |
JPC 比较类型 操作数 |
CALL | 调用 | CALL 操作数 |
RET | 返回 | RET |
CMP | Compare - 比较 | CMP 比较类型 操作数, 操作数 |
CAL | Calculate - 计算 | CAL 数据类型 计算类型 操作数, 操作数 |
EXIT | 退出 | EXIT |
DATA | 数据伪指令 | DATA 标示符 数据[,数据[,数据...]] |
BLOCK | 块数据伪指令 | BLOCK 长度, 数据 |
表示 | 机器码 | 说明 |
---|---|---|
RX | 0x0 | 寄存器寻址 |
[RX] | 0x1 | 寄存器间接寻址 |
N | 0x2 | 立即数寻址 |
[N] | 0x3 | 直接寻址 |
A/B | RX | [RX] | N | [N] |
---|---|---|---|---|
RX | 0x0 | 0x1 | 0x2 | 0x3 |
[RX] | 0x4 | 0x5 | 0x6 | 0x7 |
N | 0x8 | 0x9 | 0xA | 0xB |
[N] | 0xC | 0xD | 0xE | 0xF |
寄存器 | 机器码 | 说明 |
---|---|---|
RP | 0x0 | 程序计数器,指令寻址寄存器 |
RF | 0x1 | 标志寄存器,存储比较操作结果 |
RS | 0x2 | 栈寄存器 空栈顶地址,指向的是下一个准备要压入数据的位置 |
RB | 0x3 | 辅助栈寄存器 栈开始的地址(文件长度+2) |
R0 | 0x4 | #0 寄存器 |
R1 | 0x5 | #1 寄存器 |
R2 | 0x6 | #2 寄存器 |
R3 | 0x7 | #3 寄存器 |
注意
: 默认栈大小为 1000b
: 假如rb和rs分别为1260,260,那么push一次后, rb 变为 1256.
: 每 call 一次,向栈中写入一个返回地址
: CMP int 2,1
后, rf
为4, 即 A
,只会为 A B N
, 即大于小于等于
数据类型 | 机器码 |
---|---|
DWORD | 0x0 |
WORD | 0x1 |
BYTE | 0x2 |
FLOAT | 0x3 |
INT | 0x4 |
算术类型 | 机器码 |
---|---|
ADD | 0x0 |
SUB | 0x1 |
MUL | 0x2 |
DIV | 0x3 |
MOD | 0x4 |
比较操作 | 机器码 | 说明 |
---|---|---|
Z | 0x1 | 等于 |
B | 0x2 | Below,小于 |
BE | 0x3 | 小于等于 |
A | 0x4 | Above,大于 |
AE | 0x5 | 大于等于 |
NZ | 0x6 | 不等于 |
指令 | 机器码 | 说明 |
---|---|---|
NOP | 0x0 | 无操作 |
LD | 0x1 | 数据读写 |
PUSH | 0x2 | 入栈 |
POP | 0x3 | 出栈 |
IN | 0x4 | IN端口调用 |
OUT | 0x5 | OUT端口调用 |
JMP | 0x6 | 跳转 |
JPC | 0x7 | 条件跳转 |
CALL | 0x8 | 调用跳转 |
RET | 0x9 | 返回 |
CMP | 0xA | 比较 |
CAL | 0xB | 算术运算 |
EXIT | 0xF | 退出 |
DATA | n/a | 伪指令 |
BLOCK | n/a | 伪指令 |
- NOP,RET,EXIT 无操作数 长度为 1
- JMP,PUSH,CALL,POP 一个操作数 长度为 5
- JPC 一个操作数 长度为 6
- LD,IN,OUT,CMP,CAL 两个操作数 长度为 10
- JPC 根据 rf 来判断是否跳转
- JPC 比较特殊,数据类型为__比较操作__,该指令只有6个字节
- CAL 使用特殊用途字节来指定算术类型
- CAL 数据类型 ADD 操作数1, 操作数2 返回值写入操作数1
- CAL 在计算 BYTE,如果越界了,是直接减去256,例如
ld int r1 300
cal int add r1,r1
; r1 的结果为 344 = 600 -256
- TODO: CAL 在计算WORD,如果越界了,不清楚是怎么处理的
- LD 能处理 byte 和 word 的溢出问题,但是对于超过int或dwrod的溢出,不知道是怎么处理的
-
LD FLOAT
和LD DWORD
没有实际意义,和LD INT
一样
指令码 + 数据类型 + 特殊用途字节 + 寻址方式 + 第一个操作数 + 第二个操作数
0x 0 0 0 0 0000 0000
- 在长度为 1 的操作码中, 数据类型 为 寻址方式
- 在长度为 5 的操作码中,没有
特殊用途字节 + 寻址方式
- 无操作数的时候,寻址方式为0
- 无数据类型,数据类型为0
- CAL 使用特殊用途字节来指定算术类型
- JPC 比较特殊,数据类型为__比较操作__,该指令只有6个字节
- BB 为 LITTLE_ENDIAN
- 原始编码为GBK
- 给定一个地址作为参数地址开始的参数,都是逆序的,例如
; SHOWPIC(PAGE,PIC,DX,DY,W,H,X,Y,MODE) data SHOWPIC_PARAM_INV int MODE, 0, 0, 320, 240, 0, 0, 0, PAGE
- BBAsm 的数据标签和跳转标签大小写敏感
- BBAsm 的指令大小写不敏感
句柄是否会重用 栈的具体布局和行为
文件结构
|<--文件头-->|<--执行内容-->|
内存结构
|<--内存-->|<--栈-->|
- 文件头
- 16 byte
- 栈
- 1024 byte