在上篇设计了一个极简单的CPU,并定义了相应的寄存器和指令集。接下来就是利用定义的寄存器和指令集完成一个程序,最后实现一个虚拟机来运行这个程序。
这个程序由汇编语言编写,并且手工编译成机器码。为了简单起见,设定CPU的寻址范围为64字节。程序代码为:
CODE:
04 12 I_JMP 12 //直接跳转到内存12的地址
DATA:
00 00 01 00 07 0F 08 07 00 00 00 00 00 00 00 00 //03-11为数据区
CODE:
02 03 04 I_ADD 03 04 //将03和04地址内容相加,结果送入03地址
02 05 06 I_ADD 05 06 //将05和06地址内容相加,结果送入05地址
03 03 07 I_CMP 03 07 //比较03和07地址内容
05 1E 20 I_JCP 1E 20 //根据寄存器R_CMP的值决定跳转到1E或20地址
04 23 I_JMP 23 //直接跳转到23地址
01 03 02 I_MOV 03 02 //把02地址内容送至03地址
03 05 07 I_CMP 05 07 //比较05和07地址内容
05 29 2B I_JCP 29 2B //根据寄存器R_CMP的值决定跳转到29或2B地址
04 2E I_JMP 2E //直接跳转到2E地址
01 05 02 I_MOV 05 02 //把02地址内容送至05地址
04 12 I_JMP 12 //直接跳转到内存12的地址
接着用任意16进制编辑器将机器码和数据输入,然后另存为一个文件,这里另存为rom.bin。如下图:

最后,需要将程序载入内存,为虚拟机运行程序做准备,对应代码为:
#define MEMSIZE 64
unsigned char* RAM;
int loadROM(void);
int memInit(void);
void memFree(void);
int loadROM(void)
{
FILE* rom;
if ((rom = fopen("rom.bin", "r")) == NULL)
{
MessageBox(NULL, "Cannot find rom file", "Warning", MB_OK);
return 1;
}
fread((void*)RAM, sizeof(char), MEMSIZE, rom);
fclose(rom);
return 0;
}
int memInit(void)
{
RAM = (unsigned char*)GlobalAlloc(GMEM_FIXED,MEMSIZE);
if (RAM == NULL)
{
MessageBox(NULL, "Cannot allocate enough memory", "Error", MB_OK);
return 1;
}
return 0;
}
void memFree(void)
{
GlobalFree(RAM);
}
当然,也可以用int数组来保存这段程序,但这里只是希望看起来更像是真正的外部程序。

浙公网安备 33010602011771号