-
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