当前位置: 首页 > news >正文

32位汇编:实验11子程序调用

程序示例

堆栈图

调试梳理

我们在OB中观察我们堆栈和ESP寄存器的变化情况

初始状态下,我们先准备了参数,执行后第一次调用 call AddProc1,我们让CPU走到这里的时候停下。

我们画出初始状态下的堆栈图

执行到相关位置后,我们发现没有执行cal命令之前堆栈没有发生变化。

执行 call AddProc1call 会:压入返回地址(call 下一条指令的地址)。

F7单步进入,观察call瞬间的堆栈变化

ESP ← ESP - 4

接着在 AddProc1 内部执行接下来的命令

我们可以发现在执行return之前没有变化。

而我们知道return相当于pop EIP,从[ESP]弹出返回地址到EIP,*ESP+4*

结束后堆栈相当于回到最开始的状态

下面程序完成保存结果并准备第二次调用。

第二次调用call AddProc2

call 压入返回地址:

进入到AddProc2

push eax

将EAX当前值(0000001Eh)压栈,ESP减4

接着实现我们的函数功能后**pop eax**

从[ESP]弹出数据到EAX,ESP加4

恢复堆栈后,执行完毕,return弹出返回地址,回到调用处。

堆栈变为初始状态。

同样我们发现因为少了一次平衡,堆栈其实并没有完全恢复。

emm……中间程序卡了一下,重启后堆栈信息发生了变化,不过不影响我们的分析思路。我们下面画图中用新的堆栈表示

接着cal调指令后,我们到了用 printf 函数部分。

这时的堆栈为下图状态

输出寄存器传参的计算结果,四次push后:

push ESP -= 4,我们的堆栈图也变为了

第二次 printf 函数部分输出内存变量传参的计算结果

add esp,10,堆栈指针回到初始位置,栈顶数据被标记为"已释放",下次调用必须重新压入参数。

下面就是我们第二次调用printf的四次压栈

第二次printf调用时栈顶

同理add esp,10,堆栈指针回到初始位置,栈顶数据被标记为"已释放"。

最后return跳出程序

程序堆栈图片变化如下

也算是把当年看滴水画堆栈的功拾回来了。

都写了这么多了,我们顺便回顾一下实验里的知识点吧。

1. 汇编程序结构

.686                    ; 使用686指令集
.model flat,stdcall     ; 平坦内存模型,stdcall调用约定
option casemap:none     ; 大小写敏感
  • 平坦内存模型:所有段(代码、数据、堆栈)都在同一个4GB地址空间

  • stdcall调用约定:被调用函数负责清理堆栈参数

2. 函数声明与调用

printf PROTO C :dword,:vararg  ; 声明C函数原型
invoke printf, offset szFmt, esi, edi, eax  ; 调用函数
  • PROTO:函数原型声明,指定参数类型

  • invoke:高级函数调用指令,自动处理参数压栈

3. 数据定义

szFmt byte '%d + %d = %d', 0ah, 0  ; 字符串以0结尾
X dword ?  ; 未初始化双字变量
  • byte/dword:定义字节/双字(4字节)数据

  • ?:未初始化变量

  • 0ah:换行符(LF)

  • 0:字符串结束符

4. 寄存器使用

mov esi, 10     ; 源索引寄存器存放参数
mov edi, 20     ; 目的索引寄存器存放参数

通用寄存器用途

  • EAX:累加器,常用于算术运算和函数返回值

  • ESI:源索引,常用于字符串/数组操作

  • EDI:目的索引,常用于字符串/数组操作

  • ESP:堆栈指针,指向栈顶

  • EBP:基址指针,指向当前栈帧

5. 算术运算指令

add eax, edi    ; eax = eax + edi

算术指令

  • add dest, src:加法

  • sub dest, src:减法

  • inc reg:加1

  • dec reg:减1

6. 堆栈操作指令

push eax    ; ESP-4, 将EAX压栈
pop eax     ; ESP+4, 从堆栈弹出到EAX
call proc   ; ESP-4, 压入返回地址后跳转
ret         ; ESP+4, 弹出返回地址并跳转

堆栈变化规律

调用前: ESP = 1000
call指令: ESP = 1000-4 = 0FFC, [0FFC]=返回地址
push: ESP = 0FFC-4 = 0FF8
pop: ESP = 0FF8+4 = 0FFC  
ret: ESP = 0FFC+4 = 1000

7. 函数调用约定

寄存器传参(AddProc1)

; 调用前准备参数
mov esi, 10
mov edi, 20
call AddProc1  ; 结果在EAX中

全局变量传参(AddProc2)

; 调用前设置全局变量
mov X, 50
mov Y, 60
call AddProc2  ; 结果在Z中

8. 内存访问

mov eax, X     ; 直接寻址,从变量X读取值
mov Z, eax     ; 直接寻址,将值存入变量Z

9. 程序控制流

start:         ; 程序入口标签
call AddProc1  ; 函数调用
ret            ; 程序结束返回
end start      ; 指定程序入口点
http://www.dtcms.com/a/607742.html

相关文章:

  • 网站开发用px好还是em好企业网站建设综合实训心得体会
  • 网站定制牛七科技校园营销渠道有哪些
  • 做视频的网站做百度网站需不需要备案吗
  • 可以刮刮卡的网站wordpress用户搜索次数
  • phpcms网站seo怎么做抚松做网站
  • window.crypto
  • 校招面经(一)入门篇
  • 织梦生成网站地图什么是网络营销?网络营销有哪些内容?
  • 哈尔滨网站制作专业铁路最好的5个专业学校
  • 国家高新技术企业查询网站徐州关键字优化公司
  • 手机咋建网站建设英文网站的请示
  • (4)Kafka消费者分区策略、Rebalance、Offset存储机制
  • 网站后台都需要什么软件做电子印章制作生成免费
  • 销型网站建设必须的步骤包括网站开发需要的软件有哪些
  • 有做lol直播网站有哪些app制作定制外包服务商e
  • BFS-走迷宫和八数码-java实现
  • 从Manifest V2到V3:Chrome插件开发全解析
  • 百家号和网站同步做建筑公司信用分查询官网
  • 怎么给网站做301绍兴建设网站制作
  • 网站建设项目报告总结报告wordpress 图标上传
  • 网站建设后端技术长春做网络推广的公司
  • 个人网站建设怎么样怎么把自己做的网站上传到网上
  • 无锡网站的建设软件开发外包合同范本
  • RustDesk搭建公网中继服务器远控内网机器(完整版)
  • 站长工具app官方下载wordpress会员积分邀请
  • 网站注册页面htmlphp+ajax网站开发典型实例pdf
  • 如何用excel来做网站后台网站建设管理汇报
  • 虚拟空间有独立ip吗
  • 用fetch-event-source处理流式消息:Vue 3中实现openAI/DeepSeek的实时输出
  • Vue 内置指令