c++学习(一)程序内部链接三块核心内容
主要内容1.进程的虚拟地址空间内存划分和布局2.函数的调用堆栈详细过程3.程序编译链接原理《深入理解计算机系统》《程序员的自我修养》1.进程的虚拟地址空间内存划分和布局任何的编程语言 -产生两种东西指令和数据可执行文件从磁盘中加载到内存中运行 但是不可能直接加载到物理内存进程的虚拟地址空间x86 32位Linux环境下会给当前进程分配一个2^32大小的一块空间 4G它存在你能看得见他是物理的他存在你看不见他是透明的他不存在你却看得见他是虚拟的他不存在你也看不见他被删除了.text放指令.rodata都是只读.data初始化不为零.bss未初始化或初始化为0未初始化的运行时会变为零.heap堆内存从低地址到高地址线程独有的stack栈空间从高地址到低地址ZONE区域栈和堆之间的匿名映射区用来放动态库、共享内存示例其中123456都会在符号表中产生代码段符号14放在.data中 2356放在.bss中而在函数中abc三个局部变量不会产生符号只是生成指令abc的机器指令放入.text中运行时会在栈上划分空间放指令的值efg三个静态局部变量也放在数据段程序启动时不会初始化程序运行时给值ef放在.datag放在.bss如果打印c将不为0是栈上的无效值g为一定为0《深入理解计算机系统》中示例图从高地址到低地址每一个进程的用户空间是私有的但是内核空间是共享的进程之间的通信方式有哪些匿名管道通信2.深入分析函数的调用堆栈详细过程分析一个例子问题1main函数调用sumsum执行完之后怎么知道回到哪个函数中问题2sum函数执行完回到main以后怎么知道从哪个指令继续运行的函数运行时会在栈帧上开辟空间描述栈的时候有栈顶和栈底就行1.a会产生指令是第一个局部变量放到栈底栈底指针偏移找到指令2.b和ret继续放入3.sum函数开始调用首先压参数从右向左压开辟形参变量b压栈栈顶指针移动继续开辟形参变量a压栈把下一行的指令地址压栈call进入sum开辟栈帧指令入栈栈底地址让栈底指向栈顶让他头指向sum部分为sum函数开辟栈帧空间sub初始化函数部分的栈帧入栈temp把ab计算结果存放到temp中返回temp中的值temp出不去他是局部变量值通过寄存器带出去回退栈帧把sum空间退回数据没有清空出栈并且把sum中栈底内容赋给ebp回到从前main的栈底sum回到main函数4.出栈把出栈的内容放入cpu的pc寄存器中下一行要执行指令的地址来运行下一行指令5.把刚刚压栈的ab形参变量返回6.把寄存器中temp的值放到return中返回给main注意4字节 通过eax寄存器带出来4 8 eax edx寄存器带出来8 产生临时量带出返回值3.c代码编译链接原理用Linux系统学习理解以下为main函数和sum函数发生过程以及应该注意的问题注意1.编译的时候分开编译链接的时候一块链接2.#pragma lib需要链接的库#pragma link指定入口函数不在预编译中进行在链接阶段3.编译阶段语义分析语法分析代码优化4.生成汇编指令汇编中生成机器码二进制文件5.xxx.exe是win的 a.out是linux的6. .o文件是由各种段组成的7.可执行文件a.out 有一个program headers段 有两个load把哪些内容加载到内存当中符号与引用查看符号表引用的函数和数据也会产生符号gdata和sum在示例main函数中产生符号*UND*对于链接器来说只能看见g的符号不能看见l的l的符号在当前文件能查看g的符号在其他文件也能看见编译过程中符号是不分配虚拟地址的在链接过程中分配查看地址与指令地址是0所以.o文件无法运行链接1.合并所有的.o文件的各个段开始进行合并2.符号解析所有对符号表的引用都要找到该符号定义的地方*UND*的符号在别的文件找到定义的地方如.text .data可能会报错符号未定义符号重定义3.符号的重定向给所有的符号分配虚拟地址现在有地址了可执行文件加载过程