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

E40.【C语言】练习:有关栈帧的讨论(反汇编分析)

目录

1.题目

2.解

反汇编查看F1函数

3.改编

解:

反汇编分析

内存图


1.题目

下列代码中,F1的a和F2的b是否使用同一块栈帧空间?

#include <stdio.h>
void F1()
{int a = 0;printf("%p\n", &a);
}void F2()
{int b = 0;printf("%p", &b);
}int main()
{F1();F2();
}

2.解

程序运行时,VS先为main函数申请栈帧,执行到F1函数时再为其申请栈帧空间,但注意以下写法:

	F1();F2();

F1()运行完后,其栈帧被销毁,交换操作系统后,再执行F2()函数

反汇编查看F1函数

void F1()
{push        ebp  mov         ebp,esp  sub         esp,0D0h  push        ebx  push        esi  push        edi  lea         edi,[ebp-10h]  mov         ecx,4  mov         eax,0CCCCCCCCh  rep stos    dword ptr es:[edi]  mov         eax,dword ptr [__security_cookie (02FA040h)]  xor         eax,ebp  mov         dword ptr [ebp-4],eax  mov         ecx,offset _2D923C74_FileName@c (02FC009h)  call        @__CheckForDebuggerJustMyCode@4 (02F1334h)  nop  int a = 0;mov         dword ptr [a],0  printf("%p\n", &a);lea         eax,[a]  push        eax  push        offset string "%p\n" (02F7B30h)  call        _printf (02F10DCh)  add         esp,8  
}push        edx  mov         ecx,ebp  push        eax  lea         edx,ds:[2F20F8h]  call        @_RTC_CheckStackVars@8 (02F11F4h)  pop         eax  pop         edx  pop         edi  pop         esi  pop         ebx  mov         ecx,dword ptr [ebp-4]  xor         ecx,ebp  call        @__security_check_cookie@4 (02F1159h)  add         esp,0D0h  cmp         ebp,esp  call        __RTC_CheckEsp (02F1258h)  mov         esp,ebp  pop         ebp  ret  

注意到最后两行:  pop         ebpret(返回),之后交还操作系统

VS再为F2申请栈帧空间,用的空间是原来为F1申请的地方(空间可以重复利用),也就有了下面的结果,a与b存储的地址相同

3.改编

修改代码后,F1的a和F2的b是否使用同一块栈帧空间?

#include <stdio.h>
void F2();
void F1()
{int a = 0;printf("%p\n", &a);F2();
}void F2()
{int b = 0;printf("%p", &b);
}int main()
{F1();
}

解:

显然改成了嵌套调用,在F1()的内部调用F2(),导致F1()函数在F2()执行完之前无法返回

反汇编分析

void F1()
{push        ebp  mov         ebp,esp  sub         esp,0D0h  push        ebx  push        esi  push        edi  lea         edi,[ebp-10h]  mov         ecx,4  mov         eax,0CCCCCCCCh  rep stos    dword ptr es:[edi]  mov         eax,dword ptr [__security_cookie (0F7A040h)]  xor         eax,ebp  mov         dword ptr [ebp-4],eax  mov         ecx,offset _2D923C74_FileName@c (0F7C009h)  call        @__CheckForDebuggerJustMyCode@4 (0F71334h)  nop  int a = 0;mov         dword ptr [a],0  printf("%p\n", &a);lea         eax,[a]  push        eax  push        offset string "%p\n" (0F77B30h)  call        _printf (0F710DCh)  add         esp,8  F2();call        _F2 (0F71037h)  nop  
}push        edx  mov         ecx,ebp  push        eax  lea         edx,ds:[0F747D0h]  call        @_RTC_CheckStackVars@8 (0F711F4h)  pop         eax  pop         edx  pop         edi  pop         esi  pop         ebx  mov         ecx,dword ptr [ebp-4]  xor         ecx,ebp  call        @__security_check_cookie@4 (0F71159h)  add         esp,0D0h  cmp         ebp,esp  call        __RTC_CheckEsp (0F71258h)  mov         esp,ebp  pop         ebp  ret 

尽管在F1函数的最后有ret返回指令,但是call        _F2 (0F71037h)指令在前,导致先去执行F2()函数,待F2结束后再执行call后的指令

再看看F2函数的反汇编指令:

void F2()
{push        ebp  mov         ebp,esp  sub         esp,0D0h  push        ebx  push        esi  push        edi  lea         edi,[ebp-10h]  mov         ecx,4  mov         eax,0CCCCCCCCh  rep stos    dword ptr es:[edi]  mov         eax,dword ptr [__security_cookie (0F7A040h)]  xor         eax,ebp  mov         dword ptr [ebp-4],eax  mov         ecx,offset _2D923C74_FileName@c (0F7C009h)  call        @__CheckForDebuggerJustMyCode@4 (0F71334h)  nop  int b = 0;mov         dword ptr [b],0  printf("%p", &b);lea         eax,[b]  push        eax  push        offset string "%p" (0F77BD0h)  call        _printf (0F710DCh)  add         esp,8  
}push        edx  mov         ecx,ebp  push        eax  lea         edx,ds:[0F742A8h]  call        @_RTC_CheckStackVars@8 (0F711F4h)  pop         eax  pop         edx  pop         edi  pop         esi  pop         ebx  mov         ecx,dword ptr [ebp-4]  xor         ecx,ebp  call        @__security_check_cookie@4 (0F71159h)  add         esp,0D0h  cmp         ebp,esp  call        __RTC_CheckEsp (0F71258h)  mov         esp,ebp  pop         ebp  ret 

注意到最后的ret返回指令,其返回后,来到了call        _F2 (0F71037h)下面的nop空指令

此后才能对F1()函数返回,也就有了下面的结果,a与b存储的地址不一样

内存图

如果画张内存图来表示main,F1,F2这三个函数


http://www.mrgr.cn/news/49135.html

相关文章:

  • 基于Raspberry Pi人脸识别自动门
  • C++中单例推荐写法
  • 【尚硅谷】FreeRTOS学笔记(更新中更新时间2024.10.12)
  • 81.【C语言】数据结构之空间复杂度
  • 探索Spring Cloud Config:构建高可用的配置中心
  • 语料库综述
  • vue3学习:数字时钟遇到的两个问题
  • 部分品牌电脑进入BIOS方法
  • RBTree(红黑树)的介绍和实现
  • gaussdb 主备版本8 SQL参考 学习
  • 2024全国科技特长生趋势揭秘
  • 利士策分享,生命的价值是金钱可以丈量的吗?
  • C++基础补充(03)C++20 的 std::format 函数
  • 【Redis】什么是Redis
  • RabbitMQ 入门(二)基本结构和消息模型
  • S4.2.6.1 LTSSM 之 Detect 状态
  • 【C++栈】2434. 使用机器人打印字典序最小的字符串|1953
  • MySQL 删除数据库
  • python 画图|三维散点图输出
  • 现代数字信号处理I-P2概率论学习笔记