首页 > 系统相关 >10.10临时确保局部变量用的内存空间

10.10临时确保局部变量用的内存空间

时间:2023-02-07 20:33:20浏览次数:42  
标签:esp 局部变量 内存空间 编译器 ebp 寄存器 10.10

为什么局部变量只能在定义该变量的函数内进行参阅呢?这是因为,局部变量是临时保存在寄存器和栈中的。正如本章前半部分讲的那样,函数内部利用的栈,在函数处理完毕后会恢复到初始状态,因此局部变量的值也就被销毁了,而寄存器也可能会被用于其他目的。因此,局部变量只是在函数处理运行期间临时存储在寄存器和栈上。

在代码清单 10-6 中定义了 10个局部变量。这是为了表示存储局部变量的不仅仅是栈,还有寄存器。为确保 cl~c10 所需的领域,寄存器空闲时就使用寄存器,寄存器空间不足的话就使用栈。

下面让我们来看一下代码清单 10-7 中 TEXT 段定义的内容。(7)表示的是 MyFunc 函数的范围。在 MyFunc 函数中定义的局部变量所需要的内存领域,会被尽可能地分配在寄存器中。大家可能会认为用高性能的寄存器来代替普通的内存是很奢侈的事情,不过编译器不会这么认为、只要寄存器有空间,编译器就会使用它。因为与内存相比使用寄存器时访问速度会高很多,这样就可以更快速地进行处理。局部变量利用寄存器,是 Borland C++ 编译器最优化的运行结果。旧的编译器没有类似的最优化功能,局部变量就可能会仅仅使用栈。

代码清单中的(8)表示的是往寄存器中分配局部变量的部分。仅仅对局部变量进行定义是不够的,只有在给局部变量赋值时,才会被分配到寄存器的内存区域。(8)就相当于给 5 个局部变量 c1~c5 分别赋予数值1~5这一处理。eax、edx、ecx、ebx、esi是 Pentium 等x86系列 32位CPU 寄存器的名称(参考表 10-2)。至于使用哪一个寄存器则要由编译器来决定。这种情况下,寄存器只是被单纯地用于存储变量的值,和其本身的角色没有任何关系。

x86 系列 CPU 拥有的寄存器中,程序可以操作的有十几个。其中空闲的,最多也只有几个。因而,局部变量数目很多的时候,可分配的寄存器就不够了。这种情况下,局部变量就会申请分配栈的内存空间。虽然栈的内存空间也是作为一种存储数据的段定义来处理的,但在程序各部分都可以共享并临时使用这一点上,它和 DATA 段定义及BSS 段定义在性质上还是有些差异的。例如,在函数入口处为变量申请分配栈的内存空间的话,就必须在函数出口处进行释放。否则,经过多次调用函数后,栈的内存空间就会被用光了。

在(8)这一部分中,给局部变量 c1~c5 分配完寄存器后,可用的寄存器数量就不足了。于是,剩下的 5 个局部变量 c6~c10 就被分配了栈的内存空间,如(9)所示。函数入口(10)处的 add esp,-20 指的是对栈数据存储位置的 esp 寄存器(栈指针)的值做减 20 的处理。为了确保内部变量 c6~c10 在栈中,就需要保留 5个int类型的局部变量(4字节 x5 = 20字节)所需的空间。(11)中的 mov ebp,esp 这一处理指的是把当前 esp 寄存器的值复制到 ebp 寄存器中。之所以需要(11)这一处理,是为了通过在函数出口处的(12)这一 move esp,ebp 的处理,把 esp 寄存器的值还原到原始状态,从而对申请分配的栈空间进行释放,这时栈中用到的局部变量就消失了。这也是栈的清理处理。在使用寄存器的情况下,局部变量则会在寄存器被用于其他用途时自动消失(图 10-6)。

 

 (9)中的 5 行代码是往栈空间中代人数值的部分。由于在向栈申请内存空间前,借助 mov ebp,esp 这个处理,esp 寄存器的值被保存到了 ebp 寄存器中,因此,通过使用[ebp - 4]、[ebp - 8]、[ebp - 12]、[ebp - 16]、[ebp - 2] 这样的形式,就可以将申请分配的 20 字节的栈内存空间切分成5个长度分别是4字节的空间来使用(图 10-7)。例如(9)中的 mov dword ptr [ebp - 4],6 表示的就是,从申请分配的内存空间的下端(ebp 寄存器指示的位置)开始往前4字节的地址([ebp - 4]中,存储着6这一4字节的数据。

 

 关于往全局变量中代人局部变量的数值这一内容,这里不再进行说明。这时可能有读者会产生疑问,既然不进行说明,那为什么代码清单 10-6 中没有省略掉该部分呢?这是为了避免编译器的最优化功能如果仅进行定义局部变量并代人数值这一处理的话,编译器的最优化功能就会启动,届时编译器就会认为某些代码没有意义,从而导致汇编语言的源代码无法生成。

标签:esp,局部变量,内存空间,编译器,ebp,寄存器,10.10
From: https://www.cnblogs.com/z1218/p/17099723.html

相关文章

  • 全局变量和局部变量使用问题
      在Java中变量类型有成员变量、局部变量和静态变量(类变量、static变量),本篇文章主要介绍成员变量(全局变量)和局部变量的区别。根据变量的作用范围,将程序中的变量分为......
  • Jmeter-用户定义变量(全局变量)与用户参数(局部变量)-5.31
    1、位置-作用域-运行次数 用户定义变量位置:配置元件、测试计划作用域:全局变量,作用于整个测试计划在启动运行时,获取一次值,在运行过程中,不会动态获取值,在运行......
  • Java—成员变量与局部变量、封装
    一、成员变量与局部变量1.定义的位置不同成员变量:成员变量定义在方法外,类中;局部变量:局部变量定义在方法中。2.生命周期不同成员变......
  • Java(10)成员变量和局部变量
    1、声明的位置局部变量:方法体{}中,形参,代码块中成员变量:类中方法外  ①、类变量:有static修饰  ②、实例变量:没有stati......
  • 【KAWAKO】python查看内存空间占用情况
    目录查看变量的内存占用查看运行内存占用查看变量的内存占用importsysc=1145.114print(sys.getsizeof(c))查看运行内存占用importpsutilmemory=psutil.vir......
  • 局部变量与全局变量
    不同的函数之间传递数据:(1)参数:通过形参或实参(2)返回值:用return语句返回计算结果(3)全局变量:外部变量注:如果全局变量与局部变量重名,那么将采取就近原则,即实际获取和修改的值......
  • C++指针类型的局部变量初始化
    编译器一般不会对一般变量进行初始化,当然也包括指针。所以负责初始化指针变量的只有程序员自己。使用未初始化的指针是相当危险的。因为指针直接指向内存空间,所以程序员很......
  • 硬盘安装ubuntu 10.10及相关事项
    Windows7下硬盘安装ubuntu10.x.desktop.iso   理论上win7、vista系统32位或64位均可。ubuntu适用与10.X版本,且ubuntu-10.10-desktop-i386.iso和ubuntu-10.10-desktop......
  • java循环结构中局部变量和成员变量
    前言在前两篇文章中,壹哥给大家讲解了Java里的条件分支,包括if和switch两种情况。我们知道,除了条件分支结构,还有循环结构,所以接下来的一个学习重点就是Java里的循环。但在学......
  • linux 内存空间(三) 内存地址范围和例子
    先放一张虚拟地址空间分布图(图截至深入理解计算机系统第三版):对于这张图有好多种不同的画法和呈现方式。       通过上面这几张图,我们应该清晰认识到linux......