【编程基础】C函数的调用过程

这几天在看GCC Inline Assembly,在C代码中通过asm或__asm__嵌入一些汇编代码,如进行系统调用,使用寄存器以提高性能能,需要对函数调用过程中的堆栈帧(Stack Frame)、CPU寄存器、GCC inlie assembly等了如指掌。现在看看函数调用过程吧。

1. Linux 进程虚拟地址空间

以32位操作系统为例,下面是Linux进程地址空间布局:

32位虚拟地址空间的高1GB的空间是留给操作系统内核的,栈由高地址到低地址向下增长,堆由低地址到高地址向上增长。

C中如 malloc 等分配的内存在堆中分配。初始化了的静态变量和全局变量放在Data段中。未初始化的全局变量和局部静态变量放在Bss段中,更准确的说是在Bss段为它们预留了空间。非静态局部变量是在函数调用过程中暂存在栈上的。

2. 函数的堆栈帧

栈在程序运行中具有举足轻重的地位。最重要的,栈保存了一个函数调用所需要的维护信息,被称为堆栈帧(Stack Frame),一个函数(被调函数)的堆栈帧一般包括下面几个方面的内容:

(1) 函数参数,默认调用惯例情况下从右向左的顺序依次把参数压入栈中。由函数调用方执行。

(2) 函数的返回地址,即调用方调用此函数(如call func1)的下一条指令的地址。函数调用方(call指令)执行。

(3) 保存调用方函数的EBP寄存器,即将调用方函数的EBP压入堆栈,并令EBP指向此栈中的地址:pushl %ebp; movl %esp, %ebp。由被调函数执行。

(4) 上下文:保存在函数调用过程中需要保持不变的寄存器(函数调用方的),如ebx,esi,edi等。由被调函数执行。

(5) 临时变量,如非静态局部变量。

下面是一个函数的堆栈帧结构图:

压入函数参数和返回地址的过程是由函数调用方在调用函数之前将其压入栈中,每个函数执行后首先要执行的就是把函数调用方的EBP寄存器压入栈中,之后是在栈上开辟一些空间存放局部变量,最后把要保存的寄存器压入栈中。

文章摘自csdn:songuo's home s home

原文发布于微信公众号 - 程序员互动联盟(coder_online)

原文发表时间:2015-06-16

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏程序你好

Java集合对象如何进行内存优化

752
来自专栏瓜大三哥

Yaffs_guts

Yaffs_guts ? 1.Chunk的读写擦除 2.文件地址映射 3.文件系统对象 1.Chunk的读写擦除 我们知道,NAND Flash的基本擦除单位是...

18210
来自专栏Java3y

JVM如何从入门到放弃的?

JVM在准备面试的时候就有看了,一直没时间写笔记。现在到了一家公司实习,闲的时候就写写,刷刷JVM博客,刷刷电子书。

1010
来自专栏圣杰的专栏

线程安全知多少

1. 如何定义线程安全 线程安全,拆开来看: 线程:指多线程的应用场景下。 安全:指数据安全。 多线程就不用过多介绍了,相关类型集中在System.Thread...

3215
来自专栏老司机的简书

老司机读书笔记——Effective Objective-C 2.0阅读笔记

比方说,在循环中不断地创建的临时对象。即便这些对象在调用完方法之后就就不在使用了,他们也依然处于存活状态,因为目前还在自动释放池里,等待系统稍后将其释放并回收。...

592
来自专栏Golang语言社区

Golang语言--资源自动回收技术

Go语言作为一个现代化的编程语言以及支持垃圾内存的自动回收特性(GC). 我们现在关注的是非内存资源的自动回收技术. 局部资源的管理 在讨论Go语言解决方案之前...

3558
来自专栏积累沉淀

Java设计模式(八)----代理模式

代理描述 1.生活中: 代理就是一个人或者一个组织代表其他人去做一件事的现实生活中的。在一些情况下,一个客户不想或者不能够直接引用一个对...

1789
来自专栏专注 Java 基础分享

基于 JDK 的动态代理机制

624
来自专栏技术墨客

JVM与字节码——类的方法区模型 原

这是一段平凡得不能再平凡的Java代码,稍微有点编程语言入门知识的人都能理解它表达的意思:

502
来自专栏Linyb极客之路

工作流引擎之activiti入门

在解释activiti之前我们看一下什么是工作流。 工作流(Workflow),就是“业务过程的部分或整体在计算机应用环境下的自动化”,它主要解决的是“使在多个...

804

扫描关注云+社区