从刚开始学C语言的时候就给我们大脑里灌输了一个知识点: main函数是程序的入口,并且有且仅有一个.

当时我学习这个部分的时候对此深信不疑,main嘛,主嘛,那肯定就这个是入口了

根据后来的学习,慢慢地发现…好像这句话…真的是这样吗?如果是,那为什么会这样呢?或者说,为什么大家都说C语言main函数是程序的入口呢?

一段简单的C语言demo

#include<stdio.h>int main(){printf("hello world\n");return 0;}

这段代码很简单,都会写

那么gcc编译成a.out可执行文件后运行一下看看?
没有问题,能成功编译并且成功打印

对这个编译出来的可执行文件好好认识一下

由于我们知道,在linux平台的可执行文件一般是ELF文件,那么我们可以通过阅读elf文件的工具来看一看这个咋回事

执行指令 readelf -a a.out

ELF 头:Magic:  7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 类别:                              ELF64数据:                              2 补码,小端序 (little endian)版本:                              1 (current)OS/ABI:                            UNIX - System VABI 版本:                          0类型:                              EXEC (可执行文件)系统架构:                          Advanced Micro Devices X86-64版本:                              0x1入口点地址:              0x400440程序头起点:              64 (bytes into file)Start of section headers:          6480 (bytes into file)标志:             0x0本头的大小:       64 (字节)程序头大小:       56 (字节)Number of program headers:         9节头大小:         64 (字节)节头数量:         30字符串表索引节头: 29节头:[号] 名称              类型             地址              偏移量大小              全体大小          旗标   链接   信息   对齐[ 0]                   NULL             0000000000000000  000000000000000000000000  0000000000000000           0     0     0[ 1] .interp           PROGBITS         0000000000400238  00000238000000000000001c  0000000000000000   A       0     0     1[ 2] .note.ABI-tag     NOTE             0000000000400254  000002540000000000000020  0000000000000000   A       0     0     4[ 3] .note.gnu.build-i NOTE             0000000000400274  000002740000000000000024  0000000000000000   A       0     0     4[ 4] .gnu.hash         GNU_HASH         0000000000400298  00000298000000000000001c  0000000000000000   A       5     0     8[ 5] .dynsym           DYNSYM           00000000004002b8  000002b80000000000000060  0000000000000018   A       6     1     8[ 6] .dynstr           STRTAB           0000000000400318  00000318000000000000003d  0000000000000000   A       0     0     1[ 7] .gnu.version      VERSYM           0000000000400356  000003560000000000000008  0000000000000002   A       5     0     2[ 8] .gnu.version_r    VERNEED          0000000000400360  000003600000000000000020  0000000000000000   A       6     1     8[ 9] .rela.dyn         RELA             0000000000400380  000003800000000000000018  0000000000000018   A       5     0     8[10] .rela.plt         RELA             0000000000400398  000003980000000000000048  0000000000000018  AI       5    23     8[11] .init             PROGBITS         00000000004003e0  000003e0000000000000001a  0000000000000000  AX       0     0     4[12] .plt              PROGBITS         0000000000400400  000004000000000000000040  0000000000000010  AX       0     0     16[13] .text             PROGBITS         0000000000400440  000004400000000000000182  0000000000000000  AX       0     0     16[14] .fini             PROGBITS         00000000004005c4  000005c40000000000000009  0000000000000000  AX       0     0     4[15] .rodata           PROGBITS         00000000004005d0  000005d0000000000000001c  0000000000000000   A       0     0     8[16] .eh_frame_hdr     PROGBITS         00000000004005ec  000005ec0000000000000034  0000000000000000   A       0     0     4[17] .eh_frame         PROGBITS         0000000000400620  0000062000000000000000f4  0000000000000000   A       0     0     8[18] .init_array       INIT_ARRAY       0000000000600e10  00000e100000000000000008  0000000000000008  WA       0     0     8[19] .fini_array       FINI_ARRAY       0000000000600e18  00000e180000000000000008  0000000000000008  WA       0     0     8[20] .jcr              PROGBITS         0000000000600e20  00000e200000000000000008  0000000000000000  WA       0     0     8[21] .dynamic          DYNAMIC          0000000000600e28  00000e2800000000000001d0  0000000000000010  WA       6     0     8[22] .got              PROGBITS         0000000000600ff8  00000ff80000000000000008  0000000000000008  WA       0     0     8[23] .got.plt          PROGBITS         0000000000601000  000010000000000000000030  0000000000000008  WA       0     0     8[24] .data             PROGBITS         0000000000601030  000010300000000000000004  0000000000000000  WA       0     0     1[25] .bss              NOBITS           0000000000601034  000010340000000000000004  0000000000000000  WA       0     0     1[26] .comment          PROGBITS         0000000000000000  00001034000000000000005a  0000000000000001  MS       0     0     1[27] .symtab           SYMTAB           0000000000000000  0000109000000000000005e8  0000000000000018          28    46     8[28] .strtab           STRTAB           0000000000000000  0000167800000000000001c9  0000000000000000           0     0     1[29] .shstrtab         STRTAB           0000000000000000  000018410000000000000108  0000000000000000           0     0     1
Key to Flags:W (write), A (alloc), X (execute), M (merge), S (strings), I (info),L (link order), O (extra OS processing required), G (group), T (TLS),C (compressed), x (unknown), o (OS specific), E (exclude),l (large), p (processor specific)There are no section groups in this file.程序头:Type           Offset             VirtAddr           PhysAddrFileSiz            MemSiz              Flags  AlignPHDR           0x0000000000000040 0x0000000000400040 0x00000000004000400x00000000000001f8 0x00000000000001f8  R E    8INTERP         0x0000000000000238 0x0000000000400238 0x00000000004002380x000000000000001c 0x000000000000001c  R      1[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]LOAD           0x0000000000000000 0x0000000000400000 0x00000000004000000x0000000000000714 0x0000000000000714  R E    200000LOAD           0x0000000000000e10 0x0000000000600e10 0x0000000000600e100x0000000000000224 0x0000000000000228  RW     200000DYNAMIC        0x0000000000000e28 0x0000000000600e28 0x0000000000600e280x00000000000001d0 0x00000000000001d0  RW     8NOTE           0x0000000000000254 0x0000000000400254 0x00000000004002540x0000000000000044 0x0000000000000044  R      4GNU_EH_FRAME   0x00000000000005ec 0x00000000004005ec 0x00000000004005ec0x0000000000000034 0x0000000000000034  R      4GNU_STACK      0x0000000000000000 0x0000000000000000 0x00000000000000000x0000000000000000 0x0000000000000000  RW     10GNU_RELRO      0x0000000000000e10 0x0000000000600e10 0x0000000000600e100x00000000000001f0 0x00000000000001f0  R      1Section to Segment mapping:段节...00     01     .interp 02     .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame 03     .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss 04     .dynamic 05     .note.ABI-tag .note.gnu.build-id 06     .eh_frame_hdr 07     08     .init_array .fini_array .jcr .dynamic .got Dynamic section at offset 0xe28 contains 24 entries:标记        类型                         名称/值0x0000000000000001 (NEEDED)             共享库:[libc.so.6]0x000000000000000c (INIT)               0x4003e00x000000000000000d (FINI)               0x4005c40x0000000000000019 (INIT_ARRAY)         0x600e100x000000000000001b (INIT_ARRAYSZ)       8 (bytes)0x000000000000001a (FINI_ARRAY)         0x600e180x000000000000001c (FINI_ARRAYSZ)       8 (bytes)0x000000006ffffef5 (GNU_HASH)           0x4002980x0000000000000005 (STRTAB)             0x4003180x0000000000000006 (SYMTAB)             0x4002b80x000000000000000a (STRSZ)              61 (bytes)0x000000000000000b (SYMENT)             24 (bytes)0x0000000000000015 (DEBUG)              0x00x0000000000000003 (PLTGOT)             0x6010000x0000000000000002 (PLTRELSZ)           72 (bytes)0x0000000000000014 (PLTREL)             RELA0x0000000000000017 (JMPREL)             0x4003980x0000000000000007 (RELA)               0x4003800x0000000000000008 (RELASZ)             24 (bytes)0x0000000000000009 (RELAENT)            24 (bytes)0x000000006ffffffe (VERNEED)            0x4003600x000000006fffffff (VERNEEDNUM)         10x000000006ffffff0 (VERSYM)             0x4003560x0000000000000000 (NULL)               0x0重定位节 '.rela.dyn' 位于偏移量 0x380 含有 1 个条目:偏移量          信息           类型           符号值        符号名称 + 加数
000000600ff8  000300000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0重定位节 '.rela.plt' 位于偏移量 0x398 含有 3 个条目:偏移量          信息           类型           符号值        符号名称 + 加数
000000601018  000100000007 R_X86_64_JUMP_SLO 0000000000000000 puts@GLIBC_2.2.5 + 0
000000601020  000200000007 R_X86_64_JUMP_SLO 0000000000000000 __libc_start_main@GLIBC_2.2.5 + 0
000000601028  000300000007 R_X86_64_JUMP_SLO 0000000000000000 __gmon_start__ + 0The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported.Symbol table '.dynsym' contains 4 entries:Num:    Value          Size Type    Bind   Vis      Ndx Name0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 1: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND puts@GLIBC_2.2.5 (2)2: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@GLIBC_2.2.5 (2)3: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__Symbol table '.symtab' contains 63 entries:Num:    Value          Size Type    Bind   Vis      Ndx Name0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 1: 0000000000400238     0 SECTION LOCAL  DEFAULT    1 2: 0000000000400254     0 SECTION LOCAL  DEFAULT    2 3: 0000000000400274     0 SECTION LOCAL  DEFAULT    3 4: 0000000000400298     0 SECTION LOCAL  DEFAULT    4 5: 00000000004002b8     0 SECTION LOCAL  DEFAULT    5 6: 0000000000400318     0 SECTION LOCAL  DEFAULT    6 7: 0000000000400356     0 SECTION LOCAL  DEFAULT    7 8: 0000000000400360     0 SECTION LOCAL  DEFAULT    8 9: 0000000000400380     0 SECTION LOCAL  DEFAULT    9 10: 0000000000400398     0 SECTION LOCAL  DEFAULT   10 11: 00000000004003e0     0 SECTION LOCAL  DEFAULT   11 12: 0000000000400400     0 SECTION LOCAL  DEFAULT   12 13: 0000000000400440     0 SECTION LOCAL  DEFAULT   13 14: 00000000004005c4     0 SECTION LOCAL  DEFAULT   14 15: 00000000004005d0     0 SECTION LOCAL  DEFAULT   15 16: 00000000004005ec     0 SECTION LOCAL  DEFAULT   16 17: 0000000000400620     0 SECTION LOCAL  DEFAULT   17 18: 0000000000600e10     0 SECTION LOCAL  DEFAULT   18 19: 0000000000600e18     0 SECTION LOCAL  DEFAULT   19 20: 0000000000600e20     0 SECTION LOCAL  DEFAULT   20 21: 0000000000600e28     0 SECTION LOCAL  DEFAULT   21 22: 0000000000600ff8     0 SECTION LOCAL  DEFAULT   22 23: 0000000000601000     0 SECTION LOCAL  DEFAULT   23 24: 0000000000601030     0 SECTION LOCAL  DEFAULT   24 25: 0000000000601034     0 SECTION LOCAL  DEFAULT   25 26: 0000000000000000     0 SECTION LOCAL  DEFAULT   26 27: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c28: 0000000000600e20     0 OBJECT  LOCAL  DEFAULT   20 __JCR_LIST__29: 0000000000400470     0 FUNC    LOCAL  DEFAULT   13 deregister_tm_clones30: 00000000004004a0     0 FUNC    LOCAL  DEFAULT   13 register_tm_clones31: 00000000004004e0     0 FUNC    LOCAL  DEFAULT   13 __do_global_dtors_aux32: 0000000000601034     1 OBJECT  LOCAL  DEFAULT   25 completed.635533: 0000000000600e18     0 OBJECT  LOCAL  DEFAULT   19 __do_global_dtors_aux_fin34: 0000000000400500     0 FUNC    LOCAL  DEFAULT   13 frame_dummy35: 0000000000600e10     0 OBJECT  LOCAL  DEFAULT   18 __frame_dummy_init_array_36: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS test.c37: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c38: 0000000000400710     0 OBJECT  LOCAL  DEFAULT   17 __FRAME_END__39: 0000000000600e20     0 OBJECT  LOCAL  DEFAULT   20 __JCR_END__40: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS 41: 0000000000600e18     0 NOTYPE  LOCAL  DEFAULT   18 __init_array_end42: 0000000000600e28     0 OBJECT  LOCAL  DEFAULT   21 _DYNAMIC43: 0000000000600e10     0 NOTYPE  LOCAL  DEFAULT   18 __init_array_start44: 00000000004005ec     0 NOTYPE  LOCAL  DEFAULT   16 __GNU_EH_FRAME_HDR45: 0000000000601000     0 OBJECT  LOCAL  DEFAULT   23 _GLOBAL_OFFSET_TABLE_46: 00000000004005c0     2 FUNC    GLOBAL DEFAULT   13 __libc_csu_fini47: 0000000000601030     0 NOTYPE  WEAK   DEFAULT   24 data_start48: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND puts@@GLIBC_2.2.549: 0000000000601034     0 NOTYPE  GLOBAL DEFAULT   24 _edata50: 00000000004005c4     0 FUNC    GLOBAL DEFAULT   14 _fini51: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@@GLIBC_52: 0000000000601030     0 NOTYPE  GLOBAL DEFAULT   24 __data_start53: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__54: 00000000004005d8     0 OBJECT  GLOBAL HIDDEN    15 __dso_handle55: 00000000004005d0     4 OBJECT  GLOBAL DEFAULT   15 _IO_stdin_used56: 0000000000400550   101 FUNC    GLOBAL DEFAULT   13 __libc_csu_init57: 0000000000601038     0 NOTYPE  GLOBAL DEFAULT   25 _end58: 0000000000400440     0 FUNC    GLOBAL DEFAULT   13 _start59: 0000000000601034     0 NOTYPE  GLOBAL DEFAULT   25 __bss_start60: 000000000040052d    21 FUNC    GLOBAL DEFAULT   13 main61: 0000000000601038     0 OBJECT  GLOBAL HIDDEN    24 __TMC_END__62: 00000000004003e0     0 FUNC    GLOBAL DEFAULT   11 _initVersion symbols section '.gnu.version' contains 4 entries:地址:0000000000400356  Offset: 0x000356  Link: 5 (.dynsym)000:   0 (*本地*)       2 (GLIBC_2.2.5)   2 (GLIBC_2.2.5)   0 (*本地*)    Version needs section '.gnu.version_r' contains 1 entries:地址:0x0000000000400360  Offset: 0x000360  Link: 6 (.dynstr)000000: 版本: 1  文件:libc.so.6  计数:10x0010:名称:GLIBC_2.2.5  标志:无  版本:2Displaying notes found at file offset 0x00000254 with length 0x00000020:所有者             Data size  DescriptionGNU                  0x00000010  NT_GNU_ABI_TAG (ABI version tag)OS: Linux, ABI: 2.6.32Displaying notes found at file offset 0x00000274 with length 0x00000024:所有者             Data size DescriptionGNU                  0x00000014  NT_GNU_BUILD_ID (unique build ID bitstring)Build ID: a22f3cbab085833d1404bce09e1fd1fb7138db77

重点关注,程序的入口点地址 0x400440

通过另外一个指令objdump -S a.out查看已经编译完之后反汇编的结果

a.out:     文件格式 elf64-x86-64Disassembly of section .init:00000000004003e0 <_init>:4003e0:   48 83 ec 08             sub    $0x8,%rsp4003e4: 48 8b 05 0d 0c 20 00    mov    0x200c0d(%rip),%rax        # 600ff8 <__gmon_start__>4003eb:    48 85 c0                test   %rax,%rax4003ee: 74 05                   je     4003f5 <_init+0x15>4003f0:    e8 3b 00 00 00          callq  400430 <__gmon_start__@plt>4003f5:    48 83 c4 08             add    $0x8,%rsp4003f9: c3                      retq   Disassembly of section .plt:0000000000400400 <.plt>:400400:    ff 35 02 0c 20 00       pushq  0x200c02(%rip)        # 601008 <_GLOBAL_OFFSET_TABLE_+0x8>400406: ff 25 04 0c 20 00       jmpq   *0x200c04(%rip)        # 601010 <_GLOBAL_OFFSET_TABLE_+0x10>40040c:   0f 1f 40 00             nopl   0x0(%rax)0000000000400410 <puts@plt>:400410:  ff 25 02 0c 20 00       jmpq   *0x200c02(%rip)        # 601018 <puts@GLIBC_2.2.5>400416: 68 00 00 00 00          pushq  $0x040041b:  e9 e0 ff ff ff          jmpq   400400 <.plt>0000000000400420 <__libc_start_main@plt>:400420:   ff 25 fa 0b 20 00       jmpq   *0x200bfa(%rip)        # 601020 <__libc_start_main@GLIBC_2.2.5>400426:    68 01 00 00 00          pushq  $0x140042b:  e9 d0 ff ff ff          jmpq   400400 <.plt>0000000000400430 <__gmon_start__@plt>:400430:  ff 25 f2 0b 20 00       jmpq   *0x200bf2(%rip)        # 601028 <__gmon_start__>400436:    68 02 00 00 00          pushq  $0x240043b:  e9 c0 ff ff ff          jmpq   400400 <.plt>Disassembly of section .text:0000000000400440 <_start>:400440:  31 ed                   xor    %ebp,%ebp400442: 49 89 d1                mov    %rdx,%r9400445:  5e                      pop    %rsi400446:  48 89 e2                mov    %rsp,%rdx400449: 48 83 e4 f0             and    $0xfffffffffffffff0,%rsp40044d:  50                      push   %rax40044e:  54                      push   %rsp40044f:  49 c7 c0 c0 05 40 00    mov    $0x4005c0,%r8400456: 48 c7 c1 50 05 40 00    mov    $0x400550,%rcx40045d:    48 c7 c7 2d 05 40 00    mov    $0x40052d,%rdi400464:    e8 b7 ff ff ff          callq  400420 <__libc_start_main@plt>400469: f4                      hlt    40046a:  66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)0000000000400470 <deregister_tm_clones>:400470:    b8 3f 10 60 00          mov    $0x60103f,%eax400475:    55                      push   %rbp400476:  48 2d 38 10 60 00       sub    $0x601038,%rax40047c:    48 83 f8 0e             cmp    $0xe,%rax400480: 48 89 e5                mov    %rsp,%rbp400483: 77 02                   ja     400487 <deregister_tm_clones+0x17>400485: 5d                      pop    %rbp400486:  c3                      retq   400487:  b8 00 00 00 00          mov    $0x0,%eax40048c: 48 85 c0                test   %rax,%rax40048f: 74 f4                   je     400485 <deregister_tm_clones+0x15>400491: 5d                      pop    %rbp400492:  bf 38 10 60 00          mov    $0x601038,%edi400497:    ff e0                   jmpq   *%rax400499: 0f 1f 80 00 00 00 00    nopl   0x0(%rax)00000000004004a0 <register_tm_clones>:4004a0: b8 38 10 60 00          mov    $0x601038,%eax4004a5:    55                      push   %rbp4004a6:  48 2d 38 10 60 00       sub    $0x601038,%rax4004ac:    48 c1 f8 03             sar    $0x3,%rax4004b0: 48 89 e5                mov    %rsp,%rbp4004b3: 48 89 c2                mov    %rax,%rdx4004b6: 48 c1 ea 3f             shr    $0x3f,%rdx4004ba:    48 01 d0                add    %rdx,%rax4004bd: 48 d1 f8                sar    %rax4004c0:  75 02                   jne    4004c4 <register_tm_clones+0x24>4004c2:   5d                      pop    %rbp4004c3:  c3                      retq   4004c4:  ba 00 00 00 00          mov    $0x0,%edx4004c9: 48 85 d2                test   %rdx,%rdx4004cc: 74 f4                   je     4004c2 <register_tm_clones+0x22>4004ce:   5d                      pop    %rbp4004cf:  48 89 c6                mov    %rax,%rsi4004d2: bf 38 10 60 00          mov    $0x601038,%edi4004d7:    ff e2                   jmpq   *%rdx4004d9: 0f 1f 80 00 00 00 00    nopl   0x0(%rax)00000000004004e0 <__do_global_dtors_aux>:4004e0:  80 3d 4d 0b 20 00 00    cmpb   $0x0,0x200b4d(%rip)        # 601034 <_edata>4004e7:    75 11                   jne    4004fa <__do_global_dtors_aux+0x1a>4004e9:    55                      push   %rbp4004ea:  48 89 e5                mov    %rsp,%rbp4004ed: e8 7e ff ff ff          callq  400470 <deregister_tm_clones>4004f2:   5d                      pop    %rbp4004f3:  c6 05 3a 0b 20 00 01    movb   $0x1,0x200b3a(%rip)        # 601034 <_edata>4004fa:    f3 c3                   repz retq 4004fc:   0f 1f 40 00             nopl   0x0(%rax)0000000000400500 <frame_dummy>:400500:    48 83 3d 18 09 20 00    cmpq   $0x0,0x200918(%rip)        # 600e20 <__JCR_END__>400507:   00 400508:  74 1e                   je     400528 <frame_dummy+0x28>40050a:  b8 00 00 00 00          mov    $0x0,%eax40050f: 48 85 c0                test   %rax,%rax400512: 74 14                   je     400528 <frame_dummy+0x28>400514:  55                      push   %rbp400515:  bf 20 0e 60 00          mov    $0x600e20,%edi40051a:    48 89 e5                mov    %rsp,%rbp40051d: ff d0                   callq  *%rax40051f: 5d                      pop    %rbp400520:  e9 7b ff ff ff          jmpq   4004a0 <register_tm_clones>400525: 0f 1f 00                nopl   (%rax)400528:    e9 73 ff ff ff          jmpq   4004a0 <register_tm_clones>000000000040052d <main>:40052d:   55                      push   %rbp40052e:  48 89 e5                mov    %rsp,%rbp400531: bf e0 05 40 00          mov    $0x4005e0,%edi400536:    e8 d5 fe ff ff          callq  400410 <puts@plt>40053b:  b8 00 00 00 00          mov    $0x0,%eax400540: 5d                      pop    %rbp400541:  c3                      retq   400542:  66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)400549:  00 00 00 40054c:    0f 1f 40 00             nopl   0x0(%rax)0000000000400550 <__libc_csu_init>:400550:    41 57                   push   %r15400552:  41 89 ff                mov    %edi,%r15d400555:    41 56                   push   %r14400557:  49 89 f6                mov    %rsi,%r1440055a: 41 55                   push   %r1340055c:  49 89 d5                mov    %rdx,%r1340055f: 41 54                   push   %r12400561:  4c 8d 25 a8 08 20 00    lea    0x2008a8(%rip),%r12        # 600e10 <__frame_dummy_init_array_entry>400568:    55                      push   %rbp400569:  48 8d 2d a8 08 20 00    lea    0x2008a8(%rip),%rbp        # 600e18 <__init_array_end>400570:  53                      push   %rbx400571:  4c 29 e5                sub    %r12,%rbp400574: 31 db                   xor    %ebx,%ebx400576: 48 c1 fd 03             sar    $0x3,%rbp40057a: 48 83 ec 08             sub    $0x8,%rsp40057e: e8 5d fe ff ff          callq  4003e0 <_init>400583:  48 85 ed                test   %rbp,%rbp400586: 74 1e                   je     4005a6 <__libc_csu_init+0x56>400588:  0f 1f 84 00 00 00 00    nopl   0x0(%rax,%rax,1)40058f:  00 400590:  4c 89 ea                mov    %r13,%rdx400593: 4c 89 f6                mov    %r14,%rsi400596: 44 89 ff                mov    %r15d,%edi400599:    41 ff 14 dc             callq  *(%r12,%rbx,8)40059d:    48 83 c3 01             add    $0x1,%rbx4005a1: 48 39 eb                cmp    %rbp,%rbx4005a4: 75 ea                   jne    400590 <__libc_csu_init+0x40>4005a6:  48 83 c4 08             add    $0x8,%rsp4005aa: 5b                      pop    %rbx4005ab:  5d                      pop    %rbp4005ac:  41 5c                   pop    %r124005ae:  41 5d                   pop    %r134005b0:  41 5e                   pop    %r144005b2:  41 5f                   pop    %r154005b4:  c3                      retq   4005b5:  90                      nop4005b6:  66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)4005bd:  00 00 00 00000000004005c0 <__libc_csu_fini>:4005c0:   f3 c3                   repz retq Disassembly of section .fini:00000000004005c4 <_fini>:4005c4:   48 83 ec 08             sub    $0x8,%rsp4005c8: 48 83 c4 08             add    $0x8,%rsp4005cc: c3                      retq

可以看到我们当前的a.out程序的main函数对应的汇编指令的起始地址是000000000040052d,并不是一开始在elf文件中显示的那个0x400440,不过你会发现,有一个代码段是0x400440 <_start>

所以至此我们可以知道<_start> 便是C语言程序的入口,操作系统调用程序的第一行执行的代码,并不是main函数中的指令

那么,是怎么到main的呢??

下面来看看glibc中的一些内容

_start的节选:

很显然,调用了一个__libc_start_main@PLT 说明这个地方是用到了动态链接的,将__libc_start_main链接到了当前的这个地方来

__libc_start_main干了件什么事呢?? 也就是进到了csu文件夹下的libc-start.c的LIBC_START_MAIN方法中(因为这个libc-start.c头部有段宏定义# define LIBC_START_MAIN __libc_start_main)

STATIC int
LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),int argc, char **argv,
#ifdef LIBC_START_MAIN_AUXVEC_ARGElfW(auxv_t) *auxvec,
#endif__typeof (main) init,void (*fini) (void),void (*rtld_fini) (void), void *stack_end)
{/* Result of the 'main' function.  */int result;__libc_multiple_libcs = &_dl_starting_up && !_dl_starting_up;#ifndef SHARED_dl_relocate_static_pie ();char **ev = &argv[argc + 1];__environ = ev;/* Store the lowest stack address.  This is done in ld.so if this isthe code for the DSO.  */__libc_stack_end = stack_end;# ifdef HAVE_AUX_VECTOR/* First process the auxiliary vector since we need to find theprogram header to locate an eventually present PT_TLS entry.  */
#  ifndef LIBC_START_MAIN_AUXVEC_ARGElfW(auxv_t) *auxvec;{char **evp = ev;while (*evp++ != NULL);auxvec = (ElfW(auxv_t) *) evp;}
#  endif_dl_aux_init (auxvec);if (GL(dl_phdr) == NULL)
# endif{/* Starting from binutils-2.23, the linker will define themagic symbol __ehdr_start to point to our own ELF headerif it is visible in a segment that also includes the phdrs.So we can set up _dl_phdr and _dl_phnum even without anyinformation from auxv.  */extern const ElfW(Ehdr) __ehdr_start__attribute__ ((weak, visibility ("hidden")));if (&__ehdr_start != NULL){assert (__ehdr_start.e_phentsize == sizeof *GL(dl_phdr));GL(dl_phdr) = (const void *) &__ehdr_start + __ehdr_start.e_phoff;GL(dl_phnum) = __ehdr_start.e_phnum;}}/* Initialize very early so that tunables can use it.  */__libc_init_secure ();__tunables_init (__environ);ARCH_INIT_CPU_FEATURES ();/* Perform IREL{,A} relocations.  */ARCH_SETUP_IREL ();/* The stack guard goes into the TCB, so initialize it early.  */ARCH_SETUP_TLS ();/* In some architectures, IREL{,A} relocations happen after TLS setup inorder to let IFUNC resolvers benefit from TCB information, e.g. powerpc'shwcap and platform fields available in the TCB.  */ARCH_APPLY_IREL ();/* Set up the stack checker's canary.  */uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard (_dl_random);
# ifdef THREAD_SET_STACK_GUARDTHREAD_SET_STACK_GUARD (stack_chk_guard);
# else__stack_chk_guard = stack_chk_guard;
# endif# ifdef DL_SYSDEP_OSCHECKif (!__libc_multiple_libcs){/* This needs to run to initiliaze _dl_osversion before TLSsetup might check it.  */DL_SYSDEP_OSCHECK (__libc_fatal);}
# endif/* Initialize libpthread if linked in.  */if (__pthread_initialize_minimal != NULL)__pthread_initialize_minimal ();/* Set up the pointer guard value.  */uintptr_t pointer_chk_guard = _dl_setup_pointer_guard (_dl_random,stack_chk_guard);
# ifdef THREAD_SET_POINTER_GUARDTHREAD_SET_POINTER_GUARD (pointer_chk_guard);
# else__pointer_chk_guard_local = pointer_chk_guard;
# endif#endif /* !SHARED  *//* Register the destructor of the dynamic linker if there is any.  */if (__glibc_likely (rtld_fini != NULL))__cxa_atexit ((void (*) (void *)) rtld_fini, NULL, NULL);#ifndef SHARED/* Call the initializer of the libc.  This is only needed here if weare compiling for the static library in which case we haven'trun the constructors in `_dl_start_user'.  */__libc_init_first (argc, argv, __environ);/* Register the destructor of the program, if any.  */if (fini)__cxa_atexit ((void (*) (void *)) fini, NULL, NULL);/* Some security at this point.  Prevent starting a SUID binary wherethe standard file descriptors are not opened.  We have to do thisonly for statically linked applications since otherwise the dynamicloader did the work already.  */if (__builtin_expect (__libc_enable_secure, 0))__libc_check_standard_fds ();
#endif/* Call the initializer of the program, if any.  */
#ifdef SHAREDif (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))GLRO(dl_debug_printf) ("\ninitialize program: %s\n\n", argv[0]);
#endifif (init)(*init) (argc, argv, __environ MAIN_AUXVEC_PARAM);#ifdef SHARED/* Auditing checkpoint: we have a new object.  */if (__glibc_unlikely (GLRO(dl_naudit) > 0)){struct audit_ifaces *afct = GLRO(dl_audit);struct link_map *head = GL(dl_ns)[LM_ID_BASE]._ns_loaded;for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt){if (afct->preinit != NULL)afct->preinit (&head->l_audit[cnt].cookie);afct = afct->next;}}
#endif#ifdef SHAREDif (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS))GLRO(dl_debug_printf) ("\ntransferring control: %s\n\n", argv[0]);
#endif#ifndef SHARED_dl_debug_initialize (0, LM_ID_BASE);
#endif
#ifdef HAVE_CLEANUP_JMP_BUF/* Memory for the cancellation buffer.  */struct pthread_unwind_buf unwind_buf;int not_first_call;not_first_call = setjmp ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf);if (__glibc_likely (! not_first_call)){struct pthread *self = THREAD_SELF;/* Store old info.  */unwind_buf.priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf);unwind_buf.priv.data.cleanup = THREAD_GETMEM (self, cleanup);/* Store the new cleanup handler info.  */THREAD_SETMEM (self, cleanup_jmp_buf, &unwind_buf);/* Run the program.  */result = main (argc, argv, __environ MAIN_AUXVEC_PARAM);}else{/* Remove the thread-local data.  */
# ifdef SHAREDPTHFCT_CALL (ptr__nptl_deallocate_tsd, ());
# elseextern void __nptl_deallocate_tsd (void) __attribute ((weak));__nptl_deallocate_tsd ();
# endif/* One less thread.  Decrement the counter.  If it is zero weterminate the entire process.  */result = 0;
# ifdef SHAREDunsigned int *ptr = __libc_pthread_functions.ptr_nthreads;
#  ifdef PTR_DEMANGLEPTR_DEMANGLE (ptr);
#  endif
# elseextern unsigned int __nptl_nthreads __attribute ((weak));unsigned int *const ptr = &__nptl_nthreads;
# endifif (! atomic_decrement_and_test (ptr))/* Not much left to do but to exit the thread, not the process.  */__exit_thread ();}
#else/* Nothing fancy, just call the function.  */result = main (argc, argv, __environ MAIN_AUXVEC_PARAM);
#endifexit (result);
}

重点关注 先 if (init) (*init) (argc, argv, __environ MAIN_AUXVEC_PARAM);然后经过一系列动态链接的过程,最终调用 LIBC_START_MAIN中的main方法,至此程序才正式进入到main方法

所以…C语言程序的入口是main函数么?你们怎么觉得的呢???

C语言程序的入口真的是main方法吗?相关推荐

  1. 《JAVA 语言程序设计基础篇》chapter 5 方法

    <JAVA 语言程序设计基础篇>chapter 5 方法 依然是先回顾一下上一章的内容 主要是关于循环语句 这里做一个有关于蒙特卡罗模拟有关的练习 先是一段背景介绍 蒙特卡罗方法通过抓住事 ...

  2. c语言清除键盘缓冲区函数,C语言程序中清除键盘缓冲区的方法

    第四期2006年12月益阳职业技术学院学报 JournalofYiyangVocationalandTechnicalCollegeNO.4Dec.2006 C语言程序中清除键盘缓冲区的方法 杨长虹 ...

  3. c语言程序的入口是哪部分,C语言入口函数和LD_PRELOAD环境变量

    零.C语言入口函数 从第一天学习C语言开始,我们的脑子里就深深烙下这样一个概念:C语言程序总是从main()函数开始执行,main()函数结束,程序也就结束了.在平时的练习中貌似这没有问题,但事实真的 ...

  4. c语言程序 5ms 延时,计算机单片机延时方法电脑c语言.docx

    计算机单片机延时方法电脑C 语言 您需要登录后才可以回帖登录| 注册发布 单片机是一种集成电路芯片,是采用超大规模集成电路技术把 具有数据处理能力的中央处理器CPU.随机存储器RAM.只读存储器 RO ...

  5. Linux系统中创建C语言程序文件并编译执行的方法

    使用vim编辑器创建并编辑C语言源程序文件           执行命令"vim button_led.c"打开Button_Led目录下button_led.c源程序文件并进行编 ...

  6. linux下运行c语言程序报Segmentation Fault的定位方法

    打开终端,然后输入以下命令开启ulimit ulimit -c unlimited # 打开ulimit ulimit -c # 如果打开成功会返回unlimited PS:以上开启ulimit的操作 ...

  7. 杨辉三角python语言程序思路_python杨辉三角方法的实例介绍

    程序输出需要实现如下效果:[1] [1,1] [1,2,1] [1,3,3,1] ...... 方法:迭代,生成器def triangles() L = [1] while True: yiled L ...

  8. 激光测距仪系统设计 c语言程序),基于时差法的激光测距方法与应用

    摘要: 激光测距技术被发现并研制出以后,因为它的测量精度非常高,与其他传统测距技术相比具有的优点非常多,并且激光测距基本能够应用在所有测量环境,激光测距的基本方法是用激光在目标物与发射器之间传播时间来 ...

  9. Java中的main方法

    2019独角兽企业重金招聘Python工程师标准>>> 在一个Java应用程序中,通常程序的入口是一个main方法,它被声明为公有静态方法,参数是一个字符串数组,返回值为Void类型 ...

最新文章

  1. FPGA中的Logic Cells, Logic Slices, Configurable Logic Blocks and Gates 的定义
  2. 稀疏多项式的运算用链表_用漫画告诉你—什么是HashMap?
  3. 用CSS的 filter 来轻松实现图层半透明
  4. 20.毛玻璃效果blur
  5. 巧用拦截器:高效的扩展点设计
  6. Spark Metrics配置详解
  7. linux服务器做301跳转,nginx 实现当找不到文件时实现301跳转
  8. C++基础——类模板
  9. Android计分器课程设计,比赛计分器课程设计.doc
  10. linux能yum装mcafee吗,Ubuntu安装Mcafee步骤
  11. .kux转mp4文件
  12. 微信小程序tabBar闪烁问题
  13. 关于癌症的思考:癌症的本质是什么
  14. 类动态规划求解较小规模的最大团问题(Python实现)
  15. Python设置32位环境
  16. c语言中立方和乘法怎么表示什么区别,c语言中的乘方符号是什么?
  17. 设计模式之观察者模式详解(附应用举例实现)
  18. mac下统计代码行数方法
  19. Apache Velocity 模板语言 特殊字符${ $!{ 原样输出问题 转义符 # ! 无效
  20. windows 没有应用商店,直接安装所需应用的解决方案

热门文章

  1. Pyecharts绘制上下组合图、左右组合图、一轴多图,超经典!
  2. php文件如何上传到服务器,php文件怎么上传到云服务器
  3. 卡巴斯基网络安全解决方案-服务器虚拟化安全2.0安装方法,营销材料(内部)_卡巴斯基网络安全解决方案-虚拟化安全(KSV2.0)_V1.0.docx...
  4. High performance server architecture(高性能服务器架构)
  5. 迭代求解线性方程组的解
  6. ElasticSerach7.6.0拼音分词器安装和使用
  7. 最好的vsftpd配置教程
  8. 实时语音通讯的回音消除技术详解
  9. 每天学点英语语法-重头开始8
  10. c程序的基本组成单位是什么?