再把上节代码贴出来,

1 //int main(void) {
2 int _start(void) {
3 while(1);
4 return 0;
5 }

有没有同学想过,这里写一个_start函数,让其调用main函数如何?其实这是可以的,main函数并不是第一个函数,它实际上也是被别人调用的,不过这是编译器背后的策略啦,好奇心大的同学自己尝试下吧。

虽然把函数名改成_start可以解决问题,但我们习惯于main函数做为主函数,不习惯函数用_start,于是用了-e来指定起始的函数名为main,所以代码才链接正常。

也许有同学想过,哎?我平时写的程序也没有_start啊,直接用gcc编译后就能运行,没出过问题啊。是啊,确实如您所说,由于我也没深入研究过,但咱们通过比较的方式,让您自己悟出这里面的秘密。还是用上述代码为例,gcc –o /tmp/test.bin kernel/main.c编译链接,由于未加-c参数,生成的test.bin不再是目标文件而是可执行文件。然后再用先编译成目标文件再链接成可执行文件的方式,对比这两个文件的区别。见图

您看,test.bin是gcc直接生成的可执行文件,它的大小是4586字节。而kernel.bin是经过手动编译、链接这两个步骤完成的,其文件大小是1777字节。这两个文件的体积可是差了几乎2倍呢。再看看这两个文件中的符号信息,还是用nm命令,如图

test.bin中共有34个符号(wc –l命令是用来统计输出的行数,一个符号占用一行,故34个符号),由于输出太长了,我们只截取了关键的部分,不过您看那些frame_dummy、data_start等,这并不是咱们代码中存在的符号,这说明在编译器在编译过程中为咱们引用了别的代码,这就是c运行库的功劳,目的是在调用main函数前做初始化环境等工作。您看,用白色方框圈出来的_start,这就是默认的入口符号,链接器还是用到了它,它不是咱们提供的代码,依然是运行库提供的,这也说明main函数不是第一个执行的代码,它一定是被其它代码调用的,main函数在运行库代码初始化完环境后才被调用。

咱们继续看kernel.bin中的符号,一共就4行,尽管其中也包含了咱们不认识的符号,但毕竟少得多,我们的程序更短小精干,而且确实没有_start函数。这里添加了3个类型为A的符号,这表示它们的值是不变的。T表示是该符号是位于代码段中,更多符号的意义请参考man nm。

其实上述代码中要是换成汇编代码的话,就是个jmp $,其大小不过是2字节的机器码ebfe。除了编译器自动添加的代码外,一般情况下c语言编译出来的程序也比汇编语言生成的程序体积大。可见,人们常说的汇编语言比c语言快,并不是汇编语言本身有多快(它也要变成机器指令后才能上cpu运行),而是汇编语言对应的机器指令是一对一,简单直接可依赖,而c语言生成的机器指令是一对多,复杂间接略冗余。

好啦,关于内核的部分咱们就此先打住,其实说这话我有点不好意思,您也看到啦,内核代码中就一个死循环而已,我们的内核还没有开始。咱们的内核虽然离真正的内核差得十万八千里,但它目的是两个:

  1. 是为了演示加载内核,
  2. 是为了演示elf格式的文件解析。

后面我们将结合此简单至极的c程序来学习有关elf方面的知识。

一步步编写操作系统 46 用c语言编写内核3相关推荐

  1. 一步步编写操作系统 42 用c语言编写内核

    在这之前,我们一直用汇编语言直接与机器对话,如果大家不知道这个世界上有高级语言的话,我想大家也不会觉得写汇编代码的过程很辛苦,哈哈,幸福确实是比较出来的.相对于汇编语言,用c 语言写内核是非常爽的事, ...

  2. 一步步编写操作系统 45 用c语言编写内核2

    在linux下用于链接的程序是ld,链接有一个好处,可以指定最终生成的可执行文件的起始虚拟地址.它是用-Ttext参数来指定的,所以咱们可以执行以下命令完成链接: ld kernel/main.o - ...

  3. 一步步编写操作系统 44 用c语言编写内核1

    先来个简单的,欢迎我们神秘嘉宾--main.c.这是我们第一个c语言代码. 1 int main(void) { 2 while(1); 3 return 0; 4 } 它没法再简单啦,简单的程序似乎 ...

  4. 世界上最著名的操作系统是用什么语言编写的?

    Unix 与 C 语言的关系 在服务器领域,最著名的系统莫过于Unix了,即便Linux也是类Unix的操作系统.Unix 是用 C 语言编写的,而且是世界上第一个用 C 语言编写的操作系统.但是 U ...

  5. magenta内核与linux,谷歌将推出新操作系统Fuchsia:Magenta语言为内核

    谷歌现在研发出来并且推出使用的系统有Chrome OS.Android和Chromecasts,这三者在操作系统的市场中占得份额很高,但是好像谷歌对此并不满意,因为有相关消息显示,谷歌正在研发新的操作 ...

  6. c语言编写的商品管理程序,C语言编写的商品管理系统

    C语言编写的商品管理系统 商品的增删改查 #include #include #include #define K 5 int m=2; //商品种数 /*定义商品结构体*/ struct goods ...

  7. C语言编写Python包,使用C语言编写Python扩展1——Hello World

    能够使用C语言编写扩展是Python一大卖点吧,这可以将一些关键的代码使用C来写以提升程序的性能.本文是参考了Python的官方文档整理而来的,同时结合了Python2跟Python3.按照惯例现在先 ...

  8. C语言编写一下棋程序,C语言编写的与电脑下棋程序代码

    C语言编写的与电脑下棋程序代码 C语言编写的与电脑下棋程序代码 #include "stdafx.h" #include using namespace std; void che ...

  9. matlab编写正整数阶乘函数,用matlab语言编写程序:编写一个计算阶乘的函数,再编写一个脚本文件,通过键盘输入计算阶乘的n值....

    点击查看用matlab语言编写程序:编写一个计算阶乘的函数,再编写一个脚本文件,通过键盘输入计算阶乘的n值.具体信息 答:编写一个matlab文件,求1到n的阶乘之和.其代码编写的目的,就是学会自定义 ...

最新文章

  1. 安全性测试之认证授权
  2. python 访问网页 重定向_Python数据网络采集5--处理Javascript和重定向
  3. 在 ASP.NET 上实现锁定表头、支持滚动的表格的做法
  4. unity 平移图片_Unity 两张背景的切换平移
  5. DGL教程【五】使用自己的数据集
  6. android view父级隐藏,Android指定的子级已经有父级。必须先对子级的父级调用removeView()...
  7. Linux下安装、查看、删除软件包
  8. Django从理论到实战(part1)--虚拟环境
  9. 二维数组作为函数参数
  10. windows 如何在Windows命令行下配置IP地址
  11. html5 5s自动返回键,关于HTML5页面与手机虚拟键盘的回车的处理
  12. linux eth em,em改eth导致网卡无法启动
  13. hdu2844 amp; poj1742 Coin ---多重背包--两种方法
  14. RabbitMQ入门:发布/订阅(Publish/Subscribe)
  15. nodejs实现定时任务
  16. NRF51822 回顾总结
  17. 接口(一)什么是接口
  18. 软件公司/个人道德标准
  19. Spring事务For循环中的代码单独为一个事务,循环一次提交一次事务
  20. 五分钟用 linux搭建我的世界服务器

热门文章

  1. css3 - target
  2. 自动生成业务单据流水号方案
  3. 求一个整数数组的最大元素,递归方法实现
  4. EasyDarwin开源手机直播方案:EasyPusher手机直播推送,EasyDarwin流媒体服务器,EasyPlayer手机播放器...
  5. [Leedcode][JAVA][第152题][乘积最大子数组][动态规划]
  6. [Leedcode][JAVA][第94/144/145题][前中后序遍历][递归][迭代][二叉树]
  7. 【匈牙利算法】【二分图匹配】【转载】趣写算法系列之--匈牙利算法
  8. python 在gui中显示logging_如何在GUI中显示print()的输出python
  9. php代码expl,php – 参数号无效:参数未定义Explination
  10. 弹出并点击弹框关闭 自定义toast_关于别名配置使用弹框交互应用的思考