Compiler Construction using Flex and Bison(译6--虚拟机)

虚拟机

由真实物理设备构造的计算机,用术语来说就是一台真实计算机或硬件计算机.从程序设计的观点来看,它是由机器定义的设备指令集.一个操作系统构建在机器的顶层,用于管理访问机器和提供一些附加服务.这些由操作系统提供的服务构成了另一台机器,即虚拟机.
一种程序设计语言提供了一组运算集合.这样,例如,它可能会被称作一台Pascal计算机或是一台Scheme计算机.对于程序员来说,程序设计语言是一台计算机;程序设计语言定义了一台虚拟机.Simple的虚拟机包含一个把变量和值关联起来的数据区域,和用于操作这个数据区域的程序.
在程序员认为的程序和由操作系统提供的虚拟机之前还有另一种虚拟机.它包含了必要的数据结构和算法去支持程序的执行.这样的虚拟机是一种语言的实时系统.它的复杂性规模大小从没有一点实质,如FORTRAN语言,延伸到为了支持极其高级系统内存管理和内部进程通信的并发程序设计语言,如SR.作为Simple的实时系统包含执行代码的处理单元能力和一个数据区域,在这个数据区域中,赋给变量的值通过数据区域的偏址来获得.
用户程序构成另一个虚拟机类.

一个堆栈机

堆栈机(S-machine)1是一个为了简化块结构语言实现而组织的一个堆栈机器.通过一个栈的活化记录,它可提供动态存储分配.这个活化记录被链接,以提供静态作用域支持和包含支持过程的上下文信息

机器的组织:堆栈机包含两个存储器,一个程序存储器--C(组织成一个只读的数组).和一个数据存储器--S(组织成一个栈).这里有四个寄存器,一个指令寄存器IR(包含正在被解释的指令),一个栈顶寄存器T(包含栈顶元素的地址),一个程序地址寄存器PC(包含下一个将要取指解释),和一个当前活化记录寄存器AR(包含正在被解释的过程活化记录基地址).每一个C中的存储单元可以存储一条指令.而每个S存储单元可以存储一个地址或一个整数.每个指令包含三个域,一个操作码和两个操作数.

指令集:S-code是堆栈机的机器语言.每条S-code占四个字节.第一个字节是操作码.这里有9条基本S-code指令,每条指令有为不同的操作码.S-code指令的第二个字节包含0或一个常量,或一个条件转移指令的条件码.最后两个字节可作为一个十六位的整型操作数,例如代表一个常量值,或是一个变量在栈中的偏移地址,或一条S-code指令地址,或是一个操作数,或是一个特定的函数号,这取决于指令的操作码.
每条指令的操作用英语和数学形式化的混合来描述.数学形式化用于标记发生在寄存器和堆栈机的栈中的值的变化.数据访问和存储指令要求一个在活化记录中的偏移地址,和一个不同于引用层和定义层的层.过程调用要求一个代码地址和一个不同于引用层和定义层的层.
------------------------------------------------------------------------------------------------------------------
1:这是改编自:Nikaus Wirth,Algorithms + Data Structures =Programs Prentice-Hall,Englewood Cliffs,N.J.,1976

Instruction(指令)  Operands(操作数)  Comments(注释)

READ   0,N  输入整数到N:S(N):=INPUT
WRITE     输出栈顶元素:Output :=S(T);T:=T-1 
OPR     算术与逻辑操作
0,0  过程和函数,返回操作T:=AR-1;AR:=S(T+2);P:=S(T+3)
ADD     ADD:S(T-1):=S(T-1)+S(T);T:=T-1
SUB      SUBTRACT:S(T-1):=S(T-1)-S(T);T:=T-1
    MULT     MULTIPLY:S(T-1):=S(T-1)*S(T);T:=T-1
    DIV      DIVIDE:S(T-1):=S(T-1)/S(T);T:=T-1
MOD     MOD:S(T-1):=S(T-1) mod S(T);T:=T-1
EQ      测试是否相等:S(T-1):=if S(T-1)=S(T) then 1 else 0;T:=T-1
LT      测试是否是于:S(T-1):=if S(T-1)<S(T) then 1 else 0;T:=T-1
GT      测试是否大于:S(T-1):=if S(T-1)>S(T) then 1 else 0;T:=T-1
LD_INT    0,N  把一个常量值装入栈中:T:=T+1;S(T):=N
LD_VAR    L,N  把一个在层中偏移L,在栈中基地址为N`的变量值送入        栈,T:=T+1;S(T):=S(f(L,AR)+N)+3
STORE       L,N     把栈中的值存储在层偏移为L,栈基地址为N                                  的变量中S(f(ld,AR)+os+3):=S(T);T:=T-1
CAL    L,N  调用S-code地址在N中,声明在层编移为L的 过程或函数
CAL       255,0    调用在内存中的过程地址:POP 地址,PUSH返回地         址.JUMP 地址
DATA       0,NN 栈指针加上NN: T:=T+NN
GOTO    0,N     JUMP: P:=N
JMP_FALSE   C,N     JUMP:if S(T) = C then P:=N;T:=T-1

在不同于当前过程和调用过程的静态层,被称作ld.os是在活化记录中的偏移,ld是不同于当前的活化记录的静态层,而其值在活化记录中保存,
f(ld,a) = if i=0 then a else f(i-1,S(a))
运算:栈机的寄存器和栈按如下初始化:

P=0.  {程序计数器}
AR=0; {活化记录}
T=2;  {栈顶}
s[0] :=0; {静态链}
s[1] :=0; {静态动态链}
s[2] :=0; {返回地址}

机器重复地取出以寄存器P为地址,并以寄存器P为增量的指令,并一直执行指令直到寄存器P包含一个0

 

execution-loop : I:= C(P);
 P := P+1;
 imterpret(I);
if { P<=0 -> halt
   & p>0 ->execution - loop }

堆栈机的模块

实现堆栈机是很直接的.
指令集和一条指令的结构被定义如下:
/*OPERATIONS : Internal Representation */
enum code_ops {  HALT , STORE , JMP_FALSE , GOTO,
         DATA, LD_INT,LD_VAR,
        READ_INT, WRITE_INT ,
LT, EQ, GT, ADD, SUB, MULT,DIV, PWR };

/*OPERATIONS: External Representation */

char *op_name[] = { "halt", "store", "jmp_false", "goto",
"data", "ld_int", "ld_var",
"in_int", "out_int",
"lt", "eq", "gt", "add", "sub", "mult", "div", "pwr" };

struct instruction
{
enum code_ops op;
int arg;
};

内存被分为两个段,一个代码段和一个运行时数据和表达式栈:
struct instruction code[999];
int stack[999];

寄存器组的定义,如程序计数器pc,指令计数器ir,活化记录ar(指向当前活化记录的最开始处),和指向栈顶的指针是很直观的:

int    pc =0;
struct  instructions ir;
int   ar =0;
int   top=0;

取指-执行周期重复地运行直到遇到一条halt指令.


void fetch_execute_cycle()
{ do { /* Fetch   */
ir = code[pc++];
/*Execute   */
switch (ir.op) {
case  HALT  : printf( "halt/n" );   break;
case  READ_INT : printf( "Input: ");
 scanf( "%1d", &stack[ar+ir.arg] ); break;
case  WRIRE_INT: printf( "Output : %d/n",stack[top--] ); break;
case  STORE  : stack[ir.arg] = stack[top--];  break;
case  JMP_FALSE: if ( stack[top--] == 0 )
pc = ir.arg;
break;
case  GOTO     : pc = ir.arg;    break;
case   DATA  : top = top + ir.arg;   break;
case   LD_INT : stack[++top] = ir.arg;  break;
case  LD_VAR : stack[++top] = stack[ar+ir.arg]; break;
case  LT   : if ( stack[top-1] < stack[top] );
stack[--top] = 1;
else stack[--top] = 0;
case  ADD : stack[top-1] = stack [top-1] + stack[top];
 top--;
 break;
case  SUB : stack[top-1] = stack [top-1] - stack[top];
 top--;
     break;
case  MULT : stack[top-1] = stack [top-1] * stack[top];
 top--;
     break;
case  DIV : stack[top-1] = stack [top-1] / stack[top];
 top--;
     break;
 /*译注:这里有问题和MULT一样*/
case  PWR : stack[top-1] = stack [top-1] * stack[top];
 top--;
     break;0
default  : printf( "%sInteral Error : Memory Dump/n");
 break;
}
      }
     while (ir.op != HALT);
}

weixin295微信小程序选课系统+ssm后端毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值