一些语言的运行逻辑整理
这是个人对一些语言内部大体运行逻辑的整理,包括 C++,Java,Python 和汇编。很多来自于网络,不保证完全正确,有错请指出。
C++ 的具体细节见这篇文章:深入理解 C++ 编译过程:从源码到可执行程序的完整工具链 - 知乎。而这里要写一下,理解的东西,不同的架构有不同的指令集,这个指令集里面的指令,就是我们常说的机器码,或者机器语言,它们是一段二进制代码,用于控制 cpu 操作。而汇编是用来方便书写机器码的工具,汇编本身指的是一类语言,而汇编器就是用来写汇编代码并把汇编代码转化成机器码的实际工具,这个转化过程也称为汇编,就像 C++ 编译器一样,汇编器有很多,它们的语法各不相同,但是最后生成的机器码一定都是规定在指令集内的。这就是汇编。
汇编的不同在于系统、架构、语法的不同:
- 系统的影响在于,部分汇编需要调用系统的接口,而不同系统的接口一般不一样,这就造成了不同。
- 不同架构的指令集不同,自然汇编不同。
- 汇编书写有两种主流语法:Intel 和 AT&T。语法不同造成了汇编不同
就是这些东西影响了同一段汇编代码在不同平台的移植。那么理论上如果一段汇编代码,不涉及系统接口,在不同系统上采用的汇编器语法一致,还是同一架构的,那么就可以直接运行。
然而不同系统对于运行程序还有格式要求,因此汇编出的二进制代码不会完全一致(汇编可以运行,但是结果不同),最后得到的可执行程序就不同。因此,此时可移植的是仅仅是汇编。
那么对于这段汇编生成的纯二进制代码,是否可以移植呢?首先注意这里的是纯二进制代码,在不同系统下汇编出的代码,是带有系统特色的,因为需要处理后续链接所以添加了很多代码,总的来说是不纯的。对于纯二进制代码,理论上,只要能扔进内存里面里面运行,就可以跑。但是因为系统保护,尝尝无法直接扔进去代码(二进制代码,或者叫机器码)。
对于裸机可以通过烧录直接运行机器码(下面称二进制代码),而对于 linux 和 win 这种系统,为了方便管理,是有一层保护的,没法运行纯二进制代码,(如果你能绕过保护的话,就可以运行)。
C++ 本质上是依赖了汇编,因为汇编器在不同平台都有,因此只要 C++ 代码不涉及系统调用,就可以直接移植(这里说的有点过,但是运行是可以运行的,至于不同系统下的一些特色,如 rand 范围等,不在这句话考虑内),否则就需要改代码。这也使得 C++ 代码具有移植性,但是不算特别好。
而 python 的原理是,先判断语法是否正确,然后编译生成字节码,然后通过解释器逐行执行字节码,这个解释过程就是把字节码转化成机器码进行执行。因为这个解释器(不同系统,不同架构有不同的解释器)的存在,所以只要 python 不涉及到系统命令的调用,就可以完美移植。但是 python 和 C++ 不一样,C++很难不使用系统的命令,而 python 很多都可以通过解释器各种库避免直接调用系统 api,而且 python 的编译仅仅是简单得把代码转化为字节码,这个字节码是可以跨平台的,而 C++ 编译需要经历预处理、编译、汇编、链接等多个过程,并且这几个过程(除了预处理)都不是简单的处理,在编译上速度差的还是很大的。并且 C++ 生成的程序和系统绑死,也不利于了移植性。因此 python 的移植性是优于 C++ 的,但相对的 C++ 的效率要比 python 好很多(毕竟底层是汇编)。
而 java 和 python 很像,它是先使用 javac 编译成字节码,再通过 JVM (Java Virtual Machine,java虚拟机)解释字节码为机械码进行执行,特别的是,现在的 JVM 含有 JIT(Just-In-Time Compilation,即时编译) 这个东西,它会把多次使用代码块或者方法编译为机器码缓存起来,在之后再次读到此代码块或方法时直接运行机器码,从而加速运行。从这点上看,java 比 python 更适合长期运行的项目使用。
参考文章:

浙公网安备 33010602011771号