程序的生命周期:从.c文件到二进制文件

一个.c文件是如何成为一个可执行二进制文件的?

文件后缀被执行过程工具细节
.c预处理预处理器(cpp,c pre-processor)宏替换、头文件展开、注释删除
.i编译cclC语言程序转化为汇编语言程序(.s)
.s汇编编译器汇编语言程序转化可重定位目标文件(.o)
.o链接ld(链接器)将多个.o文件链接为一个可执行文件

在这里插入图片描述

预处理

使用cpp(C 预处理器)完成了:

  • 将.c文件转化为.i文件
    • 在这里.i文件只是一个后缀而已,本质上仍然是文本文件
  • 宏替换
  • 头文件展开
    • 找到#include的文件内容将其插入到.c文件中
  • 注释删除

将hello.c文件得到的预处理结果重定向到hello.i

cpp hello.c > hello.i

可以使用man cpp得到预处理器的相关信息

测试代码:

#include <string.h>
#include <sys/syscall.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
    char *msg = "Hello, world!\n";
    syscall(SYS_write, 1, msg, strlen(msg));

    return 0;
}

编译

  • 使用编译器将.i文件转换为.s文件
  • 将C语言文本转换为汇编语言文本(Assembly Code)
  • 命令: gcc hello.i -S -o hello.s
        .file   "hello.c"
        .text
        .section        .rodata
.LC0:
        .string "Hello, world!\n"
        .text
        .globl  main
        .type   main, @function
main:
.LFB0:
        .cfi_startproc
        endbr64
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        subq    $32, %rsp
        movl    %edi, -20(%rbp)
        movq    %rsi, -32(%rbp)
        leaq    .LC0(%rip), %rax
        movq    %rax, -8(%rbp)
        movq    -8(%rbp), %rax
        movq    %rax, %rdi
        call    strlen@PLT
        movq    %rax, %rdx
        movq    -8(%rbp), %rax
        movq    %rdx, %rcx
        movq    %rax, %rdx
        movl    $1, %esi
        movl    $1, %edi
        movl    $0, %eax
        call    syscall@PLT
        movl    $0, %eax
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE0:
        .size   main, .-main
        .ident  "GCC: (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0"
        .section        .note.GNU-stack,"",@progbits
        .section        .note.gnu.property,"a"
        .align 8
        .long    1f - 0f
        .long    4f - 1f
        .long    5
0:
        .string  "GNU"
1:
        .align 8
        .long    0xc0000002
        .long    3f - 2f
2:
        .long    0x3
3:
        .align 8
4:
.file源文件
.text代码段
.global全局变量
.data存放已经初始化的全局和静态C 变量
.section .rodata存放只读变量
.align对齐方式
.type表示是函数类型/对象类型
.size表示大小
.long .string表示是long类型/string类型

汇编

  • 编译器将汇编语言程序转化为可重定位目标文件
  • .s —> .o 指令为gcc -c hello.s -o hello.o
  • objdump 分析hello.o:objdump -d hello.o

链接

将多个.o文件链接为一个可执行文件

关于链接器的更多内容:man ld

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值