编译连接与函数调用过程

本文详细阐述了代码从编译到执行的过程,包括编译链接生成二进制文件、虚拟地址空间的分配、函数调用的参数传递和返回值处理。在32位系统中,虚拟地址空间为4GB,由用户空间和内核空间组成。函数调用涉及参数入栈、栈帧开辟、返回值返回及栈退出等步骤,对于不同大小的参数和返回值有不同的处理策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

编译链接 

 代码--编译-->二进制可重定位文件--链接-->二进制可执行文件--执行-->为进程分配虚拟地址空间--地址映射-->内存/IO磁盘

虚拟地址空间:以32位操作系统为例,给每个进程划分一个执行空间,大小4G。其中3G为用户空间,1G为内核空间。

32位系统的虚拟地址空间为什么是4G?

一共有32条地址总线能标志的最小地址0000 0000,能标志的最大空间ffff ffff。2^32=4G,也就是能表示的最大范围。

 编译在单文件进行,链接在多文件进行

编译链接详解

 

数据的存储 / 数据段:(上图中数据与指令中的数据)

. bss段存储没有初始化或者初始化为0的数据

.data段存储初始化且初始化值不为0的数据

 

函数调用过程

参数入栈  ->  函数栈帧开辟  ->  返回值返回  ->  函数栈退出

1.参数入栈(小于等于8,大于8)


4字节参数入栈   
顺序  从右向左
方式  使用寄存器push带入

8字节参数入栈
顺序   从右向左
方式   使用寄存器push带入

>8

12字节参数入栈
顺序   从右向左
方式   先在栈顶开辟足够该参数的空间,之后将数据复制进去

c++ 中只要是自定义类型,无论多大字节,都采用先开辟空间,之后赋值的方式



2.函数栈帧开辟


调用方函数(我调用其他函数,我是调用方)的下一行指令地址入栈
将调用方函数的栈底寄存器入栈
让ebp=esp
让esp=esp-***    (在栈里面,减是向低地址增长)
将其他使用的寄存器入栈
将新开辟的栈帧空间中全部写为ccccccccc



3.返回值返回(小于等于8,大于8)


4字节返回值
方式:将返回值放入寄存器带回

8字节返回值
方式:将返回值放在两个寄存器,带回

>8字节

12字节返回值:
方式:
函数参数入栈之后入栈一个地址。地址是调用方栈帧上的地址(是靠近调用方函数栈帧的栈顶的位置)(调用方指的是调用其他函数的一方)
在返回值返回的时候,将返回数据写入到上面入栈的调用方地址上
返回之后,将从该地址上将数据取出

c++中,自定义类型都按照入栈调用方地址的方式


4.函数栈退出


进行当前函数栈帧的校验
将线程保护的寄存器出栈
让esp=ebp
ebp= pop
将下一行指令的地址还原
清除参数

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值