分析下C#中的函数
先写一个小例子,一个静态函数,无返回值,无形参
在第17行与20行分袂下断点
F5调试运行,此时中断在第17行MyFunction(),
在第17行右键反汇编,看下反汇编代码
这里的Call 002D0C30 对应用就是MyFunction()
此时F11直接进入MyFunction函数内部检察我们函数
002D2CA0就是MyFunction的入口,这里就有疑问了,明明上面Call 002D0C30,这里为什么是002D2CA0呢?
在地点栏上转到002D0C30,功效VS提示无法指定地点,当前地点处没有代码……Fuck VS
难道我们就这么放弃了吗?NO…换一种方法,用第三方调试器附加我们的控制台措施
一下就明了了,本来执先完call 002D0C30这条语句, 进入的不是我们的函数MyFunction,
而是先是入到002D0C30里,执行jmp 002D2CA0语句,再跳转到真正的MyFunction函数入口.
总结下: call 002D0C30-> 002D0C30 jmp 002D2CA0->002D2CA0(MyFunction真正的函数入口)
接着分析下仓库,这里能看到的是挪用仓库,而我关心的是当前仓库的情况
实际上当前仓库.里压入的是执行完MyFunction()后的返回地点,
也就是第18行代码的地点002D2B00
为了验证,转到寄存器窗口,学过汇编的都知道ESP指针指向的是当前栈顶
Ok,ESP = 06D6EC18, 转到内存处去检察下06D6EC18处是否生存着002D2B00
总结下:当前仓库栈顶存储的是执行完当前函数后的返回地点.
此刻开始进行最后一步,,分析下函数里反汇编代码的成果
002D2CA0 push ebp //前面这二句用来生存esp,
002D2CA1 mov
ebp,esp //此时ebp指向栈顶,后面可以通过[ebp+xx]访谒函数参数
002D2CA3 push
edi
002D2CA4 push
esi
002D2CA5 push
ebx //对edi esi ebx寄存器压栈进行生存
//sub esp,2Ch 分配姑且变量空间, 我们代码是个空函数,没有姑且变量,
//这里的2Ch空间是供下面VS添加的代码使用的
//这下面是一堆是VS生成的debug代码, release代码就不一样了
002D2CA6 sub
esp,2Ch
002D2CA9 xor
ebx,ebx
002D2CAB mov
dword ptr [ebp-10h],ebx
002D2CAE mov
dword ptr [ebp-1Ch],ebx
002D2CB1 cmp
dword ptr ds:[0015C7A8h],0
002D2CB8 je
002D2CBF
002D2CBA call
71C6CB2D
002D2CBF nop
//这后面的代码是当前函数返回时必需要做的仓库平衡措置惩罚惩罚
002D2CC0 nop
002D2CC1 lea
esp,[ebp-0Ch] //让esp指向函数入口处的栈顶
//下面就是依次把入口处后生存的三个寄存器依次从栈中弹出
002D2CC4 pop
ebx
002D2CC5 pop
esi
002D2CC6 pop
edi
002D2CC7 pop
ebp
//ret 把栈顶的返回地点弹出,转变eip,让当前CPU跳转到Main函数中语句MyFunction()下一句代码的地点
002D2CC8 ret
未完待续,后面还有第二篇有返回值有参数的函数分析