任何程序在运行过程中都需要使用堆栈,操作系统为每一个程序(进程及线程)设置一个堆栈。在使用高级语言编程时,源程序中使用的函数调用、局部变量都要用到堆栈,由编译器来负责生成有关的机器指令。我的理解,堆栈就是维护当前线程中运行状态的一个数据结构,这种状态包括:需要传递的变量,函数的返回地址,局部变量等等。

与堆栈相关的 3 个寄存器是:SS, ESP, EBP。
ESP 寄存器中的内容作为堆栈的当前指针。PUSH, POP, CALL, RET 等指令都与堆栈有关,使用 SS:ESP 指向堆栈单元。
EBP 寄存器中的内容作为堆栈的“基准”指针。SS:EBP 指向的地址作为基准地址。在函数(子程序)内部,可以使用 [EBP+立即数] 的形式来取得主程序传递的参数,使用 [EBP-立即数] 的形式来访问局部变量。
从上述的描述可以看出,整个堆栈的是一个经典的先入后出的栈结构,在栈中还存在着“栈帧”这样的结构,用来表示当前函数运行的环境,里面存放着当前函数的局部变量,所需的返回地址。栈帧由 EBP 所指出,EBP 和 ESP 之间即为当前函数帧,调用函数和被调用函数的栈帧是相邻存放,这样即可通过 EBP加减固定的数,来获取主调函数所传递的函数参数。
上述的堆栈结构如下:

堆栈是经过精心设计的结构,使得编程人员能够方便的设计函数来实现结构化设计,高级语言也得益于这种结构,c 语言基本上就是汇编的一种简单的翻译。这里要强调的是,在用汇编写程序的时候,完全可以不按这种结构来设计,比如参数我们可以放到指定的内存区,被调用的函数到指定的内存区去取出传递给它的参数;也可以让函数参数全部通过寄存器来传送,尤其是在 ARM 这种寄存器特别多,而且每个寄存器的地位都相同的处理器之中。之所以要设计出堆栈,就是为了能够以统一的方式来编写程序。

对于 c 语言,函数有好几种调用规则。最常见的是两种,cdecl 方式和 stdcall 方式。

Cdecl 方式
(1)使用堆栈传递参数
(2)主程序按从右向左的顺序将参数逐个压栈,最后一个参数先入栈。每一个参数压栈一次。
(3)在子程序中,使用 [EBP+X] 的方式来访问参数。X=8 代表第 1 个参数;X=12 代表第二个参数,依次类推
(4)子程序用 RET 指令返回。
(5)由主程序执行“ADD ESP, n”指令调整 ESP,达到堆栈平衡。
(6)一般返回值放在 EAX 中

Stdcall 方式
与Cdecl的不同是,堆栈的平衡不是由主程序完成,而是由子程序通过调用“RET n”指令主动平衡。

这些调用规则,都是针对 c 语言来说的,在 c 语言和汇编需要互相调用的情况;c 语言编写的不通的二进制函数库之间,都要注意函数的调用规则。

下面举一个普通的例子

[plain] view plain copy
  1. AddProc1    proc   ; cdecl方式
  2. push    ebp    ; 记下上一个栈帧地址
  3. mov     ebp, esp
  4. mov     eax, dword ptr [ptr+8]  ; 取第一个参数
  5. add     eax, dword ptr [ptr+12] ; 取第二个参数
  6. pop     ebp    ; 恢复栈帧为调用者,但这时候堆栈还未平衡
  7. ret
  8. AddProc1    endp
  9. AddProc2    proc   ; stdcall
  10. push    ebp
  11. mov     ebp, esp
  12. mov     eax, dword ptr [ptr+8]
  13. add     eax, dword ptr [ptr+12]
  14. pop     ebp
  15. ret     8    ; 和前面一样,唯一不同是,直接由子程序恢复堆栈,8 正好是两个参数的长度
  16. AddProc2    endp
  17. start:
  18. push    20
  19. push    10
  20. call    AddProc1
  21. add     esp, 8   ; 由主调函数恢复堆栈
  22. push    50
  23. push    60
  24. call    AddProc2
  25. ret
  26. end start

汇编堆栈平衡的几种方式相关推荐

  1. 汇编-子程序参数传递的三种方式-寄存器法,堆栈法,参数赋值法【详述后两者】

    汇编-子程序参数传递的三种方式: 寄存器法,堆栈法,参数赋值法 子程序结构如下: 名称 PROC FAR|NEAR;DO SOMETHINGRET [N];返回断点地址,N可忽略,加了必须对SP进行 ...

  2. 得到当前堆栈信息的两种方式(Thread和Throwable)的方法

    今天看到有一个工具类中有一句 Thread.currentThread().getStackTrace()[2].getClassName(); 原来工作中遇到的问题:使用Thread.current ...

  3. 从汇编角度理解 ebpesp 寄存器、函数调用过程、函数参数传递以及堆栈平衡

    关于函数参数的传递及堆栈指针的变化,一直缺乏系统的认识和了解,各种博客也只是片面的讲解某个局部知识点,并没有全局的把握和对栈的深刻理解.本文试图从汇编以及整体上,讲解函数调用时,堆栈的变化,以及到底是 ...

  4. windows结束线程的三种方式

    windows 结束线程有三种方式 一.让线程函数执行到 return 二.在线程函数内调用 ExitThread 三.调用 TerminateThread 其中前两种方式比较类似,它们都是通过修改某 ...

  5. 实验四:使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用

    贺邦+原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 实验目的: 使用库函数 ...

  6. 使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用

    实验4:使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用 姓名:李冬辉 学号:20133201 注: 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http ...

  7. 汇编达人视频学习6(汇编眼中的函数、CALL指令执行函数、堆栈传参、堆栈平衡、外平栈、内平栈)

    title: 汇编达人视频学习6 date: 2021年8月4日 15点15分 tags: 汇编达人 categories: 汇编达人 21.汇编眼中的函数 1.什么是函数 函数就是一系列指令的集合, ...

  8. 替代反射调用的几种方式及性能测试

    园子里和这个话题的相关文章比较多,本文是旧话重提,外加个小的总结.主要因为近期看到很多同事.朋友都已经使用 VS2012 进行 .NET 4.5 开发了,却还在大量使用反射,不知道用新的方式.或有所了 ...

  9. C/C++函数调用的几种方式

    2019独角兽企业重金招聘Python工程师标准>>> 我们知道,调用函数时,计算机常用栈来存放函数执行需要的参数,由于栈的空间大小是有限的,在windows下栈是向低地址扩展的数据 ...

  10. 【汇编语言与计算机系统结构笔记15】子程序设计:调用与返回,保护与恢复寄存器,子程序的参数传递,堆栈平衡,结构伪操作 STRUC

    本次笔记内容: 20.子程序设计-1-1 21.子程序设计-1-2 22.子程序设计-1-3 注:我找到了对应内容的课件,请见我于GitHub的CS笔记仓库.因此,为了节省时间,我只记录老师上课强调的 ...

最新文章

  1. 鲜为人知的pandas骚操作
  2. python 服务端性能_python 学习笔记---Locust 测试服务端性能
  3. What to call your Academic Event
  4. packageinfo.java_package-info.java文件详解
  5. Ubuntu 12.04 eclipse 安装 svn插件
  6. 区块链学习-以太坊学习简介
  7. mediacodec surfaceview解码失败
  8. 初中信息技术考试:Python试题及答案
  9. ICEM对装配体进行网格划分实例
  10. 制图中比例尺的一些问题
  11. [产品]博客文章被企业群组收录的方法
  12. 判断火车票座位python代码_12306 火车票监控Python代码详解
  13. JS获取当前使用的浏览器名字以及版本号
  14. 让你实现财富自由,从此不再缺资金
  15. 按键精灵什么是动态数组?如何使用动态数组?(新手进阶)
  16. 英语 计算机水平怎么填写,计算机水平一般怎么填
  17. 微信小程序如何调用后台接口
  18. 什么是显热?什么是潜热?
  19. 盲沟低比?不不不,是芒果的笔,今天学一下分布式文件存储数据库MongoDB。
  20. 小程序嵌入web-view网页后,点击网页中的按钮跳转回小程序

热门文章

  1. 【目标检测】YOLOv5跑通VOC2007数据集
  2. Mujoco不错的视频教程
  3. mujoco安装教程
  4. flash百叶窗消失_flash遮罩特效实例---百叶窗效果
  5. BScroll 使用(Vue)
  6. 铺铜需要把agnd和dgnd分开_AGNDDGND 分析
  7. 物联网时代即将到来,LED显示屏内容显示安全尤为重要
  8. PIC单片机C语言编程教程
  9. 我java启蒙老师 郝斌老师
  10. 小米5主板原理图_小米5手机拆解及评测 小米5拆机详细图解教程