自己动手制作C 语言编译器(2):虚拟机

本章我们要构建一台虚拟的电脑,设计我们自己的指令集,运行我们的指令集,说得通俗一点就是自己实现一套汇编语言。它们将作为我们的编译器最终输出的目标代码。

计算机的内部工作原理

我们关心计算机的三个基本部件:CPU、寄存器及内存。代码(汇编指令)以二进制的形式保存在内存中,CPU 从中一条条地加载指令执行。程序运行的状态保存在寄存器中。

内存

我们从内存开始说起。现代的操作系统都不直接使用内存,而是使用虚拟内存。虚拟内存可以理解为一种映射,在我们的程序眼中,我们可以使用全部的内存地址,而操作系统需要将它映射到实际的内存上。当然,这些并不重要,重要的是一般而言,进程的内存会被分成几个段:

1.代码段(text)用于存放代码(指令)。

2.数据段(data)用于存放初始化了的数据,如int i = 10;,就需要存放到数据段中。

3.未初始化数据段(bss)用于存放未初始化的数据,如int i[1000];,因为不关心其中的真正数值,所以单独存放可以节省空间,减少程序的体积。

4.栈(stack)用于处理函数调用相关的数据,如调用帧(calling frame)或是函数的局部变量等。

5.堆(heap)用于为程序动态分配内存。

它们在内存中的位置类似于下图:

推荐C语言编程学习交流群:941636044,大量学习资料免费下载!

但我们的虚拟机并不模拟完整的计算机,我们只关心三个内容:代码段、数据段以及栈。其中的数据段我们只存放字符串,因为我们的编译器并不支持初始化变量,因此我们也不需要未初始化数据段。理论上我们的虚拟器需要维护自己的堆用于内存分配,但实际实现上较为复杂且与编译无关,故我们引入一个指令MSET,使我们能直接使用编译器(解释器)中的内存。

综上,我们需要首先在全局添加如下代码:

int *text,            // text segment

     *old_text,        // for dump text segment

     *stack;           // stack

char *data;           // data segment

注意这里的类型,虽然是int型,但理解起来应该作为无符号的整型,因为我们会在代码段(text)中存放如指针/内存地址的数据,它们就是无符号的。其中数据段(data)由于只存放字符串,所以是char *型的

接着,在main函数中加入初始化代码,真正为其分配内存:

int main() {

    close(fd);

    ...

 

    // allocate memory for virtual machine

    if (!(text = old_text = malloc(poolsize))) {

        printf("could not malloc(%d) for text area\n", poolsize);

        return -1;

    }

    if (!(data = malloc(poolsize))) {

        printf("could not malloc(%d) for data area\n", poolsize);

        return -1;

    }

    if (!(stack = malloc(poolsize))) {

        printf("could not malloc(%d) for stack area\n", poolsize);

        return -1;

    }

 

    memset(text, 0, poolsize);

    memset(data, 0, poolsize);

    memset(stack, 0, poolsize);

 

    ...

    program();

寄存器

计算机中的寄存器用于存放计算机的运行状态,真正的计算机中有许多不同种类的寄存器,但我们的虚拟机中只使用 4 个寄存器,分别如下:

1.PC程序计数器,它存放的是一个内存地址,该地址中存放着下一条要执行的计算机指令。

2.SP指针寄存器,永远指向当前的栈顶。注意的是由于栈是位于高地址并向低地址增长的,所以入栈时SP的值减小。

3.BP基址指针。也是用于指向栈的某些位置,在调用函数时会使用到它。

4.AX通用寄存器,我们的虚拟机中,它用于存放一条指令执行后的结果。

要理解这些寄存器的作用,需要去理解程序运行中会有哪些状态。而这些寄存器只是用于保存这些状态的。

在全局中加入如下定义:

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值