建设宣传网站的必要性,网上接做网站的单子,网站建设心得.doc,域名解析暂时失败再把上节代码贴出来#xff0c;
1 //int main(void) {
2 int _start(void) {
3 while(1);
4 return 0;
5 }有没有同学想过#xff0c;这里写一个_start函数#xff0c;让其调用main函数如何#xff1f;其实这是可以的#xff0c;main函数并不是第一个函数#xff0c;它实…再把上节代码贴出来
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语言生成的机器指令是一对多复杂间接略冗余。
好啦关于内核的部分咱们就此先打住其实说这话我有点不好意思您也看到啦内核代码中就一个死循环而已我们的内核还没有开始。咱们的内核虽然离真正的内核差得十万八千里但它目的是两个
是为了演示加载内核是为了演示elf格式的文件解析。
后面我们将结合此简单至极的c程序来学习有关elf方面的知识。