小计算器/译原理学习日记简单指令型计算器(2)虚拟机的实现
出自Cn.18dao.net
| 您当前所在的位置:首页 > 财务类 > 小计算器 > 译原理学习日记简单指令型计算器(2)虚拟机的实现 |
|
|
|
首先,我对指令系统进行了完善,主要是添加了很多三角函数指令,尤其是双曲函数。还有,我修改了操作数和指令的数据类型,通过使用typedef语句,我将操作数类型声明为double、将指令类型声明为unsigned char。这主要体现在inst.h的改动中,我在其中添加了如下声明:
/* type of instructions: */
typedef unsigned char inst_t;
/* type of operands: */
typedef double operand_t;
这使得我的程序更具伸缩性。当然,这些改动使得我同时改动了汇编编译器和反汇编编译器。如果大家真的感兴趣,而且需要“新版”的计算器,呵呵,老规矩,给我发邮件,我悄悄地告诉你。
另外还有一件值得高兴的事我要在这里说,我的大学英语四级(国家)考试居然过了!我还是上上次(非典刚过,9月份那次)考的试,都没指望了,也没查过分,而且上次(大概是1月份的吧)都没报名。前两天居然接到通知,60.5!哈哈哈Tracy
好了,这也不是什么光彩的事,不过觉得很有意思而已。我这种人四级居然能过,中国的教育……
现在就说说我这个虚拟的计算器的实现吧。程序方面没什么新鲜的,主要是一些想法和其中的数学原理。
首先,以前已经说过,这个计算器是基于堆栈的。不过,我没有在其中使用任何显式的堆栈数据结构,也没有特地为此建立函数库。原因很简单——效率。我在程序中声明了一个全局数组opStack,类型为operand_t,作为运算栈;以及一个全局变量opSP,类型为unsigned int,作为堆栈指针。堆栈指针的初值为零(因为使用了无符号整型),这可能与一些用数组实现堆栈的程序不太一样;这样,出栈操作类似于:
operand_t operand = opStack[--opSp];
而入栈操作类似于:
opStack[opSp++] = operand;
也就是说,我的堆栈指针并未指向栈顶元素,而是指向了栈顶元素上面的位置。不过,我在程序中并没有使用这样的操作,稍后将作说明。
由于使用了固定大小的运算栈,对堆栈的空满状态的检查就显得尤为重要。因为几乎所有的指令都要涉及到出入栈操作,因此,我为栈状态的检查编写了两个宏:
/* check the stack status(overflow): */
- define check_overflow() \
if(opSp >= MAX_STACK_SIZE - 1) { \
fprintf(stderr, "Operate stack overflow!\n"); \
exit(0); \
}
/* check the stack statuc(underflow)
- n means how many operands are required:
- /
- define check_underflow(n) \
if(opSp <= n - 1) { \
fprintf(stderr, "Operate stack underflow!\n"); \
exit(0); \
}
其中,check_overflow()用于检查运算栈是否上溢出,用于所有入栈操作之前;check_underflow()用于检查运算栈是否下溢出,用于所有出栈操作之前。由于所有的指令最多只会将一个操作数压入堆栈,check_overflow()宏是没有参数的,只要检查运算栈中是否有一个空位即可;但是,有的指令需要弹出一个操作数,有的需要两个,所以我为check_underflow()宏添加了一个参数,用来表示需要的检查的最小空间。下面的示意图显示了堆栈的结构和堆栈指针在不同情况下的位置,可以帮助你理解如果获取栈顶操作数(后面会遇到)以及上、下溢出检查的依据。
|
相关栏目: | |
|
相关搜索: |
| 关于“小计算器/译原理学习日记简单指令型计算器(2)虚拟机的实现”的留言: | |
|
目前暂无留言 | |
| 新增相关留言 | |
