汇编4-递归分析

对于一个正在学数据结构的菜鸟,递归是心中抹不掉的痛。今天决定从汇编层面分析一下其过程。

构造以下代码

#include <stdio.h>

int f(int p){

    static int k = 0;

    if (p == 1)

        return 1;

    else

        return f(p - 1) + 1;

}

int main(){

    int z;

    z = f(2);

}

  

对于递归,主要观察栈的变化。观察函数入口处。

00A52A0E push 2

00A52A10 call 00A511C7

此时将2压栈,进入函数。

00A517A0 push ebp

00A517A1 mov ebp,esp

00A517A3 sub esp,0C0h

此处观察到对esp指针减0c0h,具体原因不清楚。继续向下分析。

00A517BE cmp dword ptr [ebp+8],1

00A517C2 jne 00A517CD

这两行用来比较临时变量与1是否相等,若不相等,则跳转到00A517CD。

00A517CD mov eax,dword ptr [ebp+8]

00A517D0 sub eax,1

00A517D3 push eax

00A517D4 call 00A511C7

观察附近的程序,发现将修改过的eax值压栈,继续call。

记录call后栈的返回地址, 00 a5 17 d9

仍观察到00A517A3 sub esp,0C0h

继续执行相同的函数

00A517BE cmp dword ptr [ebp+8],1

00A517C2 jne 00A517CD

但在jne处明显不发生跳转。此时跳转到

00A517C4 mov eax,1

00A517C9 jmp 00A517DF (JMP为无条件跳转)

观察跳转地址。

00A517E2 add esp,0C0h

00A517E8 cmp ebp,esp

可见这两行恰好恢复栈并比较esp和ebp的值。

由于esp和ebp值相同,继续发生跳转

00A517EA call 00A511D6

00A517EF mov esp,ebp

00A517F1 pop ebp

00A517F2 ret

弹出ebp值并返回,而返回地址恰为00A517D9

00A517D9 add esp,4

00A517DC add eax,1

此时将栈中1清除并把eax加1。

00A517E2 add esp,0C0h

00A517E8 cmp ebp,esp

}

00A517EA call 00A511D6

00A517EF mov esp,ebp

00A517F1 pop ebp

00A517F2 ret

此时继续清栈,返回。

00A52A15 add esp,4

00A52A18 mov dword ptr [ebp-8],eax

此时将参数2清栈,将eax值分配给临时变量。递归结束。自己手画了一张示意图。以下为函数调用阶段过程(忽略博主的doubi字体)

以下是返回阶段。

注意:中间忽略部分对栈结构无影响的寄存器。

就酱,真费劲。

 

posted @ 2015-04-25 23:18  无の心  阅读(427)  评论(0编辑  收藏  举报