计算机是如何执⾏代码的?
我们写下的⼀⾏⾏代码,计算机到底是如何在执⾏的呢?我们以x86架构的CPU为例,简单介绍以下CPU的执⾏过程。
1、⾼级语⾔
为了⽅便编程,⽬前⼈类已经发明了六百多种编程语⾔,使得我们可以⽤⼈类最容易理解的语法规则去告诉计算机完成我们想要的功能。例如我们常⽤的C、C++、python、perl、ruby、go、java等。这些语⾔被称为⾼级语⾔,以我们⼈类的思维⽅式来进⾏编程。
⽐如,⼀个C语⾔程序员写下了⼀⾏代码:
int sum = a + b;
这⼀句很简单的C语句,计算机却不懂。
这时候就需要⼀个翻译,负责把⼈类编写的⾼级语⾔“翻译”成计算机能看得懂的东西,这个翻译就是编译器。
2、编译链接
上⾯的⾼级语⾔语句经过编译器编译链接后,⽣成了⼀个⽬标运⾏平台为x86架构的可执⾏程序exe/elf,使⽤反编译⼯具IDA进⾏分析,可以看到这⾏代码编译后的样⼦是这样的:
8B 45 EC mov eax, [ebp+a]
03 45 E0 add eax, [ebp+b]怎样写代码 自己做编程
89 45 F8 mov [rbp+sum], eax
下⾯对上⾯的进⾏解释:
mov eax a //将变量a的值存⼊eax寄存器中
add eax b //把变量b的值和eax寄存器的值相加,并将结果保存在eax寄存器中
mov sum eax //将计算结果从eax寄存器写⼊sum变量
3、机器指令
上⾯的汇编指令只是为了⼈类理解⽅便的助记符,计算机同样也不认识这玩意,那⼏条指令在内存中实际上是这样的⼀串数据:
⼗六进制:
8B 45 EC 03 45 E0 89 45 F8
⼗六进制是为了书写⽅便,计算机真正能看到的只有⼆进制的⽐特流
10001011 01000101 11101100 00000011 01000101 11100000 10001001 01000101 11111000
接下来,计算机要做的事情就是识别这些⼆进制流都是什么意思,转换成⼀条条的指令来执⾏。
在开始执⾏之前,先来了解⼀下指令格式。
4、指令格式
x86架构CPU指令集中的指令格式如下:
主要有六个部分:
[⾮必需] 指令前缀:我们经常⽤到的原⼦操作指令前⾯有⼀个lock前缀,就属于指令前缀。
[必需] 操作码:指令最核⼼的部分,标识这条指令是什么功能。
[⾮必需] ModR/M:内存/寄存器操作数字节
[⾮必需] SIB:索引寻址描述字节
[⾮必需] Displacement:常数偏移字节/半字/字
[⾮必需] Immediate:⽴即数字节/半字/字
需要注意的是,并不是每⼀条指令都包含上⾯的所有部分,许多指令只包含其中⼀部分字段。
根据操作码的长度不同,指令分为单字节操作码指令、双字节操作码指令、三字节操作码指令。
5、执⾏指令
计算机中真正负责指令执⾏的核⼼部件是中央处理器CPU,在CPU中有⼀个指令寄存器IP,全称是Instruction Pointer,在32位下,它叫EIP,在64位下它叫RIP。
下⾯开始执⾏:
指令寄存器EIP指向了第⼀条指令,开始读取第⼀个字节:10001011,也就是0x8B。
开始指令译码,翻译出这是⼀条什么指令。
下⾯是x86架构的CPU指令操作码表:
CPU中的指令译码模块发现单字节操作码的mov指令,要往eax寄存器⾥⾯塞数据,数据从哪来呢?
再往后⼀看,0x45,再来译码:
原来是根据ebp寄存器的值+⼀个8位的偏移来读取数据。
再往后读取⼀个字节,就是偏移值:EC。
现在第⼀条指令就译码出来了:将ebp+0xEC位置处的4个字节的数据取出来,放到eax寄存器中。,这就是这⼀条指令要⼲的事情。
同时CPU还得出了另⼀个信息:这⼀条指令长度是3个字节,下⼀条指令的起始地址是在3个字节之后,随后,指令寄存器EIP向后拨动,指向下⼀条指令的地址:$+3。
指令译码完成之后,开始来正式执⾏它。
执⾏完⼀条以后,⼜来到指令寄存器EIP指向的地⽅,随后再次指令译码、执⾏,不断重复这个过程,依次执⾏每⼀条指令。
这其实就是CPU⼯作最基本的原理。
扩展
上⾯描述的过程是CPU在硬件电路层⾯完成的,但这种设计思想在软件领域也同样适⽤。
⼤家如果去研究Java虚拟机JVM和Python的解释器源代码时,也会发现有相似之处:JVM和解释器通过定义⼀套⾃⼰的“指令集”,然后它们的编译器使⽤这套指令集将Java和Python代码编译成对应的程序。
运⾏的时候也类似,虚拟机或者解释器不断识别每⼀条指令,译码、执⾏,和CPU执⾏指令的过程颇有⼏分相似。
C/C++语⾔编译的程序,最后是直接编译成了CPU的指令,所以跨平台能⼒差,如果换到ARM架构平台,原来的程序将⽆法执⾏,需要重新编译成新的平台的程序。
⽽Java、Python这类语⾔,是⾃⼰在软件层⾯的指令集,因为其⾃⾝已经开发了针对不同CPU平台的虚拟机、解释器,所以这些语⾔编写的程序移植性好,真正做到⼀次编写,到处运⾏。
总结
我们使⽤⾼级语⾔C、C++编写的程序代码,经过编译器的编译链接,最终变成CPU可以理解的机器指令,随后CPU在执⾏时通过不断的译码、执⾏,最终实现⾼级语⾔所描述的功能。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论