日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

结合hello world探讨gcc编译程序的过程

發(fā)布時間:2023/12/6 编程问答 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 结合hello world探讨gcc编译程序的过程 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

本博客(http://blog.csdn.net/livelylittlefish)貼出作者(三二一@小魚)相關(guān)研究、學(xué)習(xí)內(nèi)容所做的筆記,歡迎廣大朋友指正!

?

?

結(jié)合"hello world"探討gcc編譯程序的過程

?

1. gcc簡介

?

gcc/g++是GNU工程的C和C++編譯器。都要用四個步驟中的一個或多個處理輸入文件。

  • 預(yù)處理(preprocessing)
  • 編譯(compilation)
  • 匯編(assembly)
  • 連接(linking)

?

源文件后綴名標(biāo)識源文件的語言,但是對編譯器來說,后綴名控制著缺省設(shè)定。

gcc命令的一般格式為:gcc [選項(xiàng)]?要編譯的文件?[選項(xiàng)] [目標(biāo)文件]

?

gcc的詳細(xì)內(nèi)容,可參考gcc manual。

?

2. gcc的輸出選項(xiàng)

?

gcc輸出選項(xiàng),-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,該選項(xiàng)不考慮GCC產(chǎn)生什么輸出,無論是可執(zhí)行文件、目標(biāo)文件、匯編文件還是預(yù)處理后的C代碼。

????如果沒有使用`-o'選項(xiàng),默認(rèn)的輸出結(jié)果是:可執(zhí)行文件為a.out,source.suffix的目標(biāo)文件是source.o,匯編文件是source.s,而預(yù)處理后的C代碼送往標(biāo)準(zhǔn)輸出。

?

?

3. "hello wolrd"的處理過程

?

本文以"hello world"程序,探討GCC編譯程序的過程。

?

hello.c文件內(nèi)容如下。

?

#include <stdio.h>

?

int main(int argc, char **argv)

{

????printf("Hello World! via %x/n", printf);

????return 0;

}

?

?

3.1?預(yù)處理(preprocessing)

?

在該階段,編譯器將C源代碼中的包含的頭文件如stdio.h編譯進(jìn)來,可以使用gcc的選項(xiàng)”-E”進(jìn)行查看預(yù)處理結(jié)果。

?

Gcc manual中對-E選項(xiàng)的解釋如下。

?

`-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 don't require preprocessing are ignored.

????預(yù)處理后停止,不進(jìn)行編譯。預(yù)處理后的代碼送往標(biāo)準(zhǔn)輸出。GCC忽略任何不需要預(yù)處理的輸入文件。

?

?

格式:gcc -E hello.c -o hello.i

作用:對hello.c進(jìn)行預(yù)處理輸出為hello.i文件

?

Hello.c被預(yù)處理后的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首先要檢查代碼的規(guī)范性、是否有語法錯誤等,以確定代碼的實(shí)際要做的工作,在檢查無誤后,Gcc把代碼翻譯成匯編語言。可以使用”-S”選項(xiàng)來進(jìn)行查看,該選項(xiàng)只進(jìn)行編譯而不進(jìn)行匯編,生成匯編代碼。

?

Gcc manual中對-S選項(xiàng)的解釋如下。

?

`-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 don't require compilation are ignored.

?????編譯后即停止,不進(jìn)行匯編。對于每個輸入的非匯編語言文件,輸出文件是匯編語言文件。

?????缺省情況下,GCC通過用`.o'替換源文件名后綴`.c',`.i'等以產(chǎn)生目標(biāo)文件名。可以使用-o選項(xiàng)指定選擇其他名字。GCC忽略任何不需要編譯的輸入文件。

?

?

格式:gcc –S hello.i –o hello.s

作用:將預(yù)處理輸出文件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文件轉(zhuǎn)成二進(jìn)制目標(biāo)代碼。

?

gcc manual中對選項(xiàng)-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.

?????編譯或匯編源文件,但不連接,編譯器輸出對應(yīng)于源文件的目標(biāo)文件。

?????缺省情況下,GCC通過用'.o'替換源文件名后綴`.c', `.i', `.s'等等以產(chǎn)生目標(biāo)文件名。可以使用-o選項(xiàng)指定選擇其他名字。GCC忽略-c選項(xiàng)后面任何無法識別的不需要編譯或匯編的輸入文件。

?

?

gcc manual中對選項(xiàng)-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.

????(在標(biāo)準(zhǔn)錯誤輸出)顯示執(zhí)行編譯階段的命令,同時顯示編譯器驅(qū)動程序、預(yù)處理器、編譯器的版本號。

?

?

格式:gcc?–c hello.s?–o hello.o

作用:將編譯輸出的.s文件匯編成二進(jìn)制目標(biāo)代碼.o文件

?

我們可以通過objdump程序來查看hello.o的內(nèi)容。

?

# 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 <main+0x21>

??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)

?

編譯成功后,就進(jìn)入鏈接。

格式:gcc hello.o -o hello.exe

??或者gcc hello.o -o hello

作用:將編譯輸出的.o文件鏈接為最終可執(zhí)行文件。

?

同樣,我們也可以通過objdump程序來查看鏈接后的輸出hello文件的內(nèi)容。

?

?

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 <_init+0x18>

?

080482d0 <__libc_start_main@plt>:

?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 <_init+0x18>

?

080482e0 <printf@plt>:

?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 <_init+0x18>

?

...

?

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?<printf@plt>

?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. 小結(jié)

?

編譯程序的4個過程:

預(yù)處理: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

?

轉(zhuǎn)自:http://blog.csdn.net/livelylittlefish/article/details/5109300

總結(jié)

以上是生活随笔為你收集整理的结合hello world探讨gcc编译程序的过程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。