一段代码是如何变成可执行程序的?

论坛 期权论坛 期权     
匿名用户1024   2021-6-1 05:26   7654   5
分享到 :
0 人收藏

5 个回复

倒序浏览
2#
有关回应  16级独孤 | 2021-6-1 05:27:00
楼主这个问题要回答起来需要写一整本的书《编译原理》。

具体可以参考wiki  http://zh.wikipedia.org/wiki/Category:编译原理

如果楼主看了基本材料有具体问题可以再讨论,ps我一直觉得编译原理很重要,这个是真正将软件和硬件都连接起来的东西,如果楼主之前不了解建议好好学习一下
3#
有关回应  16级独孤 | 2021-6-1 05:27:01
这个问题涉及到的知识领域相当之广泛,我暂且说一点我的经验吧。
你说的代码和可执行程序并未指定时何种代码。高级语言还是汇编语言或者其他的,高级语言又有多种不同的类别,C/C++,Java,C#等。可执行程序对于不同的操作系统和CPU是不一样的。
此处假设以C/C++语言作为编写你所说的源代码的语言,可执行程序是Linux下X86(AMD64)机器的可执行程序。
由于软件的发展需要易于人类思维理解的高级语言,但是高级语言的很多语言结构特性与CPU指令之间存在着巨大的差距,这中间的差距需要通过编译器来逐渐得一步一步地特化(lowering)为具体的X86机器指令。
C语言的语言结构与目标机器之间的差距相对于其他高级语言来说,比较接近CPU的执行模型,所以大部分的语言结构可以转换为C语言来理解(实践中没有必要而且工作量太大),如:面向对象,多态,都可以使用C语言的特性来模拟。
[h1]一、C语言[/h1]而对于C语言来说,基本的语言结构就是函数定义,变量声明,类型声明,分支语句,循环语句,goto语句,以及多种运算符操作表达式。
  • 函数定义: 可以对应到汇编代码中的subroutine;
  • 变量声明: 可以对应到数据段的声明 x:  .data .global .long 32,这条汇编语句在数据段定义了一个类型为int,值为32的全局变量,一般使用C语言的static int x = 32;可以得到如上的结果。
  • 类型声明: 这一步只是源语言层面的信息,在机器码层面,只存在整数,浮点数。如下代码
  1. struct A{ int x1; int x2;};int main(){ struct A a; a.x1 = 0; a.x2 = 1; return 0;}// 上述代码在编译的时候,编译器会计算得到struct A的大小,以及每个成员相当于struct A起始// 地址的偏移.当分配变量的时候,也是使用push指令申请栈空间,与基本类型变量一样。访问// 结构体a中成员的时候,会进行地址计算// a.x1= 0 => movl 0, (x1.起始偏移0 + a的基地址)// a.x2 = 1 -> movl 2,(x1.起始偏移4 + a的基地址)
复制代码
  • 分支语句: 其实这条语句在机器码层次就是跳转语句(jne, je, jz等这些条件跳转和无条件跳转)
  • 循环语句:这条语句可以转换为分支语句加goto来实现。
  • goto语句:对应到机器码中的无条件跳转指令(jump **)。
  • 运算符表达式:这些都可以映射到机器码中的实现,一元,二元运算符都很直接能对应到CPU的操作,比较特殊的是&(取地址),*(解引用)两个操作,&操作可以使用LEA指令得到一个内存操作数的地址,*(解引用)操作符其实就是汇编语言级别的内存操作数间接寻址。
  1. // X86机器栈帧布局|-----------| x1 + self->x2;   // 此处的self等价于上上述代码的this指针.}int main(){   Test t;   add(&t);   return 0;}
复制代码
4#
有关回应  16级独孤 | 2021-6-1 05:27:02
这个问题,真的相当复杂,我很惊讶真的要问这么个问题,因为它太过于复杂,而且对于不同的“代码”,差别也是相当之大的。
----
总体上来说,
所谓的代码就是对过程/方法/描述的一种抽象,抽象为机器/环境/程序可以理解的东西.
所谓的执行呢,就是机器/环境/程序,按照如上抽象出来的东西,将它执行/呈现出来.
----
回到你的问题上来,估计你问题的是C代码是如何转化为可执行程序的.
这里C是一种代码表述方法,就像语文作文的作文格式类似的,只是这个格式要严格的多.可执行程序呢,就是一个执行过程,就像语文作文念一遍听一样.
C基本过程如下:预处理,编译,优化,链接过程.具体可以上网自己搜出来看.
预处理,就是简单的文本替换,比如鲁迅的通假字.
编译+优化,就是从C语言转化为汇编语言,从汇编语言到二进制机器码.
链接是执行的时候才有的过程,比如调用系统函数或者库,这个时候就会去调用它,就像作文里面引用典故一样,必须知道典故,才可以解释清楚意思.
----
为了不闭塞思维,你也可以看下其他的"代码","执行".例如网页的创作.
假设就最简单的html(这个你不知道,还是多看点书吧)
html描述了一个网页的样子,但是它不是把所有的要素都放在自己里面.例如CSS之类的定义了html页面的结构排版,
最后网页的显示,这个就相当于一个"代码执行"的过程,这个执行过程,得到了html,css,引用的图片及其他等等,最后就用js引擎,网页渲染,最后的到网页的样子.呈现给用户.
5#
有关回应  16级独孤 | 2021-6-1 05:27:03
谢邀。这问题太大了。
简单答一下,大概是需要这样一个过程:
  1. 程序代码->分词-> 解析->编译->CPU指令
复制代码
如果想详细了解,可以参考CSAPP(深入理解计算机系统)一书,或者参考我翻译的《Ruby原理剖析》,比CSAPP薄一点,以Ruby语言为例了解整个过程。
6#
有关回应  16级独孤 | 2021-6-1 05:27:04
关于这个问题,我之前也关注过,是为了明白程序的编译,链接和装载。
大佬们会给出高屋建瓴的描述的。我自己呢,说不清楚。就推荐最近看过的几本书。如果想详细知道这方面的内容,可以看看。
俞甲子的程序员的自我修养,milan stevanovic的advanced c and c++ compiling 和最近的一本,igor zhirkov的low level programming。
这三本都是讲程序链接和装载的细节的,书都各有优缺点,值得一看。因为市面上,讲这方面的书似乎并不多,我也只找到这几本。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:136515
帖子:27303
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP