「700行手写编译器」Part 2.1:虚拟机与指令集 笔记

项目中设计的VM指令集说明
在这里插入图片描述
VM指令集:
1.Save & Load:IMM(immediate的缩写,加载立即数),LEA(load effective address),LC(load char), LI(load integer),SC(save char),SI(save integer),PUSH(将寄存器数据推到栈顶)
2.算数逻辑运算:ADD,SUB,MUL,DIV,MOD,OR,XOR,AND,SHL(左移),SHR(右移),IQ(相等),NE(不等),LT(less then),LE(less equal),GT(great then),GE(great equal)
3.分支跳转:JMP,JZ(jump zero),JNZ(jump not zero),CALL,NVAR(new stack frame for variable),DARG(delete stack frame for argument),RET(return)
4.Native-Call:OPEN(打开文件),CLOSE(关闭文件),READ(读取文件),(没有WRITE写文件,因为c4源码里面没有用到write方法,这这里并没有实现write指令),PRTF(printf,相当于实现了一个write,输出到了标准输出,也就是fd=1的地方),MACC,FREE,MSET,MCMP(MEM compare),EXIT(终止程序)

1.Save & Load

在这里插入图片描述

// load & save
if (op == IMM)          ax = *pc++;                     //意思是解析完当前的代码PC指的是IMM
//pc会移动到IMM要操作的立即数的位置,然后*pc取出要操作的立即数给通用寄存器ax,然后pc++,继续往后移动pc,往后执行代码
else if (op == LEA)     ax = (int)(bp + *pc++);         //LEA的操作简化
//这里的LEA是自定义的与x86直接运算+8不同(对x86来说LEA AX,是说*(bp+8)->ax)
else if (op == LC)      ax = *(char*)ax;                // load char,ax中现在装的是一个地址,把地址对应的值移到ax中,下面的LI同理
else if (op == LI)      ax = *(int*)ax;                 // load int
else if (op == SC)      *(char*)*sp++ = ax;             //sp里面存的是一个地址,然后(char*)将地址强制转换为char*类型,
//然后再对地址dereference(就是*),拿到地址所在的char的空间,把ax中的数据存入这个空间,然后sp++,当前的sp的位置就用完了,sp指针就向上移动,释放了原来sp的存储
else if (op == SI)      *(int*)*sp++ = ax;              // save int to stack
else if (op == PUSH)    *--sp = ax;                     // push ax to stack,这里设计的是sp指向有数据的位置的栈顶指针,满栈的类型,所以要先--sp,再dereference sp的地址后,在对应位置存入ax

满栈(full stack):栈指针指向最后压入栈的数据,数据入栈时,sp先减一(或加一)再入栈。(也就是SP指的位置本身是有数据的)

空栈(empty stack):栈指针指向下一个将要放入数据的位置,数据入栈时,先入栈sp再减一(或加一)。(也就是SP指的位置本身是空的)

2.算数逻辑运算

在这里插入图片描述

// arithmetic
else if (op == OR)      ax = *sp++ |  ax;   //逻辑运算
else if (op == XOR)     ax = *sp++ ^  ax;
else if (op == AND)     ax = *sp++ &  ax;
else if (op == EQ)      ax = *sp++ == ax;   //逻辑判断,结果应该是true和false,但是这个版本没有bool类型,所以输出0或者1
else if (op == NE)      ax = *sp++ != ax;
else if (op == LT)      ax = *sp++ <  ax;
else if (op == LE)      ax = *sp++ <= ax;
else if (op == GT)      ax = *sp++ >  ax;
else if (op == GE)      ax = *sp++ >= ax;
else if (op == SHL)     ax = *sp++ << ax;   //位运算
else if (op == SHR)     ax = *sp++ >> ax;
else if (op == ADD)     ax = *sp++ +  ax;   //算术运算
else if (op == SUB)     ax = *sp++ -  ax;
else if (op == MUL)     ax = *sp++ *  ax;
else if (op == DIV)     ax = *sp++ /  ax;
else if (op == MOD)     ax = *sp++ %  ax;

在这里插入图片描述
JMP:直接调到所给的地址的位置
JZ ax:判断 ax=0跳转,ax!=0不跳转
JNZ ax:判断 ax!=0跳转,ax=0不跳转

// jump
else if (op == JMP)     pc = (int*)*pc;                 // jump
else if (op == JZ)      pc = ax ? pc + 1 : (int*)*pc;   // jump if ax == 0
else if (op == JNZ)     pc = ax ? (int*)*pc : pc + 1;   // jump if ax != 0
  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱吃小酥肉的小波

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值