#include <stdio.h>
int main()
{
printf("Hello World\n");
return 0;
}
在Linux下,当我们使用GCC来编译Hello World程序时,只需使用最简单的命令:
mali@mali:~/code/link$ cat hello.c
#include <stdio.h>
int main()
{
printf("Hello World\n");
return 0;
}
mali@mali:~/code/link$ gcc hello.c
mali@mali:~/code/link$ ls -l
total 16
-rwxrwxr-x 1 mali mali 8600 9月 3 23:20 a.out
-rw-rw-r-- 1 mali mali 73 9月 3 23:19 hello.c
mali@mali:~/code/link$ ./a.out
Hello World
mali@mali:~/code/link$
事实上,上述过程可以分解为4个步骤,分别是预处理(Preprocessing)、编译(Compilation)、汇编(Assembly)和链接(Linking)。
1.预处理(Preprocessing)
mali@mali:~/code/link$ gcc -E hello.c -o hello.i
mali@mali:~/code/link$ ls -l
total 36
-rwxrwxr-x 1 mali mali 8600 9月 3 23:20 a.out
-rw-rw-r-- 1 mali mali 73 9月 3 23:19 hello.c
-rw-rw-r-- 1 mali mali 17103 9月 3 23:25 hello.i
mali@mali:~/code/link$ cat hello.i
# 1 "hello.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "hello.c"
# 1 "/usr/include/stdio.h" 1 3 4
# 27 "/usr/include/stdio.h" 3 4
# 1 "/usr/include/features.h" 1 3 4
# 367 "/usr/include/features.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 1 3 4
# 410 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4
# 411 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 2 3 4
# 368 "/usr/include/features.h" 2 3 4
# 391 "/usr/include/features.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 1 3 4
# 10 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/gnu/stubs-64.h" 1 3 4
# 11 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 2 3 4
# 392 "/usr/include/features.h" 2 3 4
# 28 "/usr/include/stdio.h" 2 3 4
# 1 "/usr/lib/gcc/x86_64-linux-gnu/5/include/stddef.h" 1 3 4
# 216 "/usr/lib/gcc/x86_64-linux-gnu/5/include/stddef.h" 3 4
# 216 "/usr/lib/gcc/x86_64-linux-gnu/5/include/stddef.h" 3 4
typedef long unsigned int size_t;
# 34 "/usr/include/stdio.h" 2 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/types.h" 1 3 4
# 27 "/usr/include/x86_64-linux-gnu/bits/types.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4
# 28 "/usr/include/x86_64-linux-gnu/bits/types.h" 2 3 4
typedef unsigned char __u_char;
typedef unsigned short int __u_short;
typedef unsigned int __u_int;
typedef unsigned long int __u_long;
typedef signed char __int8_t;
typedef unsigned char __uint8_t;
typedef signed short int __int16_t;
typedef unsigned short int __uint16_t;
typedef signed int __int32_t;
typedef unsigned int __uint32_t;
typedef signed long int __int64_t;
typedef unsigned long int __uint64_t;
...
extern int fileno (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
extern int fileno_unlocked (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
# 872 "/usr/include/stdio.h" 3 4
extern FILE *popen (const char *__command, const char *__modes) ;
extern int pclose (FILE *__stream);
extern char *ctermid (char *__s) __attribute__ ((__nothrow__ , __leaf__));
# 912 "/usr/include/stdio.h" 3 4
extern void flockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
extern int ftrylockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
# 942 "/usr/include/stdio.h" 3 4
# 2 "hello.c" 2
# 2 "hello.c"
int main()
{
printf("Hello World\n");
return 0;
}
mali@mali:~/code/link$
2.编译(Compilation)
mali@mali:~/code/link$ gcc -S hello.i -o hello.s
mali@mali:~/code/link$ ls -l
total 40
-rwxrwxr-x 1 mali mali 8600 9月 3 23:20 a.out
-rw-rw-r-- 1 mali mali 73 9月 3 23:19 hello.c
-rw-rw-r-- 1 mali mali 17103 9月 3 23:25 hello.i
-rw-rw-r-- 1 mali mali 456 9月 3 23:33 hello.s
mali@mali:~/code/link$ cat hello.s
.file "hello.c"
.section .rodata
.LC0:
.string "Hello World"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $.LC0, %edi
call puts
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609"
.section .note.GNU-stack,"",@progbits
mali@mali:~/code/link$
3.汇编(Assembly)
mali@mali:~/code/link$ gcc -c hello.s -o hello.o
mali@mali:~/code/link$ ls -l
total 44
-rwxrwxr-x 1 mali mali 8600 9月 3 23:20 a.out
-rw-rw-r-- 1 mali mali 73 9月 3 23:19 hello.c
-rw-rw-r-- 1 mali mali 17103 9月 3 23:25 hello.i
-rw-rw-r-- 1 mali mali 1504 9月 3 23:35 hello.o
-rw-rw-r-- 1 mali mali 456 9月 3 23:33 hello.s
mali@mali:~/code/link$ objdump -d hello.o
hello.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <main>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: bf 00 00 00 00 mov $0x0,%edi
9: e8 00 00 00 00 callq e <main+0xe>
e: b8 00 00 00 00 mov $0x0,%eax
13: 5d pop %rbp
14: c3 retq
mali@mali:~/code/link$
4.链接(Linking)
0000000000400400 <puts@plt>:
400400: ff 25 12 0c 20 00 jmpq *0x200c12(%rip) # 601018 <_GLOBAL_OFFSET_TABLE_+0x18>
400406: 68 00 00 00 00 pushq $0x0
40040b: e9 e0 ff ff ff jmpq 4003f0 <_init+0x28>
0000000000400526 <main>:
400526: 55 push %rbp
400527: 48 89 e5 mov %rsp,%rbp
40052a: bf c4 05 40 00 mov $0x4005c4,%edi
40052f: e8 cc fe ff ff callq 400400 <puts@plt>
400534: b8 00 00 00 00 mov $0x0,%eax
400539: 5d pop %rbp
40053a: c3 retq
40053b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
mali@mali:~/code/link$ gcc hello.o -o hello
mali@mali:~/code/link$ ls -l
total 56
-rwxrwxr-x 1 mali mali 8600 9月 3 23:20 a.out
-rwxrwxr-x 1 mali mali 8600 9月 3 23:50 hello
-rw-rw-r-- 1 mali mali 73 9月 3 23:19 hello.c
-rw-rw-r-- 1 mali mali 17103 9月 3 23:25 hello.i
-rw-rw-r-- 1 mali mali 1504 9月 3 23:35 hello.o
-rw-rw-r-- 1 mali mali 456 9月 3 23:33 hello.s
mali@mali:~/code/link$ objdump -d hello
hello: file format elf64-x86-64
Disassembly of section .init:
00000000004003c8 <_init>:
4003c8: 48 83 ec 08 sub $0x8,%rsp
4003cc: 48 8b 05 25 0c 20 00 mov 0x200c25(%rip),%rax # 600ff8 <_DYNAMIC+0x1d0>
4003d3: 48 85 c0 test %rax,%rax
4003d6: 74 05 je 4003dd <_init+0x15>
4003d8: e8 43 00 00 00 callq 400420 <__libc_start_main@plt+0x10>
4003dd: 48 83 c4 08 add $0x8,%rsp
4003e1: c3 retq
Disassembly of section .plt:
00000000004003f0 <puts@plt-0x10>:
4003f0: ff 35 12 0c 20 00 pushq 0x200c12(%rip) # 601008 <_GLOBAL_OFFSET_TABLE_+0x8>
4003f6: ff 25 14 0c 20 00 jmpq *0x200c14(%rip) # 601010 <_GLOBAL_OFFSET_TABLE_+0x10>
4003fc: 0f 1f 40 00 nopl 0x0(%rax)
0000000000400400 <puts@plt>:
400400: ff 25 12 0c 20 00 jmpq *0x200c12(%rip) # 601018 <_GLOBAL_OFFSET_TABLE_+0x18>
400406: 68 00 00 00 00 pushq $0x0
40040b: e9 e0 ff ff ff jmpq 4003f0 <_init+0x28>
0000000000400410 <__libc_start_main@plt>:
400410: ff 25 0a 0c 20 00 jmpq *0x200c0a(%rip) # 601020 <_GLOBAL_OFFSET_TABLE_+0x20>
400416: 68 01 00 00 00 pushq $0x1
40041b: e9 d0 ff ff ff jmpq 4003f0 <_init+0x28>
Disassembly of section .plt.got:
0000000000400420 <.plt.got>:
400420: ff 25 d2 0b 20 00 jmpq *0x200bd2(%rip) # 600ff8 <_DYNAMIC+0x1d0>
400426: 66 90 xchg %ax,%ax
Disassembly of section .text:
0000000000400430 <_start>:
400430: 31 ed xor %ebp,%ebp
400432: 49 89 d1 mov %rdx,%r9
400435: 5e pop %rsi
400436: 48 89 e2 mov %rsp,%rdx
400439: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp
40043d: 50 push %rax
40043e: 54 push %rsp
40043f: 49 c7 c0 b0 05 40 00 mov $0x4005b0,%r8
400446: 48 c7 c1 40 05 40 00 mov $0x400540,%rcx
40044d: 48 c7 c7 26 05 40 00 mov $0x400526,%rdi
400454: e8 b7 ff ff ff callq 400410 <__libc_start_main@plt>
400459: f4 hlt
40045a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
0000000000400460 <deregister_tm_clones>:
400460: b8 3f 10 60 00 mov $0x60103f,%eax
400465: 55 push %rbp
400466: 48 2d 38 10 60 00 sub $0x601038,%rax
40046c: 48 83 f8 0e cmp $0xe,%rax
400470: 48 89 e5 mov %rsp,%rbp
400473: 76 1b jbe 400490 <deregister_tm_clones+0x30>
400475: b8 00 00 00 00 mov $0x0,%eax
40047a: 48 85 c0 test %rax,%rax
40047d: 74 11 je 400490 <deregister_tm_clones+0x30>
40047f: 5d pop %rbp
400480: bf 38 10 60 00 mov $0x601038,%edi
400485: ff e0 jmpq *%rax
400487: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1)
40048e: 00 00
400490: 5d pop %rbp
400491: c3 retq
400492: 0f 1f 40 00 nopl 0x0(%rax)
400496: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
40049d: 00 00 00
00000000004004a0 <register_tm_clones>:
4004a0: be 38 10 60 00 mov $0x601038,%esi
4004a5: 55 push %rbp
4004a6: 48 81 ee 38 10 60 00 sub $0x601038,%rsi
4004ad: 48 c1 fe 03 sar $0x3,%rsi
4004b1: 48 89 e5 mov %rsp,%rbp
4004b4: 48 89 f0 mov %rsi,%rax
4004b7: 48 c1 e8 3f shr $0x3f,%rax
4004bb: 48 01 c6 add %rax,%rsi
4004be: 48 d1 fe sar %rsi
4004c1: 74 15 je 4004d8 <register_tm_clones+0x38>
4004c3: b8 00 00 00 00 mov $0x0,%eax
4004c8: 48 85 c0 test %rax,%rax
4004cb: 74 0b je 4004d8 <register_tm_clones+0x38>
4004cd: 5d pop %rbp
4004ce: bf 38 10 60 00 mov $0x601038,%edi
4004d3: ff e0 jmpq *%rax
4004d5: 0f 1f 00 nopl (%rax)
4004d8: 5d pop %rbp
4004d9: c3 retq
4004da: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
00000000004004e0 <__do_global_dtors_aux>:
4004e0: 80 3d 51 0b 20 00 00 cmpb $0x0,0x200b51(%rip) # 601038 <__TMC_END__>
4004e7: 75 11 jne 4004fa <__do_global_dtors_aux+0x1a>
4004e9: 55 push %rbp
4004ea: 48 89 e5 mov %rsp,%rbp
4004ed: e8 6e ff ff ff callq 400460 <deregister_tm_clones>
4004f2: 5d pop %rbp
4004f3: c6 05 3e 0b 20 00 01 movb $0x1,0x200b3e(%rip) # 601038 <__TMC_END__>
4004fa: f3 c3 repz retq
4004fc: 0f 1f 40 00 nopl 0x0(%rax)
0000000000400500 <frame_dummy>:
400500: bf 20 0e 60 00 mov $0x600e20,%edi
400505: 48 83 3f 00 cmpq $0x0,(%rdi)
400509: 75 05 jne 400510 <frame_dummy+0x10>
40050b: eb 93 jmp 4004a0 <register_tm_clones>
40050d: 0f 1f 00 nopl (%rax)
400510: b8 00 00 00 00 mov $0x0,%eax
400515: 48 85 c0 test %rax,%rax
400518: 74 f1 je 40050b <frame_dummy+0xb>
40051a: 55 push %rbp
40051b: 48 89 e5 mov %rsp,%rbp
40051e: ff d0 callq *%rax
400520: 5d pop %rbp
400521: e9 7a ff ff ff jmpq 4004a0 <register_tm_clones>
0000000000400526 <main>:
400526: 55 push %rbp
400527: 48 89 e5 mov %rsp,%rbp
40052a: bf c4 05 40 00 mov $0x4005c4,%edi
40052f: e8 cc fe ff ff callq 400400 <puts@plt>
400534: b8 00 00 00 00 mov $0x0,%eax
400539: 5d pop %rbp
40053a: c3 retq
40053b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
0000000000400540 <__libc_csu_init>:
400540: 41 57 push %r15
400542: 41 56 push %r14
400544: 41 89 ff mov %edi,%r15d
400547: 41 55 push %r13
400549: 41 54 push %r12
40054b: 4c 8d 25 be 08 20 00 lea 0x2008be(%rip),%r12 # 600e10 <__frame_dummy_init_array_entry>
400552: 55 push %rbp
400553: 48 8d 2d be 08 20 00 lea 0x2008be(%rip),%rbp # 600e18 <__init_array_end>
40055a: 53 push %rbx
40055b: 49 89 f6 mov %rsi,%r14
40055e: 49 89 d5 mov %rdx,%r13
400561: 4c 29 e5 sub %r12,%rbp
400564: 48 83 ec 08 sub $0x8,%rsp
400568: 48 c1 fd 03 sar $0x3,%rbp
40056c: e8 57 fe ff ff callq 4003c8 <_init>
400571: 48 85 ed test %rbp,%rbp
400574: 74 20 je 400596 <__libc_csu_init+0x56>
400576: 31 db xor %ebx,%ebx
400578: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1)
40057f: 00
400580: 4c 89 ea mov %r13,%rdx
400583: 4c 89 f6 mov %r14,%rsi
400586: 44 89 ff mov %r15d,%edi
400589: 41 ff 14 dc callq *(%r12,%rbx,8)
40058d: 48 83 c3 01 add $0x1,%rbx
400591: 48 39 eb cmp %rbp,%rbx
400594: 75 ea jne 400580 <__libc_csu_init+0x40>
400596: 48 83 c4 08 add $0x8,%rsp
40059a: 5b pop %rbx
40059b: 5d pop %rbp
40059c: 41 5c pop %r12
40059e: 41 5d pop %r13
4005a0: 41 5e pop %r14
4005a2: 41 5f pop %r15
4005a4: c3 retq
4005a5: 90 nop
4005a6: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
4005ad: 00 00 00
00000000004005b0 <__libc_csu_fini>:
4005b0: f3 c3 repz retq
Disassembly of section .fini:
00000000004005b4 <_fini>:
4005b4: 48 83 ec 08 sub $0x8,%rsp
4005b8: 48 83 c4 08 add $0x8,%rsp
4005bc: c3 retq
mali@mali:~/code/link$