Hello World历程

    Hello World,很简单的一句话,很多程序员入门新语言的第一行代码,能输出这句话在屏幕,说明整个开发环境都已经搭建好了,可以进一步开发了,如果连这句话都无法输出,后面做再多算法设计也没用,因为,你的软件无法在客户机使用,那么,计算机在输出Hello World的背后做了什么呢,下面记录一下。

    且看最简单的C++代码:

    

    在Linux下使用G++编译器编译运用如下:

    

    在生成可执行文件a.out背后,经历了如下几个过程:

    预处理(PrePressing) -> 编译(Compilation) -> 汇编(Assembly) -> 链接(Linking)

    A. 预处理

    主要处理源码文件中以"#"符号开头的预编译指令,如“#include”、"#define"等。预处理过程中,大致做了如下几件事情:

    1. 展开宏定义

    2. 处理条件预编译指令,如"#if"

    3. 处理文件包含预编译指令

    4. 删除所有注释

    5. 添加行号和文件名标识,便于编译时编译器产生调试需要用到的符号信息

    6. 保留#pragma编译指令,该指令主要编译器会用到

    预编译如下:

    

    -E参数是进行预编译,生成的文件的扩展名为*.i 。调试时,如果觉得宏定义或文件保护不对,可以看看这么预编译文件是否正确。

    B. 编译

    在预处理的基础上,对预处理生成的文件进行词法分析、语法及语义分析及优化,产生汇编代码文件。如下:

    

    -S参数是进行编译

    C. 汇编

    对编译生成的汇编代码文件进行翻译生成机器码文件。如下:

    

    -c参数是进行汇编也可以一步到位:g++ -c main.cpp -o main.o

    可以用命令"objdump -s -d main.o"来看它的格式,如下(objdump属于binutils工具集的其中一个工具):

    

    可以看到,目标文件按段来存储的,如一般编译后的执行语存放在.text段,已初始化的全局变量和局部静态变量存放在.data段,未初始化的全局变量和局部静态变量存放在.bss段(用于定义符号并且为符号预留给定数量的未初始化空间)。上面输出信息比较详细,如果需要总览每个段的信息,使用"-h"参数即可:

    

    这里可以看到目标文件格式通用的格式,包含拥有的数据段及其权限、作用(.note.GNU-stack为堆栈提示段, CONTENTS:表示该段在文件中存在)。

    D. 链接

    前面只是针对一个文件生成目标机器码文件,要运行起来,还需要很多其他依赖的目标文件,类似与操作系统启动,操作系统是安装在硬盘的,直接启动是不行的,需要配合硬盘BIOS的那512字节,逐段加载到内存,经历一系列初始化,最终进入保护模式等,同样,要启动应用软件a.out,也是需要很多依赖,拼装成一个可执行软件,才可以运行。   

    链接过程主要有包括了地址和控件分配、符号决议和重定位等。        

    g++ main.o -o  main

    可以用ldd命令看其具体的依赖库:

    


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值