一、虚拟地址空间布局
1、.text段(代码段)
用于存放程序执行代码,可共享,频繁执行的程序在内存中拷贝一份就可以。代码段属于只读,防止其他操作意外的修改对代码段的操作。
代码段指令根据程序设计流程依次执行,对于顺序指令,只会执行一次(每个进程);若有反复,则需使用跳转指令;若进行递归,则需要借助栈来实现。
2、数据段(分为.data段和.bss段)
1).data段(属于静态内存分配,可读可写)
已初始化且初始化值不为0的全局变量、静态全局变量。
数据段保存在目标文件中,初始化通常由程序初始化。
2).bss段
未初始化且初始化值为0 的全局变量、静态全局变量。
.bss与.data段的区别:
1)BSS段不占用物理文件尺寸,但占用内存空间;数据段占用物理文件,也占用内存空间。
2)当程序读取数据段的数据时,系统会出发缺页故障,从而分配相应的物理内存;当程序读取BSS段的数据时,内核会将其转到一个全零页面,不会发生缺页故障,也不会为其分配相应的物理内存。
二、编译链接运行原理
链接:把各个模块之间相互引用的部分都处理好,使得各个模块之间能正确的衔接。分配地址和空间
汇编指令:
MOV
LEA eax,[ebp-4]; //装入有效地址
Push eax ; //压栈
Pop eax ; //从栈中恢复保存eax的值
Add eax, 4 ;//eax = eax+4
Sub eax , 4 ; //eax = eax-4
Call :
- 压入下一行指令地址
- Jmp(栈帧跳转到jmp)
寄存器:
Eax , ebx, ecx, edx
Pc(下一行指令寄存器)
Ebp(栈底指针寄存器)
Esp(栈顶指针寄存器)
函数堆栈调用开栈过程:
1.压入实参,自右向左
2.压入下一行指令地址
3.压入调用方函数的栈底地址
4.调转到被调用方函数栈帧
5.开辟被调用方函数所需要运行的空间
问题:
- 形参有没有开辟内存?谁开辟的?
开辟内存:调用方开辟;
清理内存:调用方清理。