逆向-函数

本文深入探讨函数调用的工作机制,通过递归程序分析函数栈的使用,详细解读汇编代码,揭示函数如何转移、返回以及获取参数。讲解了ESP和EBP寄存器的作用,并讨论了不同的调用约定,如cdecl、stdcall和fastcall。
摘要由CSDN通过智能技术生成

函数的工作机制主要是依托栈结构来实现的,首先栈的一种后进先出的结构,为什么使用这种数据结构,因为这和我们函数调用的流程很类似,当程序嵌套调用时,最后一个调用的函数总是最先返回。

对于函数,我们先从宏观上大体的先去了解,后面在看一些内部细节,简单理解函数调用的话,就是在程序动态的运行中,每进入一个函数,总有一块独立的栈函数空间供它使用,这段空间可以存储各类函数需要用到信息,如局部变量,参数等等,当函数返回时,该空间会销毁。

那么说到栈,当有函数调用发生,需要开辟一块新的栈空间,这时总得记录栈顶的位置吧,只有知道了栈顶的位置,这样子我们才能抬高栈顶(开辟新空间),相对于栈顶,还有一个概念就是栈底,也可以说是函数的底部位置。对于栈顶和栈底,CPU中使用ESP和EBP这两个寄存器来保存其内容。

ESP指向栈顶
    //函数的内部空间
EBP指向栈底

下面来看一段递归程序,用于分析其函数调用的过程

int GetSum(int num)
{
    num && (num += GetSum(num-1)); //num为0时不会执行后半部分,递归出口
    return num;
}

int main(int argc, char* argv[])
{
    printf("%d",GetSum(2));
    return 0;
}

下面来画一下函数递归调用的流程图

函数的返回流程图

所以这里最终的打印结果就是3。看完上面的流程分析,那么现在对函数的栈结构应该有一定的宏观上的了解了。

下面就可以说说细节了,我们就来分析一下上述程序的汇编代码,看懂汇编后,你就能知道程序是如何转移的,又是如何返回的,又是如何获取参数的...

先来看Main函数中的调用

12:       printf("%d",GetSum(2));
00401158 6A 02                push        2   //压入参数
0040115A E8 BF FE FF FF       call        @ILT+25(sub_4010A0) (0040101e)  //调用GetSum
0040115F 83 C4 04             add         esp,4

对于call指令而言,其实他的工作就是把下一行的汇编指令地址给压入栈中,也就是说我们可以如下等价替换

12:       printf("%d",GetSum(2));
00401158 6A 02                push        2
                              push 0040115F //压入下一行的地址
                              mov EIP,0040101e //修改EIP使其到跳转到函数(模拟,真实该指令无效)
0040115F 83 C4 04             add         esp,4
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值