1.C++编译链接运行原理

预编译(.i)

1.删除#define 文本替换

2.处理#include 递归展开

3.处理#if #endif 等预编译指令

4.删除注释

5.添加行号和文件标识

6.保留#pragma

编译(.s)

1.词法分析

2.语法分析 一行表达式

3.语义分析 结合上下文

4.代码优化

5.生成汇编指令 低级语言

**汇编(.o)**目标文件 可重入的二进制文件

1.翻译指令 (把低级语言翻译为机器语言)

链接(.exe) 能运行 可执行文件

数据段(.data 和 .bss)存放数据的区别

1…data 已初始化且初始化不为0的数据

2…bss 未初始化或初始化为0的数据

#include<stdio.h>

int gdata1 = 10;//全局变量生成的都是数据 数据都在数据段存放 .data段
int gdatal = 0;//.bss段
int gdata3;//.bss段
static int gdata4 = 20;//静态的全局变量也是数据 .data段
static int gdata5 = 0;//.bss段
static int gdata6;//.bss段

int main()//函数名生成的是指令  .text段
{
    static int ldata = 30;//静态局部变量生成的也是数据 .data段
    static int ldata2 = 0;//.bss段
    static int ldata3;//.bss段
    
    int ldata4 = 40;//普通局部变量生成的是指令 .text段
    int ldata5 = 0;//.text段
    int ldata6;//.text段
    return 0;
}

问题1:汇编过程 int ldata = 20 是在text段,而不在stack区?

运行前 所有东西都在文件中

运行后 程序才在内存中 栈是内存区域

问题2:汇编后,文件中存在什么内容?

1.汇编阶段 bss少了4个字节 1个数据 少了那个数据 为什么?

​ gdata3在comment段
gdata3在comment段 因为预编译、编译、汇编阶段都是对源文件进行处理

​ 这里涉及到强弱符号的问题。而强弱符号是在链接阶段处理的

​ 静态的全局变量和静态的局部变量没有强弱符号一说,因为静态文件仅本文件可见

​ 举例:

​ 因为在汇编阶段,编译器对test.c的源文件进行处理时是看不见main.c的源文件的

​ 所以在对test.c的源文件处理时,虽然int a是弱符号,但是编译器不能确定其他源文件中是否存在强符号,所以编译器没有把该弱符号放进.bss段,而是暂时存放在comment段,若当汇编对所有源文件处理完后,进行链接的时候,没有发现其他强符号,在将该弱符号从comment段取出。相反,如果其他源文件存在强符号,那么该弱符号就依旧存在comment段

2.bss段不存在?为什么?信息从哪里来?REL布局
.o的布局,数据和指令存放的位置。指令数据生成的符号存放位置和属性

文件 虚拟地址空间映射 方便映射

文件标识 main.c

段信息 .text .data .bss

数据 gdata1 gdata3

函数 main()

//main.c
#include<stdio.h>

short a = 10;//强符号
short b = 20;

int main()
{
    func();
    printf("a:%d\n",a);
    printf("b:%d\n",b);
    return 0;
}
//test.c
int a;//弱符号

void func()
{
    a = 30;
}

强弱符号(是在链接阶段处理的)

强符号

​ 已初始化的符号

弱符号

​ 未初始化的符号

强弱符号的规则

1.两强符号 报错

2.一强一弱 选强符号做最终处理

3.两弱符号 谁先编译就选谁 或 编译器报错

注:静态的全局变量和静态的局部变量没有强弱符号一说,因为静态文件仅本文件可见

#include<stdio.h>

int gdata1 = 10;//全局变量生成的都是数据 数据都在数据段存放 .data段
int gdatal = 0;//.bss段
int gdata3;//.bss段
static int gdata4 = 20;//静态的全局变量也是数据 .data段
static int gdata5 = 0;//.bss段
static int gdata6;//.bss段

char* p = "hello";//error
/*
     char* 4个字节    hello+\0 六个字节
*/

int main()//函数名生成的是指令  .text段
{
    static int ldata = 30;//静态局部变量生成的也是数据 .data段
    static int ldata2 = 0;//.bss段
    static int ldata3;//.bss段
    
    int ldata4 = 40;//普通局部变量生成的是指令 .text段
    int ldata5 = 0;//.text段
    int ldata6;//.text段
    return 0;
}

问题:hello存放的位置在哪里?

在.rodata read-only data 只读数据段

常量的字符串都在只读数据段存储

以下是链接阶段

汇编阶段那些事情没做处理

1.强弱符号处理

2.外部符号 符号表

3.虚假地址 虚假偏移 指令段

//main.c
#include<stdio.h>

int gdata1 = 10;//全局变量生成的都是数据 数据都在数据段存放 .data段
int gdatal = 0;//.bss段
int gdata3;//.bss段
static int gdata4 = 20;//静态的全局变量也是数据 .data段
static int gdata5 = 0;//.bss段
static int gdata6;//.bss段

extern int gdata;//申明有个外部的全局变量
extern int Sum(int,int);//申明有个外部的函数

int main()//函数名生成的是指令  .text段
{
    static int ldata = 30;//静态局部变量生成的也是数据 .data段
    static int ldata2 = 0;//.bss段
    static int ldata3;//.bss段
    
    int ldata4 = 40;//普通局部变量生成的是指令 .text段
    int ldata5 = gdata;
    int ldata6 = Sum(ldata4,ldata5);
    return 0;
}
//test.c
int gdata = 1000;
int Sum(int a,int b)
{
    return a + b ;
}

问题:为什么不把gdata放在.data段,为什么不把Sum放在.text段,而是把它们放在UND(未定义区)?

extern int gdata;//申明有个外部的全局变量
extern int Sum(int,int);//申明有个外部的函数

.o下不知道gdata和Sum的定义点,所以只能将gdata和Sum暂时放在放在未定义区
在这里插入图片描述
问题:根据第11行,a1后面的应该是gdata的地址,gdata能在0x0000 0000开辟空间存放吗?为什么用虚假的地址代替gdata真实的地址呢?

gdata不能再0x0000 0000,因为最终进行映射的时候是在保留区的,所以a1后面的地址是gdata的虚假地址

现在还没有链接,我们看的是目标文件的东西,看的是指令段,针对gdata来说,是外部符号,我们不知道他的定义点在哪里,所以无法得知gdata的真实地址,所以只能用一个虚假的地址做一个替换
在这里插入图片描述
call指令:函数调用指令 近址相对位移 调用指令

近址:下一行指令得地址

问题:调用Sum函数 得知道Sum函数入口地址,那么如何得知函数入口地址?

近址 + 相对位移 = 函数的入口地址

ff ff ff fc = -4

2E + ff ff ff fc = 2A

而0xFF FF FF FC是内核地址,只有操作系统可以操纵,所以这也是虚假的地址。因为Sum()的定义点看不到,所以用一个虚假的地址去代替真实的地址
汇编阶段没有处理的:**

1.强弱符号

2.符号表 外部符号处理

3.指令段 虚假地址和虚假偏移

在这里插入图片描述

链接阶段处理的:

1.合并段和符号表 强弱符号

2.符号解析

3.分配地址和空间 程序和虚拟地址空间的映射

4.符号的重定位

处理UND区域符号

​ 通过声明找到定义的位置

符号解析

​ 在符号引用的地方找到符号定义的地方
在这里插入图片描述
在这里插入图片描述

进程

运行

1.建立虚拟地址空间和物理内存的映射(创建内核映射结构体),创建页目录页表

2.加载指令和数据

3.把入口地址放在下一行指令寄存器

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值