运行时堆栈及函数调用中的部分相关指令

本文详细介绍了运行时堆栈的工作原理,包括入栈(PUSH)和出栈(POP)操作,以及堆栈在函数调用中的应用。同时,深入探讨了与函数调用相关的PUSH, POP, CALL, RET等指令,以及PUSHFD, POPFD, PUSHAD, POPAD等高级指令的作用。通过实例展示了如何使用这些指令进行寄存器的保存和恢复,以及LEA指令在计算地址和避免修改标志位方面的独特用法。" 50848381,5529947,使用NSPipe在iOS中显示NSLog日志,"['iOS开发', '日志管理', '程序调试']
摘要由CSDN通过智能技术生成

运行时堆栈

运行时堆栈是内存数组,CPU用ESP(堆栈指针寄存器)对其进行直接管理,32位模式下,ESP寄存器存放的是堆栈中某个位置的32位偏移量.ESP基本上不会直接被程序员控制,它是用CALL,RET,PUSH和POP等指令间接进行修改.

运行时堆栈工作于系统层,处理子程序调用

如下图所示:ESP中保存的是刚压入堆栈数值(00000001)的偏移量。当指针数值减少时,栈顶也随之下移。
在这里插入图片描述

入栈操作(PUSH)

步骤:

  • 把栈顶指针减4
  • 将数值复制到栈顶指向的堆栈位置
    下图是将数值0000B1压入堆栈的结果

在这里插入图片描述

出栈操作(POP)

步骤:

  • 先将数值弹出堆栈
  • 增加栈顶指针(按堆栈元素大小)
    在这里插入图片描述

堆栈的应用

关于堆栈的应用可参考:https://blog.csdn.net/qq_43313035/article/details/90215278

函数调用中的相关指令

PUSH指令

PUSH指令首先减少ESP的值,再将源操作数复制到堆栈。操作数是16位的,则ESP减2,操作数是32位的,则ESP减4。

POP指令

POP指令首先把ESP指向的堆栈的元素复制到一个16位或者32位的目的操作数中去,再增加ESP的值。操作数是16位的,则ESP加2,操作数是32位的,则ESP加4。

PUSHFD和POPFD指令

  • PUSHFD指令把32位EFLAGS寄存器内容压入堆栈
  • POPFD指令则把栈定元素弹出到EFLAGS寄存器

不能用MOV指令把标识寄存器内容复制给一个变量,因此,PUSHFD可能就是保存标志位的最佳途径。有时候保存
标志寄存器的副本是非常有用的,这样之后就可以恢复标志寄存器原来的值。

通常会用PUSHFD和POPFD封存一段代码:

pushfd       ;保存标志寄存器
;
;任意语句序列
;
popfd         ; 恢复标志寄存器

当用这种方式使用入栈和出栈指令时,必须确保程序的执行路径不会跳过POPFD指令。当程序随着时间不断修改时,很难记住所有入栈和出栈指令的位置。

一种不容易出错的保存和恢复标识寄存器的方法是:将它们压入堆栈后,立即弹出给一个变量:

.data
saveflags DWORD ?
.code
pushfd                ;标识寄存器内容入栈
pop saveflags;        ;复制给一个变量

下述语句从同一个变量中恢复标识寄存器的内容

push saveflags         ;被保存的标识入栈
popfd                  ;复制给标识寄存器

PUSHAD,PUSHA,POPAD,POPA

  • PUSHAD 指令按照 EAX、ECX、EDX、EBX、ESP(执行 PUSHAD 之前的值)、EBP、ESI 和 EDI 的顺序,将所有 32 位通用寄存器压入堆栈

  • POPAD 指令按照相反顺序将同样的寄存器弹出堆栈

  • PUSHA 指令按序(AX、CX、DX、BX、SP、BP、SI 和 DI)将 16 位通用寄存器压入堆栈

  • POPA 指令按照相反顺序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值