编译--链接--被执行

一串代码从写入编译器到最后被执行,到底中途经历了什么?

c语言中有一个经典的例子helloworld,这是每一个程序员踏入编程之路的第一步,哈哈,一入佛门深似海,从此节操是路人。

刚开始我们很懵,不知道什么,也不敢多问,可是学习了很久之后,你发现你的问题变得多了,为什么就会被编译器给打印出来hello world?为什么必须这样子写才能被执行出来hello world?怎么存放,怎么执行?等等,你就是一个十万个为什么了。

#include<stdio.h>
int main()
{
    printf("hello world\n");
    return 0;
}

好简单的代码,相信你是闭着眼睛都能写出来的。这不是重点,重点是怎么运行出来的,解决你的为什么。

这个代码被写出来,然后被gcc -o hello hello.c 就可以执行了,哇!真的执行出来了helloworld。刚开始你也会觉得很神奇,但是见多了就觉得没那么新奇了。

其实看着很简单的代码,可是对于编译器来说它是怎么处理的呢?

事实上,上述的过程被分解成了4个部分,分别是预处理、编译、汇编和链接。
那就一步一步来,反正一口也是吃不了一个胖子的。

预处理:

刚开始#include是被当成了一种惯性来写出来的。它是什么,为什么用?预处理可是专门为它量身打造。
预处理阶段stdio.h被预编译成一个.i的文件,对于c++程序来说,源代码是.cpp结尾,头文件是.hpp结尾的,那么被预编译以后成了.ii。

linux经常使用的命令是:gcc -E hello -o hello.i

预编译主要的工作(处理以#开头的预编译指令):
1.展开所有#define定义的宏;
2.处理所有的条件预编译指令,如:”if“,”ifdef”,”elif”,”else”,”endif”.
3.#include包含的文件按插入到文件指定的位置。
4.删除注释
5.添加行号
6.保留#pragme的预编译指令。

编译:

编译就是就接着预处理的文件,进行词法分析、语法分析、语义分析、优化代码、检查错误、汇总所有的符号。
linux的指令 :gcc -S hello.i -o hello.s

汇编:

根据编译完之后的.s文件,将.s文件转变成汇编指令。

linux指令:gcc -c hello.c -o hello.o
经过汇编后变成了.o文件。

大致画图说明一下,前面发生的事情。

那么这个二进制可重定向的二进制文件,是什么样子感觉很神奇呀!没事神秘还是要有的,一会在说。

链接:

链接可是一个桥梁,一个很重要的角色。
他主要负责:
1.合并个段
2.给符号分配地址(重定向)
3.符号解析

从此之后hello变成了可执行文件。

刚才前面不是留下了一个疑问,现在来看一下,目标文件经过一个链接之后,变成了一个可执行文件,他们两个有什么不一样吗?(不就是有了地址有什么了不起的)。

二进制可重定向目标文件

这里写图片描述

目标文件:
红色部分是和二进制可重定向目标文件的区别:

这里写图片描述

回归到原来的主干道上吧!不要迷路了!

将目标问价加载到虚拟地址空间之后,将main函数的入口地址写入pc寄存器。

还没有执行,目标文件被加载都了自己的虚拟地址空间。但是操作系统不认识这个虚拟地址呀!

我们得大费周章的加载到物理内存,让操作系统认识它。怎么加载呢,大致是这样子的。
这里写图片描述
这下子操作系统才认识,hello才会被执行,现在看来,是不是一个helloworld要被执行,也是很费劲的,没你想得那么简单。
所以好好爱惜你的操作系统吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值