上面是函数原型。来看看它编译后的反汇编是怎样执行的。理解函数的调用过程。
第一步:int i= 10
在执行完i= 10后,可以查到i的地址是0x0028FAAC,然后查对应的内存地址
从图中可以看到,10已经被写到对应的内存中去了。
第二步:f(&i);这句话对应的汇编有以下4句
011E1405 lea eax,[i]
011E1408 push eax
011E1409 call f (11E105Ah)
011E140E add esp,4
Lea eax,[i] 将i的有效地址传递给eax,执行完可观察到eax的值已经发生变化
Push eax ,将eax的值压栈,然后call函数f
第三步
void f(int * x)
{
011E13A0 push ebp
011E13A1 mov ebp,esp
011E13A3 sub esp,0C0h
011E13A9 push ebx
011E13AA push esi
011E13AB push edi
011E13AC lea edi,[ebp-0C0h]
011E13B2 mov ecx,30h
011E13B7 mov eax,0CCCCCCCCh
011E13BC rep stos dword ptr es:[edi]
这一段汇编来逐个看一下
Push ebp将旧的ebp压栈
Mov ebp,esp 对栈底指针重新赋值,指向现在的栈顶
然后将bx,si,di压栈
Lea edi,[ebp-c0h]将[ebp-c0h]的地址传递给edi寄存器
011E13B2 mov ecx,30h
011E13B7 mov eax,0CCCCCCCCh
011E13BC rep stos dword ptr es:[edi]
对F9D0到F910的区域初始化,全部写成ccH,共C0H个字节,每次写4个字节,共写30H次。
上面三句话是一起的,相当于是一个循环。先将cx寄存器设为30h,然后对eax赋值为cccccccch。
Rep stos dword ptr es:[edi]的作用是将 eax的值写入到es:[edi]对应的地址。
STOS指令的作用是将eax中的值拷贝到ES:EDI指向的地址. 如果设置了direction flag, 那么edi会在该指令执行后减小, 如果没有设置direction flag, 那么edi的值会增加, 这是为了下一次的存储做准备。
第四步:*x = 100;
mov eax,dword ptr [x]
Mov dword ptr [eax],64h
mov eax,dword ptr [x] ,将 [x]的值传递给eax。[x]的值就是实参i的地址,即
此时0028FAAC地址对应的值还是10.
Mov [eax],64h 往这个地址写入100,即64h
第5步:下括号
先是将edi,esi,ebx出栈。可以看到,出栈后寄存器中的值变化了,但是原来的栈区中的内容没有被清除。
然后将ebp的值赋给esp,让栈顶指针指向ebp所在的位置