对call堆栈平衡的一点心得,希望对新手有所帮助

俺也是新手,通过广海,bpsend 一些论坛学习,最近才对call 的堆栈平衡有点小小领悟,别笑话俺 
 
当你对游戏某项功能实现的时候需要调用call  ,call 前面往往有一些入栈操作 
 
例如        push  a 
            push b 
            push c 
            push d 
            call  游戏功能子程序 
 
游戏功能子程序: 
          push esi 
          push ebx 
            ......... 
          add  esp ,4 /sub esp ,8 
            ......... 
          pop  ebx 
          pop  esi 
          ret   
简单解释:  
子程序中 不管对堆栈如何操作(像上例中的add esp ,4 或者sub esp ,8) 不管游戏子程序开始对应
的push /pop 乱起八糟的有多少,只要找到子程序末尾的 ret  ,那此时堆栈一定退回到 call 刚入栈的状
态,esp的值 = eip的值(即call调用子程序结束后,需要执行的下个语句的地址) 
 
简单分类: 
  1 .  “游戏子程序”末尾是  ret  
       
这个需要call调用返回后,用户自己对堆栈进行平衡,像上面的例子 ,调用前压入了4个参数 ,返回后,
4个参数还在栈中,占用了堆栈的十六进制的4*4=10 
的栈空间 ,那自己注入写的代码 需要 在call 后面加add esp ,10  
       
如果您的程序接下来的执行,需要压入的参数,那您可以不用 平衡,平衡交给后面执行的程序。 
       
但我们见的99%的需要马上平衡,后面程序不需要上面压入的参数,那自己注入代码 需要 在call 后面加
add esp ,10 ,来进行堆栈的平衡操作。 
   
2.”游戏子程序”末尾是  ret  N 
       
这个是您调用的call 子程序 ,自己对堆栈平衡做了操作,这样的一般来说就不用我们对注入的代码进行
add esp 参数个数*4 的操作了 
     
  ret N    就是程序运行到这句时  ,先执行 ret  ,同时让 add  esp ,n 操作。 ret是返回调用程序 ,
add esp ,n 是对被调用程序压入的参数操作,以使堆栈平衡  
     
 
 
ps:    当自己嵌入汇编代码到其他高级语言的时候 ,注意您自己的参数是否正确,否则程序要么提示**
内存不可读,要么直接挂掉退出。 
 
        比如  上面例子 push a  a 是一个地址  ,您却把此地址的值压入了栈,当执行call程序的时候,
访问虚拟内存这个地址的时候,是不会找到的,因为您传入的是一个值,而非地址。 
       
  俺以前经常犯这样的错误,总认为很对,结果。。。 
 
 
以上是个人拙解,不对的地方请指正,偶马上改正。 
   
老马就跳过吧,小马共勉。 
   
精彩内容在回复!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值