查看原文
其他

Python 是用 C 语言实现的,那 C 是用什么语言实现的?

Python猫 2021-03-15

The following article is from 码农翻身 Author 码农翻身刘欣

 👆 Python猫” ,一个值得加星标的公众号
花下猫语:今天的头条是篇广告推广,望大家体谅理解、按需体验。

次条分享一篇文章,作者是刘欣,畅销书《码农翻身》作者,前 IBM 架构师,擅长用故事去讲解复杂技术。我在刘老师的星球潜水很久了,里面有很多技术干货,前不久我翻译《Python 为什么要保留显式的 self ?》,就是受到他的一篇帖子启发。一起来阅读吧。

剧照 | 《仙剑奇侠传》

这是来自我的星球的一个提问:“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 , 中文叫做自举。


END


最后,猫哥友情推荐码农翻身知识星球,里面有来自腾讯、阿里、京东、滴滴、IBM、SAP等各路大牛,可以深度交流技术学习、项目开发、编程技术、职业发展......

优质文章,推荐阅读:

Python 命令行之旅:使用 argparse 实现 git 命令

Python 设计和历史的 27 个问题

聊聊 Python 的单元测试框架(三):pytest

Top编程语言的15年沉浮:C#默Java泪,Python终上位!

感谢创作者的好文

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存