能力值:
( LV4,RANK:50 )
|
-
-
2 楼
使用retn,
因为你说的是在call的头部返回,也就是被调用过程的第一条指令处返回(我没有曲解你的意思吧)。
这是还没有分配局部变量,也没有往堆栈中压入数值,那么esp指令指向的依然是call指令的返回地址,所以你直接返回就可以了,使用retn
xxxxxxx1 call xxxxxx10
xxxxxxx5
当执行call指令时,系统会把xxxxxxx5作为返回地址压入堆栈
而在被调用过程完成它的工作后,retn指令就是读取堆栈顶部的地址,然后返回到哪里
所以,通常情况下,在被调用过程里,分配了多少局部变量,也就是形如
add esp -xx
或着
sub esp xx
这就是在分配局部变量
最后过程最后也会释放多少
但是有时程序故意要修改返回地址让程序返回到另一个地方,最简单的就是这样
push xxxxxx20
retn
这样由于修改了堆栈数据,retn指令是只管读出堆栈顶部的值作为返回地址,我们就返回
到了xxxxxx20的地方了。
如果你要在被调用过程的中间,只是返回到原来的返回地址,那么你注意好堆栈平衡就可以了。
|
能力值:
( LV9,RANK:250 )
|
-
-
3 楼
pascal 和C/C++的程序有区别,
delphi编译的一般会在子函数内部平衡堆栈,而VC编译的一般在CALL返回后平衡。
|
能力值:
( LV6,RANK:90 )
|
-
-
4 楼
[QUOTE='UD]Arthas;443163']使用retn,
因为你说的是在call的头部返回,也就是被调用过程的第一条指令处返回(我没有曲解你的意思吧)。
这是还没有分配局部变量,也没有往堆栈中压入数值,那么esp指令指向的依然是call指令的返回地址,所以你直接返回就可以了,使用retn
xxxxxxx1 call ...[/QUOTE]
哈哈,谢谢!
你完全没曲解我的意思!!
感谢了
就是说我在头部返回只用retn就足够了,不用考虑其他是吧?
|
能力值:
( LV13,RANK:380 )
|
-
-
5 楼
怎么可能不考虑其它。
调用约定为C型时,不用考虑,可以直接使用ret
调用约定为其它时,必须考虑ret n
没想到直接返回有什么用,爆破?
如果是面向对象的程序,这样修改类方法有可能死得很惨。
|
能力值:
( LV6,RANK:90 )
|
-
-
6 楼
我说的是汇编
不知道大虾所说的约定为C型、约定为其它是什么意思?
是观察call的头尾有没有对esp进行add或sub 吗?
|
能力值:
( LV13,RANK:380 )
|
-
-
7 楼
不考虑其它情况,仅考虑维持堆栈平衡时,不管是C型调用约定、还是stdcall、...,函数原代码是ret n,你就必须是ret n。
|
能力值:
( LV4,RANK:50 )
|
-
-
8 楼
所谓的调用方式是指:
在调用一个函数时,约定的传递参数方式和平衡堆栈方式,例如:
有一个函数,它有两个参数
xyz(first,second)
当我们使用stdcall调用方式时,也就是Windows调用API的常见方式(又几个函数例外),它的调用方式如下:
xxxxxxx1 push second
xxxxxxx2 push first
xxxxxxx3 call xyz
参数传递从右到左
堆栈的平衡也是有被调用函数负责,
如果是c调用方式如下:
xxxxxxx1 push second
xxxxxxx2 push first
xxxxxxx3 call xyz
xxxxxxx4 add esp 08
参数传递从右到左
堆栈的平衡要有调用函数负责,
如果是pascal调用方式如下:
xxxxxxx1 push first
xxxxxxx2 push second
xxxxxxx3 call xyz
参数传递从左到右
堆栈的平衡有被调用函数负责。
这是简要的解释,不明白就去google上搜篇文章看看吧。
|
|
|