CHIP指令表
CHIP-8有35个指令,都为两字节长,以大端方式存储。指令表的指令格式规定如下:
NNN | 地址 |
NN | 8位常量 |
N | 4位常量 |
V | 寄存器 |
X和Y | 4位,标识寄存器 |
PC | 程序计数器 |
I | 16位索引地址寄存器 |
序号 | 操作码 | 类型 | 功能描述 |
---|---|---|---|
1 | 0NNN | 调用 | 执行地址NNN的子程序 |
2 | 00E0 | 显示 | 清屏 |
3 | 00EE | 跳转 | 从子程序返回 |
4 | 1NNN | 跳转 | 跳转到地址NNN |
5 | 2NNN | 跳转 | 调用子程序NNN |
6 | 3XNN | 条件 | 如果VX等于NN则跳过下一条指令(通常时跳过一条跳转指令) |
7 | 4XNN | 条件 | 如果VX不等于NN则跳过下一条指令(同上) |
8 | 5XY0 | 条件 | 如果VX的值等于VY则跳过下一条指令(同上) |
9 | 6XNN | 赋值 | VX = NN |
10 | 7XNN | 赋值 | VX += NN,进位标记不会改变 |
11 | 8XY0 | 赋值 | VX = VY |
12 | 8XY1 | 按位或 | VX = VX |
13 | 8XY2 | 按位与 | VX = VX & VY |
14 | 8XY3 | 按位异或 | VX = VX ^ VY |
15 | 8XY4 | 运算 | VX += VY,VX有进位(大于255)时VF为1,否则VF为0 |
16 | 8XY5 | 运算 | VX -= VY,VX负数时VF为0,否则VF为1 |
17 | 8XY6 | 右移 | VX >>= 1,VX最低位存入VF中 |
18 | 8XY7 | 运算 | VX = VY - VX,VX负数时VF为0,否则VF为1 |
19 | 8XYE | 左移 | VX <<= 1,VX最高位存入VF中 |
20 | 9XY0 | 条件 | 如果VX不等于VY则跳过下一条指令(通常时跳过一条跳转指令) |
21 | ANNN | 地址 | 将I设置为NNN |
22 | BNNN | 跳转 | 跳转到地址V0+NNN,PC=V0+NNN |
23 | CXNN | 随机数 | VX = rand() & NN |
24 | DXYN | 显示 | 在(VX,VY)绘制一个宽8像素、高N像素的精灵。每8个像素从I寄存器中的地址逐步读出一字节(8位),在执行该语句时I内的值不可以改变,如果像素反转为0则碰撞检测将VF置为1 |
25 | EX9E | 按键 | 跳过下一条指令,如果存储在VX的键值所应的键被按下 |
26 | EXA1 | 按键 | 跳过下一条指令,如果存储在VX的键值所应的键没有被按下 |
27 | FX07 | 定时器 | 获取延时寄存器的值 |
28 | FX0A | 按键 | 等待按键,将按键的值存入VX(阻塞指令,所有指令将等待该指令执行完 |
29 | FX15 | 定时器 | 将VX的值存入延时寄存器 |
30 | FX18 | 定时器 | 将VX的值存入声音寄存器 |
31 | FX1E | 地址 | I += VX |
32 | FX29 | 地址 | 将VX中的精灵地址赋值给I,字符0-F由4X5字体表示 |
33 | FX33 | BCD | 将VX中值的BCD码存入I中的地址内,百位在I,十位在I+1,个位在I+2 |
34 | FX55 | 地址 | 将V0到VX的值存入I中地址为起始的内存空间 |
35 | FX65 | 地址 | 将I中地址为起始的内容依次存入V0-VX |
对每一个OPcode的实现
//no action
memset(gfx, 0, sizeof(gfx));
drawFlag = true;
pc += 2;
pc = stack[--sp] + 2;
pc = opcode & 0x0FFF;
stack[sp++] = pc;
pc = opcode & 0x0FFF;
pc += (V[(opcode & 0x0F00) >> 8] == (opcode & 0x00FF)) ? 4 : 2;
pc += (V[(opcode & 0x0F00) >> 8] != (opcode & 0x00FF)) ? 4 : 2;
pc += (V[(opcode & 0x0F00) >> 8] == V[(opcode & 0x00F0) >> 4]) ? 4 : 2;
V[(opcode & 0x0F00) >> 8] = opcode & 0x00FF;
pc += 2;
V[(opcode & 0x0F00) >> 8] += opcode & 0x00FF;
pc += 2;
V[(opcode & 0x0F00) >> 8] = V[(opcode & 0x00F0) >> 4];
pc += 2;
V[(opcode & 0x0F00) >> 8] | = V[(opcode & 0x00F0) >> 4];
pc += 2;
V[(opcode & 0x0F00) >> 8] &= V[(opcode & 0x00F0) >> 4];
pc += 2;
V[(opcode & 0x0F00) >> 8] ^= V[(opcode & 0x00F0) >> 4];
pc += 2;
V[0xF] = V[(opcode & 0x00F0) >> 4] > (0xFF - V[(opcode &0x0F00) >> 8]);
V[(opcode & 0x0F00) >> 8] += V[(opcode & 0x00F0) >> 4];
pc += 2;
V[0xF] = !(V[(opcode & 0x00F0) >> 4] > V[(opcode & 0x0F00) >> 8]);
V[(opcode & 0x0F00) >> 8] -= V[(opcode & 0x00F0) >> 4];
pc += 2;
V[0xF] = V[(opcode & 0x0F00) >> 8] & 0x1;
V[(opcode & 0x0F00) >> 8] >>= 1;
pc += 2;
V[0xF] = !(V[(opcode & 0x0F00) >> 8] > V[(opcode & 0x00F0) >> 4]);
V[(opcode & 0x0F00) >> 8] = V[(opcode & 0x00F0) >> 4] - V[(opcode & 0x0F00) >> 8];
pc += 2;
V[0xF] = V[(opcode & 0x0F00) >> 8] >> 7;
V[(opcode & 0x0F00) >> 8] <<= 1;
pc += 2;
pc += (V[(opcode & 0x0F00) >> 8] != V[(opcode & 0x00F0) >> 4]) ? 4 : 2;
I = opcode & 0x0FFF;
pc += 2;
pc = (opcode & 0x0FFF) + V[0];
V[(opcode & 0x0F00) >> 8] = (rand % 0xFF) & (opcode & 0x00FF);
pc += 2;
unsigned short x = V[(opcode & 0x0F00) >> 8];
unsigned short y = V[(opcode & 0x00F0) >> 4];
unsigned short height = opcode & 0x000F;
unsigned short pixel = 0;
V[0xF] = 0;
for(int yline = 0; yline < height; ++yline) {
pixel = memory[I+yline];
for(int xline = 0; xline < 8; ++xline) {
if((pixel & (0x80 >> xline)) != 0)
{
if(gfx[(x + xline + ((y + yline) * 64))] == 1)
{
V[0xF] = 1;
}
gfx[x + xline + ((y + yline) * 64)] ^= 1;
}
}
}
drawFlag = true;
pc += 2;
pc += (key[V[(opcode & 0x0F00) >> 8]]) ? 4 : 2;
pc += (key[V[(opcode & 0x0F00) >> 8]]) ? 2 : 4;
V[(opcode & 0x0F00) >> 8] = delay_timer;
pc += 2;
bool keyPress = false;
for(int i = 0; i < 16; ++i)
{
if(key[i] != 0)
{
V[(opcode & 0x0F00) >> 8] = i;
keyPress = true;
}
}
if(!keyPress) {
return;
}
pc += 2;
delay_timer = V[(opcode & 0x0F00) >> 8];
pc += 2;
sound_timer = V[(opcode & 0x0F00) >> 8];
pc += 2;
V[0xF] = (I + V[(opcode & 0x0F00) >> 8]) > 0xFFF;
I += V[(opcode & 0x0F00) >> 8];
pc += 2;
I = V[(opcode & 0x0F00) >> 8] * 5;
pc += 2;
unsigned short vx = V[(opcode & 0x0F00) >> 8];
memory[I] = vx / 100;
memory[I+1] = vx / 10 % 10;
memory[I+2] = vx % 10;
pc += 2;
unsigned short vx = V[(opcode & 0x0F00) >> 8];
for(int i = 0; i <= vx; ++i) {
memory[I+i] = V[i];
}
I += ((opcode & 0x0F00) >> 8) + 1;
pc += 2;
unsigned short vx = V[(opcode & 0x0F00) >> 8];
for(int i = 0; i <= vx; ++i) {
V[i] = memory[I+i];
}
I += ((opcode & 0x0F00) >> 8) + 1;
pc += 2;