上一篇文章,大概了解了链接器的工作内容就是:符号解析和重定位。点击上一篇文章查看:点击查看。

本片文章其实还是围绕链接器来学习。只不过不是很明显,当你学到下一篇文章时,就明白了。

本篇文章来弄明白一个问题:在C/C++程序被加载到内存中准备运行时,main函数是第一个被执行的函数么?答案肯定不是!如果是,就没必要去写这个文章了!!!

1、_start()函数

先说结果:_start() 是第一个被执行的函数,而不是main()函数。

我们的程序中并没有写_start() ,它是通过链接器链接到可执行文件中的(下一篇文章可以学习到这是如何办到的)。

在默认情况下(gcc)

  • 程序加载后,_start()是第一个被执行的函数
  • _start()函数,准备好参数后,立即调用 __libc_start_main() 函数
  • __libc_start_main() 初始化运行环境后,调用main()函数执行

注意:_start()函数的入口地址就是代码段(.text)的起始地址

2、__libc_start_main()函数的作用

__lib_start_main()函数的作用

  • 调用__libc_csu_init()函数(完成必要的初始化操作)
  • 启动程序的第一个线程(主线程),main()函数为主线程入口
  • 注册__libc_csu_fini()函数(程序运行终止时被调用)

3、程序的启动过程

下面给一个简图,来说明一个C/C++程序的执行过程:

4、自定义程序的入口函数

  • gcc 提供-e选项,用于在链接时指定入口函数
  • 自定义入口函数时,必须使用选项 -nostartfiles 进行链接

比如以下程序:

program.c

#include <stdio.h>
#include <stdlib.h>int program()
{printf("D.T.Software\n");exit(0);
}

很明显它没有main函数。但是我们通过以下编译命令进行编译:

  • gcc -e program -nostartfiles program.c -o program

生成可执行文件 program

运行该可执行文件: ./program

可以得到运行结果:

显而易见,我们改变了程序的入口函数。虽然没有写main函数,但是依然可以运行该程序!!!

5、总结

本文主要是理解程序的入口函数。最好自己私底下做实验,看一下可执行文件的反汇编代码,就知道整个程序的执行流程了。

本文参考狄泰软件学院相关课程
想学习的可以加狄泰软件学院群,
群聊号码:199546072

学习探讨加个人(可以免费帮忙下载CSDN资源):
qq:1126137994
微信:liu1126137994

【软件开发底层知识修炼】十 链接器-main函数不是第一个被执行的函数相关推荐

  1. 【软件开发底层知识修炼】二十三 ABI-应用程序二进制接口三之深入理解函数栈帧的形成与摧毁

    上两篇文章我们初步接触了ABI-应用程序二进制接口的概念,点击链接查看上一篇文章:[软件开发底层知识修炼]二十二 ABI-应用程序二进制接口 二.了解了为什么会有ABI的存在.本篇文章继续学习ABI ...

  2. 【软件开发底层知识修炼】二十六 ABI-应用程序二进制接口 学习总结文章目录

    前面学习了ABI的知识,感觉受益良多.对底层与编译器有更加深刻的认识,为此这里将前面写过的关于ABI 的文章给列出来,方便学习与翻阅. [软件开发底层知识修炼]二十一 ABI-应用程序二进制接口一 [ ...

  3. 【软件开发底层知识修炼】二十四 ABI之函数调用约定

    上一篇文章学习了Linux环境下的函数栈帧的形成与摧毁.点击链接查看相关文章:软件开发底层知识修炼]二十三 ABI-应用程序二进制接口三之深入理解函数栈帧的形成与摧毁 本篇文章继续学习ABI接口相关的 ...

  4. 【软件开发底层知识修炼】十三 链接器-如何写出不依赖C库函数的代码

    本文将综合以下4篇文章,学习如何写出不依赖libc库的程序: [软件开发底层知识修炼]九 链接器-可重定位文件与可执行文件 [软件开发底层知识修炼]十 链接器-main函数不是第一个被执行的函数 [软 ...

  5. 【软件开发底层知识修炼】二十五 ABI之函数调用约定二之函数返回值为结构体时的约定

    上一篇文章学习了几种函数调用约定的区别,点击链接查看上一篇文章:[软件开发底层知识修炼]二十四 ABI之函数调用约定 本篇文章继续学习函数调用约定中,关于函数返回值的问题.当函数返回值为结构体时,函数 ...

  6. 【软件开发底层知识修炼】二十 深入理解可执行程序的结构

    上一篇文章记录了GDB调试从入门到熟练掌握的学习全过程.点击链接查看:[软件开发底层知识修炼]十九 GDB调试从入门到熟练掌握超级详细实战教程学习目录 还记得在以前的学习Binutils工具的时候,学 ...

  7. 【软件开发底层知识修炼】十四 快速学习GDB调试一 入门使用

    前面几篇文章学习了链接器相关的内容.现在开始来学习GDB调试.我们的目的是通过这几篇文章将GDB调试完全学会. 文章目录 1 为什么需要GDB 2 GDB 的常规应用 3 GDB调试程序实例 4 总结 ...

  8. 【软件开发底层知识修炼】二十八 C/C++中volatile的作用

    上一篇文章学习了C/C++中的指针与数组的区别,点击链接进行查看:[软件开发底层知识修炼]二十七 C/C++中的指针与数组是不同的 本篇文章将学习volatile关键字在C/C++中的作用 文章目录 ...

  9. 【软件开发底层知识修炼】二十二 ABI-应用程序二进制接口 二

    上一篇文章学习了ABI的相关内容,具体最后分析了不同ABI下结构体的对齐方式的不同.点击链接查看上一篇文章:[软件开发底层知识修炼]二十一 ABI-应用程序二进制接口一 本篇文章继续学习ABI相关内容 ...

  10. 【软件开发底层知识修炼】十九 GDB调试从入门到熟练掌握超级详细实战教程学习目录

    本文记录之前写过的5篇关于GDB快速学习的文章,从第一篇开始学习到最后一篇,保证可以从入门GDB调试到熟练掌握GDB调试的技巧. 学习交流加 个人qq: 1126137994 个人微信: liu112 ...

最新文章

  1. TensorFlow入门教程
  2. javascript跨域实践
  3. elasticsearch-jdbc实现MySQL同步到ElasticSearch深入详解
  4. Unable to resolve dependency问题解决
  5. 思维 || Make It Equal
  6. Wpf之MVVM线程问题
  7. lora网关以太网传输
  8. 计算机的云是什么意思_阿里巴巴计算机云是什么意思
  9. php使用iframe框架,ThinkPHP后台首页使用iframe(框架)
  10. android获取手机短信记录,Android开发获取短信的内容并截取短信
  11. 计算机工程与应用期刊模板,计算机工程与应用 论文模板
  12. 面试阿里,总结vue实现打印功能的两种方法,成功拿下offer!
  13. 分析师:芯片短缺至少还将持续一年
  14. TestFlight APP测试(IOS如何让上架前给其他人测试)
  15. 模拟量输出模块支持西门子三菱PLC接DCS控制系统
  16. 调焦距离S远近与景深之关系
  17. arm对应hex_ASCII与HEX对照转换表
  18. Python 两个字典如何实现相加?(相同的键,值相加)
  19. python邮箱爆破_企业邮箱爆破脚本
  20. 单片机实验——改进型交通信号灯设计,交通信号系统是保障交通安全高效的重要设施,为了利于司机更好的判断,很多交通信号灯系统在原来的系统基础上设置了倒计时显示器。本实验利用7段数码管作倒计时显示器

热门文章

  1. java学习(15):巩固练习
  2. Python isnumeric()方法
  3. Problem Collection II 构造
  4. 一个jdbc connection连接对应一个事务
  5. 微信小程序 body属性的问题
  6. unicode 与 utf-8
  7. 编写一个函数func(),将此函数的输入参数(int型)逆序输出显示,如54321 – 12345,要求使用递归,并且函数体代码不超过8行...
  8. c++ primer 笔记 (三)
  9. 配置节处理程序时出错,未能加载文件或程序集
  10. c语言 字符串map,C语言实现BitMap