网站建设广告投放是什么,天津网站建设服务,工程中标查询网站,下载站模板 wordpress本博客#xff08;http://blog.csdn.net/livelylittlefish#xff09;贴出作者#xff08;三二一小鱼#xff09;相关研究、学习内容所做的笔记#xff0c;欢迎广大朋友指正#xff01; 结合hello world探讨gcc编译程序的过程 1. gcc简介 gcc/g是GNU工程的C和…本博客http://blog.csdn.net/livelylittlefish贴出作者三二一小鱼相关研究、学习内容所做的笔记欢迎广大朋友指正 结合hello world探讨gcc编译程序的过程 1. gcc简介 gcc/g是GNU工程的C和C编译器。都要用四个步骤中的一个或多个处理输入文件。 预处理(preprocessing)编译(compilation)汇编(assembly)连接(linking) 源文件后缀名标识源文件的语言但是对编译器来说后缀名控制着缺省设定。 gcc命令的一般格式为gcc [选项] 要编译的文件 [选项] [目标文件] gcc的详细内容可参考gcc manual。 2. gcc的输出选项 gcc输出选项-o后指定输出文件名gcc解释如下。 -o FILE Place output in file FILE. This applies regardless to whatever sort of output is being produced, whether it be an executable file, an object file, an assembler file or preprocessed C code. If -o is not specified, the default is to put an executable file in a.out, the object file for SOURCE.SUFFIX in SOURCE.o, its assembler file in SOURCE.s, a precompiled header file in SOURCE.SUFFIX.gch, and all preprocessed C source on standard output. 指定输出文件为FILE该选项不考虑GCC产生什么输出无论是可执行文件、目标文件、汇编文件还是预处理后的C代码。 如果没有使用-o选项默认的输出结果是:可执行文件为a.outsource.suffix的目标文件是source.o汇编文件是source.s而预处理后的C代码送往标准输出。 3. hello wolrd的处理过程 本文以hello world程序探讨GCC编译程序的过程。 hello.c文件内容如下。 #include stdio.h int main(int argc, char **argv) { printf(Hello World! via %x/n, printf); return 0; } 3.1 预处理(preprocessing) 在该阶段编译器将C源代码中的包含的头文件如stdio.h编译进来可以使用gcc的选项”-E”进行查看预处理结果。 Gcc manual中对-E选项的解释如下。 -E Stop after the preprocessing stage; do not run the compiler proper. The output is in the form of preprocessed source code, which is sent to the standard output. Input files which dont require preprocessing are ignored. 预处理后停止不进行编译。预处理后的代码送往标准输出。GCC忽略任何不需要预处理的输入文件。 格式gcc -E hello.c -o hello.i 作用对hello.c进行预处理输出为hello.i文件 Hello.c被预处理后的hello.i文件。 # 1 hello.c # 1 built-in # 1 command line # 1 hello.c # 1 /usr/include/stdio.h 1 3 4 # 28 /usr/include/stdio.h 3 4 # 1 /usr/include/features.h 1 3 4 # 335 /usr/include/features.h 3 4 # 1 /usr/include/sys/cdefs.h 1 3 4 # 360 /usr/include/sys/cdefs.h 3 4 # 1 /usr/include/bits/wordsize.h 1 3 4 # 361 /usr/include/sys/cdefs.h 2 3 4 # 336 /usr/include/features.h 2 3 4 # 359 /usr/include/features.h 3 4 # 1 /usr/include/gnu/stubs.h 1 3 4 # 1 /usr/include/bits/wordsize.h 1 3 4 # 5 /usr/include/gnu/stubs.h 2 3 4 # 1 /usr/include/gnu/stubs-32.h 1 3 4 # 8 /usr/include/gnu/stubs.h 2 3 4 # 360 /usr/include/features.h 2 3 4 # 29 /usr/include/stdio.h 2 3 4 # 1 /usr/lib/gcc/i386-redhat-linux/4.1.2/include/stddef.h 1 3 4 # 214 /usr/lib/gcc/i386-redhat-linux/4.1.2/include/stddef.h 3 4 typedef unsigned int size_t; # 35 /usr/include/stdio.h 2 3 4 # 1 /usr/include/bits/types.h 1 3 4 # 28 /usr/include/bits/types.h 3 4 # 1 /usr/include/bits/wordsize.h 1 3 4 # 29 /usr/include/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; __extension__ typedef signed long long int __int64_t; __extension__ typedef unsigned long long int __uint64_t; __extension__ typedef long long int __quad_t; __extension__ typedef unsigned long long int __u_quad_t; # 131 /usr/include/bits/types.h 3 4 # 1 /usr/include/bits/typesizes.h 1 3 4 # 132 /usr/include/bits/types.h 2 3 4 ... 3.2 编译(compilation) 在这个阶段中Gcc首先要检查代码的规范性、是否有语法错误等以确定代码的实际要做的工作在检查无误后Gcc把代码翻译成汇编语言。可以使用”-S”选项来进行查看该选项只进行编译而不进行汇编生成汇编代码。 Gcc manual中对-S选项的解释如下。 -S Stop after the stage of compilation proper; do not assemble. The output is in the form of an assembler code file for each non-assembler input file specified. By default, the assembler file name for a source file is made by replacing the suffix .c, .i, etc., with .s. Input files that dont require compilation are ignored. 编译后即停止不进行汇编。对于每个输入的非汇编语言文件输出文件是汇编语言文件。 缺省情况下GCC通过用.o替换源文件名后缀.c,.i等以产生目标文件名。可以使用-o选项指定选择其他名字。GCC忽略任何不需要编译的输入文件。 格式gcc –S hello.i –o hello.s 作用将预处理输出文件hello.i汇编成hello.s文件 Hello.i被汇编后的hello.s文件。 .file hello.c .section .rodata .LC0: .string Hello World! via %x/n .text .globl main .type main, function main: leal 4(%esp), %ecx andl $-16, %esp pushl -4(%ecx) pushl %ebp movl %esp, %ebp pushl %ecx subl $20, %esp movl $printf, 4(%esp) movl $.LC0, (%esp) call printf movl $0, %eax addl $20, %esp popl %ecx popl %ebp leal -4(%ecx), %esp ret .size main, .-main .ident GCC: (GNU) 4.1.2 20070925 (Red Hat 4.1.2-33) .section .note.GNU-stack,,progbits 3.3 汇编(assembly) 汇编阶段是把编译阶段生成的.s文件转成二进制目标代码。 gcc manual中对选项-C的解释如下。 -c Compile or assemble the source files, but do not link. The linking stage simply is not done. The ultimate output is in the form of an object file for each source file. By default, the object file name for a source file is made by replacing the suffix .c, .i, .s, etc., with .o. Unrecognized input files, not requiring compilation or assembly, are ignored. 编译或汇编源文件但不连接编译器输出对应于源文件的目标文件。 缺省情况下GCC通过用.o替换源文件名后缀.c, .i, .s等等以产生目标文件名。可以使用-o选项指定选择其他名字。GCC忽略-c选项后面任何无法识别的不需要编译或汇编的输入文件。 gcc manual中对选项-V的解释如下。 -v Print (on standard error output) the commands executed to run the stages of compilation. Also print the version number of the compiler driver program and of the preprocessor and the compiler proper. (在标准错误输出)显示执行编译阶段的命令同时显示编译器驱动程序、预处理器、编译器的版本号。 格式gcc –c hello.s –o hello.o 作用将编译输出的.s文件汇编成二进制目标代码.o文件 我们可以通过objdump程序来查看hello.o的内容。 # objdump -d hello.o hello.o: file format elf32-i386 Disassembly of section .text: 00000000 main: 0: 8d 4c 24 04 lea 0x4(%esp),%ecx 4: 83 e4 f0 and $0xfffffff0,%esp 7: ff 71 fc pushl -0x4(%ecx) a: 55 push %ebp b: 89 e5 mov %esp,%ebp d: 51 push %ecx e: 83 ec 14 sub $0x14,%esp 11: c7 44 24 04 00 00 00 movl $0x0,0x4(%esp) 18: 00 19: c7 04 24 00 00 00 00 movl $0x0,(%esp) 20: e8 fc ff ff ff call 21 main0x21 25: b8 00 00 00 00 mov $0x0,%eax 2a: 83 c4 14 add $0x14,%esp 2d: 59 pop %ecx 2e: 5d pop %ebp 2f: 8d 61 fc lea -0x4(%ecx),%esp 32: c3 ret 3.4 链接(linking) 编译成功后就进入链接。 格式gcc hello.o -o hello.exe 或者gcc hello.o -o hello 作用将编译输出的.o文件链接为最终可执行文件。 同样我们也可以通过objdump程序来查看链接后的输出hello文件的内容。 hello: file format elf32-i386 Disassembly of section .init: 08048298 _init: 8048298: 55 push %ebp 8048299: 89 e5 mov %esp,%ebp 804829b: 83 ec 08 sub $0x8,%esp 804829e: e8 71 00 00 00 call 8048314 call_gmon_start 80482a3: e8 f8 00 00 00 call 80483a0 frame_dummy 80482a8: e8 d3 01 00 00 call 8048480 __do_global_ctors_aux 80482ad: c9 leave 80482ae: c3 ret Disassembly of section .plt: 080482b0 __gmon_start__plt-0x10: 80482b0: ff 35 40 96 04 08 pushl 0x8049640 80482b6: ff 25 44 96 04 08 jmp *0x8049644 80482bc: 00 00 add %al,(%eax) ... 080482c0 __gmon_start__plt: 80482c0: ff 25 48 96 04 08 jmp *0x8049648 80482c6: 68 00 00 00 00 push $0x0 80482cb: e9 e0 ff ff ff jmp 80482b0 _init0x18 080482d0 __libc_start_mainplt: 80482d0: ff 25 4c 96 04 08 jmp *0x804964c 80482d6: 68 08 00 00 00 push $0x8 80482db: e9 d0 ff ff ff jmp 80482b0 _init0x18 080482e0 printfplt: 80482e0: ff 25 50 96 04 08 jmp *0x8049650 80482e6: 68 10 00 00 00 push $0x10 80482eb: e9 c0 ff ff ff jmp 80482b0 _init0x18 ... 080483c4 main: 80483c4: 8d 4c 24 04 lea 0x4(%esp),%ecx 80483c8: 83 e4 f0 and $0xfffffff0,%esp 80483cb: ff 71 fc pushl -0x4(%ecx) 80483ce: 55 push %ebp 80483cf: 89 e5 mov %esp,%ebp 80483d1: 51 push %ecx 80483d2: 83 ec 14 sub $0x14,%esp 80483d5: c7 44 24 04 e0 82 04 movl $0x80482e0,0x4(%esp) 80483dc: 08 80483dd: c7 04 24 d0 84 04 08 movl $0x80484d0,(%esp) 80483e4: e8 f7 fe ff ff call 80482e0 printfplt 80483e9: b8 00 00 00 00 mov $0x0,%eax 80483ee: 83 c4 14 add $0x14,%esp 80483f1: 59 pop %ecx 80483f2: 5d pop %ebp 80483f3: 8d 61 fc lea -0x4(%ecx),%esp 80483f6: c3 ret 80483f7: 90 nop ... 4. 小结 编译程序的4个过程 预处理gcc -E hello.c -o hello.i 编译gcc –S hello.i –o hello.s汇编gcc –c hello.s –o hello.o链接gcc hello.o -o hello 转自:http://blog.csdn.net/livelylittlefish/article/details/5109300