`
spartan1
  • 浏览: 360325 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

x86系统C语言函数调用时的内存分布

 
阅读更多

好久不用,很多内容都忘了。刚刚复习了一下,再写一遍:32位x86系统C函数调用时的内存分布。

 

每个C语言函数在运行过程中,在栈顶对应一个栈帧。想想堆栈是一个地址由上往下增长的线性内存(为什么要由上往下增长?后面说明),栈帧的顶端地址位于esp寄存器,栈帧底部地址由ebp寄存器保存(当然,这个说法不准确,ebp再往下还有这个函数的参数,后面详细说明)。结构如下所示(每行4字节):

 

00  临时变量2                               <---- esp

04  临时变量1

08  局部变量2

0C  局部变量1

10  调用函数ebp指针值                  <---- ebp

14  调用函数下一条执行指令地址

18  参数1

1C  参数2

可以看出,esp指向栈顶,ebp指向调用函数的ebp值: *esp = (first temp variable), *ebp = (last function's ebp),第一个参数是*(ebp+8),上一个函数中的返回指令是*(ebp+4)

 

在函数调用前,esp指向参数1(0x18),执行call命令后,esp指向调用函数下一条执行指令地址(0x14),被调用函数首先执行如下指令:

pushl %ebp
movl  %esp, %ebp

 

此时 esp=ebp=0x10。

 

 ok,回到刚才的问题,为什么要从上往下想象地址空间。这种想象地址空间的能力非常重要,这个搞不好,在学汇编和读汇编时会比较郁闷。

 

一般我们想象一个栈的时候,要么从上往下增长,要么从下往上增长,或者从左往右、从右往左增长。不过一般push时我们感觉是“压进去”,pop时感觉是“弹出来”,这样从上往下增长的话,感觉比较怪异:往上面压进去,从上午往下弹出来。而水平压进去、弹出来的话,展示栈中的内容展示不了多少,因为栈中数字一般是四字节(对于32位系统)一个数据,水平写栈中内容的话可能就是如下的样子:

0x12345678  0x87654321  0x12345678  0x87654321  0x12345678  0x87654321 

 

一行写不了几个数据,并且还看着比较不舒服。所以,栈从下往上涨是想起来最舒服的。

 

而内存空间为什么地址从上往下依次增大想象起来更舒服一些呢?首先,栈一般都是从大地址往小地址增长的,按照栈从下往上增长的方向,内存地址当然要从上往下增长了。另外,C语言中的结构(struct)都是从上往下写的,而一般上面的地址比下面的地址要小,更靠前,因此地址从上往下想时也更加符合平时看着的习惯。

分享到:
评论

相关推荐

    C语言函数调用机理(ppt课件)

    以Intel x86系列CPU为例子。讲解详细深入。看完后C语言水平能够进入一个新台阶。

    x86平台实现的printf函数

    x86平台实现的printf函数

    C语言讲义.doc

    1.9 SYSTEM系统调用 15 1.9.1 System返回值在windows和unix下的不同, 15 1.9.2 POSIX 15 1.10 C语言编译过程,GCC参数简介 16 1.10.1 C语言编译过程 16 1.10.2 -E预编译 16 1.10.3 -S汇编 16 1.10.4 -c编译 16 1.10.5...

    快速入门汇编语言-非常详细且系统地介绍x86-64汇编语言的文.md

    5. 重点介绍了函数调用中栈帧的使用 6. 使用很多配图辅助说明 总的来说,这是一篇写得非常好的有关x86_64汇编语言入门的长文,对于想要学习汇编语言的人来说是非常适合的读物,能从中获得系统和全面的基础知识。文章...

    Linux内核源代码情景分析 (上下册 高清非扫描 )

    4.3 系统调用fork()、vfork()与clone() 4.4 系统调用execve() 4.5 系统调用exit()与wait4() 4.6 进程的调度与切换 4.7 强制性调度 4.8 系统调用nanosleep()和pause() 4.9 内核中的互斥操作 第5章 ...

    Visual Studio 2022封装C代码为x64和x86平台动态库示例程序

    内容概要:介绍如何使用Visual Studio 2022将C语言函数封装成x64和x86平台上使用的动态链接库(dll文件)并生成对应的静态链接库(lib文件),以及如何在C++程序中调用生成的dll。 适合人群:使用Visual Studio进行C++...

    linux 内核源代码分析

    4.3 系统调用fork()、vfork()与clone() 4.4 系统调用execve() 4.5 系统调用exit()与wait4() 4.6 进程的调度与切换 4.7 强制性调度 4.8 系统调用nanosleep()和pause() 4.9 内核中的互斥操作 第5章 文件...

    linux内核源代码情景分析

    第3章 中断、异常和系统调用 3.1 X86 CPU对中断的硬件支持 3.2 中断向量表IDT的初始化 3.3 中断请求队列的初始化 3.4 中断的响应和服务 3.5 软中断与Bottom Half 3.6 页面异常的进入和返回 3.7 时钟中断 3.8...

    vld(Visual Leak Detector 内存泄露检测工具 源码)

     得到当前的堆栈的二进制表示并不是一件很复杂的事情,但是因为不同体系结构、不同编译器、不同的函数调用约定所产生的堆栈内容略有不同,要解释堆栈并得到整个函数调用过程略显复杂。不过windows提供一个StackWalk...

    宋劲彬的嵌入式C语言一站式编程

    1. 单步执行和跟踪函数调用 2. 断点 3. 观察点 4. 段错误 11. 排序与查找 1. 算法的概念 2. 插入排序 3. 算法的时间复杂度分析 4. 归并排序 5. 线性查找 6. 折半查找 12. 栈与队列 1. 数据结构的概念 2. 堆栈 3. ...

    LINUX内核源代码情景分析

    2.12 系统调用brk() 2.13 系统调用mmap() . 第3章 中断、异常和系统调用 3.1 X86 CPU对中断的硬件支持 3. 2 中断向量表IDT的初始化 3. 3 中断请求队列的初始化 3. 4 中断的响应和服务 3. 5 软中断与...

    Linux内核情景分析(非扫描版)

    第3章 中断、异常和系统调用 3.1 X86 CPU对中断的硬件支持 3. 2 中断向量表IDT的初始化 3. 3 中断请求队列的初始化 3. 4 中断的响应和服务 3. 5 软中断与Bottom Half 3.6 页面异常的进入和返回 3. 7 时钟中断 3. 8...

    Linux内核情景分析

    第3章 中断、异常和系统调用 3.1 X86 CPU对中断的硬件支持 3. 2 中断向量表IDT的初始化 3. 3 中断请求队列的初始化 3. 4 中断的响应和服务 3. 5 软中断与Bottom Half 3.6 页面异常的进入和返回 3. 7 时钟中断 3. 8...

    LINUX内核源代码情景分析(上).part1.rar

    2.12 系统调用brk() 2.13 系统调用mmap() . 第3章 中断、异常和系统调用 3.1 x86 cpu对中断的硬件支持 3. 2 中断向量表idt的初始化 3. 3 中断请求队列的初始化 3. 4 中断的响应和服务 3. 5 软中断与...

    清华大学Linux操作系统原理与应用

    6.1 系统调用与应用编程接口、系统命令、内核函数的关系 133 6.1.1 系统调用与API 133 6.1.2 系统调用与系统命令 134 6.1.3 系统调用与内核函数 134 6.2 系统调用处理程序及服务例程 135 6.2.1 初始化系统调用 136 ...

    Linux内核情景分析(二级标题).pdf

    第3章 中断、异常和系统调用 第4章 进程与进程调度 第5章 文件系统 第6章 传统的Unix进程间通信 第7章 基于socket的进程间通信 第八章 设备驱动 第9章 多处理器的SMP系统结构 第10章 系统的引导和初始化

    ARM、PowerPC、MIPS反汇编工具V1.24.00

    V1.24.00相对上一版本,进一步完善COREDUMP文件解析与应用,提供堆栈调用关系分析;V1.23.03相对上一版本,提供32位X86反汇编;V1.23.02相对上一版本,提供源代码行查询指令地址,OBJ/COREDUMP文件解析,sprintf函数...

    Linux编程从入门到精通

    附录 以字母顺序排列的系统调用 315 第四部分 Linux内核概念系统结构 摘要 323 前言 324 第1章 系统结构 325 1.1 系统概述 325 1.2 内核的目标 325 1.3 内核结构的概述 325 1.4 支持多个开发人员 327 1.5 系统数据...

    计算机系统2018B-答案1

    1. C 语言中整数-1 与无符号 0 比较,其结果是( A ) 2. 在 x86-64 系统中,调用函数 int gt (long x, long y)时,保

    Windows内核安全与驱动开发光盘源码

    2.4 函数调用 25 2.4.1 查阅帮助 25 2.4.2 帮助中有的几类函数 26 2.4.3 帮助中没有的函数 28 2.5 Windows的驱动开发模型 29 2.6 WDK编程中的特殊点 30 2.6.1 内核编程的主要调用源 30 2.6.2 函数的多线程...

Global site tag (gtag.js) - Google Analytics