编译、链接到载入、运行的大致过程 ----1. 编译

2020-06-08 12:15:23 浏览数 (1)

对于需要编译的编程语言(c, c , java, c# ...高级语言),源码写完后,是无法直接运行的;需要有 编译,链接的过程才能生成最终可以执行的二进制文件;

编译:

编译的过程通常包含: A. 预编译过程,就是在源代码中进行文本替换工作,比如c中的#include的替换,以及宏定义的替换等;最终输出的依然是 普通的文本文件;在Linux中使用gcc可以用如下命令获得预编译的结果:

代码语言:javascript复制
[root@www ~]# cat hello.c         #查看hello.c的源代码;
#include <stdio.h>
int main() {
printf("Hello,2020 !n");
}
[root@www ~]# gcc -E hello.c -o hello.i      #手动生成预编译文件hello.i , -E 参数表示 预编译完成后停止继续编译,所以可以通过 -E 参数获得预编译的结果;
[root@www ~]# ls | grep hello
hello.c
hello.i
[root@www ~]# 

B. 编译过程, 这个过程是把预编译的结果进行转换,从而获得对应的汇编语言;

代码语言:javascript复制
[root@www ~]# gcc -S hello.i -o hello.s        #手动把预编译的结果 编译为汇编语言;-S 表示 编译为汇编语言后停止后续的编译操作,所以可以获得源代码对应的汇编语言代码;
[root@www ~]# ls | grep hello
hello.c   # 这个是源代码文件
hello.i     #这个是预编译结果的文件;
hello.s    #这个是汇编语言的代码
[root@www ~]# cat hello.s        #查看汇编语言的代码
    .file   "hello.c"
    .section    .rodata
.LC0:
    .string "Hello,2020 !"
    .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, �i
    call    puts
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-39)"
    .section    .note.GNU-stack,"",@progbits
[root@www ~]# 

C. 汇编过程,该过程把上述的汇编代码(hello.s) 转变成机器码;这一过程可以用如下的步骤来完成:

代码语言:javascript复制
[root@www ~]# as hello.s -o hello.obj   #as 命令是用来将汇编语言转变成机器码的;目标文件是hello.obj
[root@www ~]# ls | grep hello
hello.c
hello.i
hello.obj
hello.s
[root@www ~]# file hello*
hello.c:   C source, ASCII text        
hello.i:   C source, ASCII text
hello.obj: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped      #目标文件是一个elf格式的二进制文件;
hello.s:   ASCII text
[root@www ~]# 
NOTE:

上面的步骤手动展示了编译的大概过程(预编译--->编译--->汇编),而在实际使用的时候,并不是这样一步步进行操作的(也不需要这样一步步进行操作),linux 下用 gcc -c hello.c -o hello.obj 这样的方式一步到位来完成编译(一般的IDE集成开发环境,直接点击"编译"按钮就完成了), 其隐藏了上述编译的步骤, 直接输出编译的结果;

0 人点赞