zoukankan      html  css  js  c++  java
  • C语言这么厉害,它自身又是用什么语言写的?编写过程被称为自举!

    来自一个小白的提问:“C语言本身用什么语言写的?”

    换个角度来问,其实是:C语言在运行之前,得编译才行,那C语言的编译器从哪里来?用什么语言来写的?如果是用C语言本身来写的,到底是先有蛋还是先有鸡?

    1

    我们假设世界上不存在任何编译器, 先从机器语言说起,看看怎么办。

    机器语言可以直接被CPU执行,不需要编译器。

    然后是汇编语言, 汇编语言虽然只是机器语言的助记符,但是也需要编译成机器语言才能执行,没办法只能用机器语言来写这第一个编译器了(以后就不用了)。

    汇编语言的问题解决了,就往前迈进了一大步,这时候就可以用汇编语言去写C语言的编译器,我们说这是C编译器的老祖宗。

    有了这个老祖宗,就可以编译任意的C语言程序了,那是不是可以用C语言本身写一个编译器?只要用老祖宗编译一下就可以了。

    OK, 这么一层层上来,终于得到了一个用C语言写的编译器, 真是够麻烦的。

    到这个时候,之前那个汇编写的C语言编译器就可以抛弃了。

    当然,如果在C语言之前,已经出现了别的高级语言,例如Pascal,那就可以用Pascal来写一个C语言的编译器。

    第一个Pascal的编译器据说使用Fortran写的。而作为第一个高级语言的Fortran,它的编译器应该是汇编语言写的。

     

    2

    关于编译器,这里边有个有趣的传说:

    传说Unix 发明人之一的 Ken Thompson在贝尔实验室,大摇大摆的走到任何一台Unix机器前,输入自己的用户名和密码,就能以root的方式登录!

    贝尔实验室人才济济,另外一些大牛发誓要把这个漏洞找出来,他们通读了Unix的C源码,终于找到了登录的后门, 清理后门以后编译Unix , 运行, 可是Thompson 还是能够登录进去。

    有人觉得可能是编译器中有问题,在编译Unix的时候植入了后门, 于是他们又用C语言重新写了一个编译器,用新的编译器再次编译了Unix, 这下总算天下太平了吧。

    可是仍然不管用, Thompson 依然可以用root登录,真是让人崩溃!

    后来Thompson 本人解开了秘密,是第一个C 语言编译器有问题, 这个编译器在编译Unix源码的时候,当然会植入后门, 这还不够,更牛的是,如果你用C 语言写了一个新编译器,肯定也需要编译成二进制代码啊,用什么来编译,只有用Thompson写的那第一个编译器来编译,好了, 你写的这个编译器就会被污染了,你的编译器再去编译Unix , 也会植入后门 :-)

    说到这里我就想起了几年前的XcodeGhost 事件,简单来说就是在Xcode(非官方渠道下载的)中植入了木马,这样XCode编译出的ios app都被污染了,这些app就可以被黑客利用做非法之事。

    虽然这个XCodeGhost和Thompson的后面相比差得远,但是提醒我们,下载软件的时候要走正规渠道,从官方网站下载,认准网站的HTTPS标准,甚至可以验证一下checksum。

     

    3

    可能有人问:我用汇编写一段Hello World都很麻烦,居然有人可以用它写复杂的编译器?这可能吗?

    当然可能,在开发第一代Unix的时候,连C语言都没有, Ken Thompson 和 Dennis Ritchie 可是用汇编一行行把Unix敲出来的。 WPS第一版是求伯君用汇编写出来的, Turbo Pascal 的编译器也是Anders 用汇编写出来的,大神们的能力不是普通人能想象得到的。

    对于编译器来说,还可以采用“滚雪球”的方式来开发:

    还是以C语言为例,第一个版本可以先选择C语言的一个子集,例如只支持基本的数据类型,流程控制语句,函数调用...... 我们把这个子集称为C0。

    然后用汇编语言写个编译器,只搞定这个语言的子集C0,这样写起来就容易不少。

    C0这个语言可以工作了,然后我们扩展这个子集,例如添加struct,指针...... ,把新的语言称为C1。

    那C1这个语言的编译器由谁来写? 自然是C0。

    等到C1可以工作了,再次扩展语言特性,用C1写编译器,得到C2。

    然后是C3, C4...... 最后得到完整的C语言。

    这个过程被称为bootstraping , 中文叫做自举。

  • 相关阅读:
    Atitit. visual studio vs2003 vs2005 vs2008  VS2010 vs2012 vs2015新特性 新功能.doc
    Atitit. C#.net clr 2.0  4.0新特性
    Atitit. C#.net clr 2.0  4.0新特性
    Atitit.通过null 参数 反射  动态反推方法调用
    Atitit.通过null 参数 反射  动态反推方法调用
    Atitit..net clr il指令集 以及指令分类  与指令详细说明
    Atitit..net clr il指令集 以及指令分类  与指令详细说明
    Atitit.变量的定义 获取 储存 物理结构 基本类型简化 隐式转换 类型推导 与底层原理 attilaxDSL
    Atitit.变量的定义 获取 储存 物理结构 基本类型简化 隐式转换 类型推导 与底层原理 attilaxDSL
    Atitit.跨语言反射api 兼容性提升与增强 java c#。Net  php  js
  • 原文地址:https://www.cnblogs.com/jinwenyi/p/13847084.html
Copyright © 2011-2022 走看看