码迷,mamicode.com
首页 > 其他好文 > 详细

汇编和C的关系

时间:2018-05-18 20:13:15      阅读:149      评论:0      收藏:0      [点我收藏+]

标签:xor   链接器   ble   没有   return   iter   一个   strong   tor   

汇编程序的入口是_start,而C程序的入口是main函数。

文件:main.c
int bar(int c, int d)
{
    int e = c + d;
    return e;
}

int foo(int a, int b)
{
    return bar(a, b);
}

int main(void)
{
    foo(2, 3);
    return 0;
}

有文件main.c,编译生成可执行文件有下面2种方式:

方式一:
$ gcc main.c -S main.s
$ as main.s -o main.o
$ ld main.o -o main
方式二:
$ gcc main.c -S main.s
$ as main.s -o main.o
$ gcc main.o -o main
mian.o: In function `_start:
(.text+0x0): multiple definition of `_start/usr/lib/gcc/i486-linux-gnu/4.3.2/../../../../lib/crt1.o:(.text+0x0): first defined here
/usr/lib/gcc/i486-linux-gnu/4.3.2/../../../../lib/crt1.o: In function `_start:
(.text+0x18): undefined reference to `maincollect2: ld returned 1 exit status

对于第二种错误的做法分析如下:

如果我们用gcc做链接,gcc其实是调用ld做链接的gcc main.o -o main相当于这样的命令:

$ ld /usr/lib/crt1.o /usr/lib/crti.o main.o -o main -lc -dynamic-linker /lib/ld-linux.so.2

除了crt1.o之外其实还有crti.o,这两个目标文件和我们的main.o链接在一起生成可执行文件main-lc表示需要链接libc库,lc选项是gcc默认的,不用写,而对于ld则不是默认选项,所以要写上。-dynamic-linker /lib/ld-linux.so.2指定动态链接器是/lib/ld-linux.so.2

那么crt1.ocrti.o里面都有什么呢?我们可以用readelf命令查看。在这里我们只关心符号表,如果只看符号表,可以用readelf命令的-s选项,也可以用nm命令。

$ nm /usr/lib/crt1.o 
00000000 R _IO_stdin_used
00000000 D __data_start
         U __libc_csu_fini
         U __libc_csu_init
         U __libc_start_main
00000000 R _fp_hw
00000000 T _start
00000000 W data_start
         U main
$ nm /usr/lib/crti.o
         U _GLOBAL_OFFSET_TABLE_
         w __gmon_start__
00000000 T _fini
00000000 T _init

U表示Undefined

T表示Text,类型是代码

技术分享图片

整个程序的入口点是crt1.o中提供的_start,它首先做一些初始化工作(以下称为启动例程,Startup Routin),然后调用C代码中提供的main函数。

crt1.o中的未定义符号mainmain.o中定义。crt1.o还有一个未定义符号__libc_start_main在其它几个目标文件中也没有定义,所以在可执行文件main中仍然是个未定义符号。这个符号是在libc中定义的,libc并不像其它目标文件一样链接到可执行文件main中,而是在运行时做动态链接。

 

操作系统在加载执行main这个程序时,首先查看它有没有需要动态链接的未定义符号。
如果需要做动态链接,就查看这个程序指定了哪些共享库(我们用-lc指定了libc)以及用什么动态链接器来做动态链接
(我们用-dynamic-linker /lib/ld-linux.so.2指定了动态链接器)。 动态链接器在共享库中查找这些符号的定义,完成链接过程。

 

_start的反汇编
... Disassembly of section .
text: 080482e0 <_start>: 80482e0: 31 ed xor %ebp,%ebp 80482e2: 5e pop %esi 80482e3: 89 e1 mov %esp,%ecx 80482e5: 83 e4 f0 and $0xfffffff0,%esp 80482e8: 50 push %eax 80482e9: 54 push %esp 80482ea: 52 push %edx 80482eb: 68 00 84 04 08 push $0x8048400 80482f0: 68 10 84 04 08 push $0x8048410 80482f5: 51 push %ecx 80482f6: 56 push %esi 80482f7: 68 c4 83 04 08 push $0x80483c4 80482fc: e8 c3 ff ff ff call 80482c4 <__libc_start_main@plt> ...

_start首先将一系列参数压栈,然后调用libc的库函数__libc_start_main做初始化工作,其中最后一个压栈的push的参数main函数的地址,__libc_start_main在完成初始化工作之后会调用main函数。

由于main函数是被启动例程调用的,所以从main函数return时仍返回到启动例程中,main函数的返回值被启动例程得到。启动例程得到main函数的返回值后,会立刻用它做参数调用exit函数。exit也是libc中的函数,它首先做一些清理工作,然后调用上一章讲过的_exit系统调用终止进程,main函数的返回值最终被传给_exit系统调用,成为进程的退出状态。我们也可以在main函数中直接调用exit函数终止进程而不返回到启动例程。

#include <stdlib.h>

int main(void)
{
    exit(4);
}

和下面做法效果一样

int main(void) 
{ 
    return 4; 
}

 

 

其实上面我们写的ld命令做了很多简化,gcc在链接时还用到了另外几个目标文件,所以上图多画了一个框,表示组成可执行文件main的除了main.ocrt1.ocrti.o之外还有其它目标文件,本书不做深入讨论,用gcc-v选项可以了解详细的编译过程:

 gcc -v main.c -o main
Using built-in specs.
Target: i486-linux-gnu
...
 /usr/lib/gcc/i486-linux-gnu/4.3.2/cc1 -quiet -v main.c -D_FORTIFY_SOURCE=2 -quiet -dumpbase main.c -mtune=generic -auxbase main -version -fstack-protector -o /tmp/ccRGDpua.s
...
 as -V -Qy -o /tmp/ccidnZ1d.o /tmp/ccRGDpua.s
...
 /usr/lib/gcc/i486-linux-gnu/4.3.2/collect2 --eh-frame-hdr -m elf_i386 --hash-style=both -dynamic-linker /lib/ld-linux.so.2 -o main -z relro /usr/lib/gcc/i486-linux-gnu/4.3.2/../../../../lib/crt1.o /usr/lib/gcc/i486-linux-gnu/4.3.2/../../../../lib/crti.o /usr/lib/gcc/i486-linux-gnu/4.3.2/crtbegin.o -L/usr/lib/gcc/i486-linux-gnu/4.3.2 -L/usr/lib/gcc/i486-linux-gnu/4.3.2 -L/usr/lib/gcc/i486-linux-gnu/4.3.2/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/i486-linux-gnu/4.3.2/../../.. /tmp/ccidnZ1d.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/i486-linux-gnu/4.3.2/crtend.o /usr/lib/gcc/i486-linux-gnu/4.3.2/../../../../lib/crtn.o

 

汇编和C的关系

标签:xor   链接器   ble   没有   return   iter   一个   strong   tor   

原文地址:https://www.cnblogs.com/kelamoyujuzhen/p/9057726.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!