理解函数调用与返回的相关汇编指令及递归函数

理解函数调用与返回的相关汇编指令及递归函数如有以下code demo:#include <stdio.h>int max(int a,int b){ return a&

大家好,欢迎来到IT知识分享网。理解函数调用与返回的相关汇编指令及递归函数"

如有以下code demo:

#include <stdio.h>
int max(int a,int b)
{
    return a>b?a:b;
}
int main()
{
    int c = max(3,4);
    return 0;
}

函数调用和返回会分别用到call和ret两个汇编指令。

8:        int c = max(3,4);
00401088   push        4
0040108A   push        3
0040108C   call        @ILT+0(max) (00401005)
00401091   add         esp,8
00401094   mov         dword ptr [ebp-4],eax
……………………………………………………………………………………
@ILT+0(?max@@YAHHH@Z):
00401005   jmp         max (00401020)
……………………………………………………………………………………
2:    int max(int a,int b)
3:    {
00401020   push        ebp
00401021   mov         ebp,esp
00401023   sub         esp,44h
00401026   push        ebx
00401027   push        esi
00401028   push        edi
00401029   lea         edi,[ebp-44h]
0040102C   mov         ecx,11h
00401031   mov         eax,0CCCCCCCCh
00401036   rep stos    dword ptr [edi]
4:        return a>b?a:b;
00401038   mov         eax,dword ptr [ebp+8]
0040103B   cmp         eax,dword ptr [ebp+0Ch]
0040103E   jle         max+28h (00401048)
00401040   mov         ecx,dword ptr [ebp+8]
00401043   mov         dword ptr [ebp-4],ecx
00401046   jmp         max+2Eh (0040104e)
00401048   mov         edx,dword ptr [ebp+0Ch]
0040104B   mov         dword ptr [ebp-4],edx
0040104E   mov         eax,dword ptr [ebp-4]
5:    }
00401051   pop         edi
00401052   pop         esi
00401053   pop         ebx
00401054   mov         esp,ebp
00401056   pop         ebp
00401057   ret

1 call addr

Switches active frame to callee function. Equivalent to:

push %eip // eip保存指令目标地址

mov addr, %eip

2 ret

Restores active frame to caller function. Equivalent to:

pop %eip

(每执行一个指令,都会更新%eip的值。)

3 push S

Pushes a copy of S onto the top of the stack. Equivalent to:

sub $4, %esp

mov S, (%esp)

4 pop D

Pops the top element off the stack and places it in location D. Equivalent to:

mov (%esp), D

add $4, %esp

(push、pop、call、ret都会更新%esp的值,也就是栈指针偏移。)

5 递归函数

先看一个while循环:

int sumDown(int n) { // iterative version
    int total = 0;
    int i = n;
    while (i > 0) { 
        total += i;
        i--;
    }
    return total;
}

两个汇编跳转指令构成一个while循环:

6:        while (i > 0) { // iterative version
00401045   cmp         dword ptr [ebp-8],0
00401049   jle         sumDown+3Fh (0040105f)  // 条件跳转至return前
7:            total += i;
0040104B   mov         ecx,dword ptr [ebp-4]
0040104E   add         ecx,dword ptr [ebp-8]
00401051   mov         dword ptr [ebp-4],ecx
8:            i--;
00401054   mov         edx,dword ptr [ebp-8]
00401057   sub         edx,1
0040105A   mov         dword ptr [ebp-8],edx
9:        }
0040105D   jmp         sumDown+25h (00401045)  // 无跳转跳转回while语句:
10:       return total;
0040105F   mov         eax,dword ptr [ebp-4]
11:   }

将while改写为goto版本:

int sumIf(int n){    // goto version
    int total = 0;
    int i = n;
restart:
    if(i<=0)
        goto end;
    total +=i;
    i--;
    goto restart;
end:
    return total;
}

对应的汇编同样由几个跳转汇编指令构成:

6:    restart:
7:        if(i<=0)
00401095   cmp         dword ptr [ebp-8],0
00401099   jg          restart+8 (0040109d)
8:            goto end;
0040109B   jmp         end+5 (004010b6)
9:        total +=i;
0040109D   mov         ecx,dword ptr [ebp-4]
004010A0   add         ecx,dword ptr [ebp-8]
004010A3   mov         dword ptr [ebp-4],ecx
10:       i--;
004010A6   mov         edx,dword ptr [ebp-8]
004010A9   sub         edx,1
004010AC   mov         dword ptr [ebp-8],edx
11:       goto restart;
004010AF   jmp         restart (00401095)
12:   end:
13:       return total;
004010B1   mov         eax,dword ptr [ebp-4]
004010B4   jmp         end+7 (004010b8)
14:   }
004010B6   jmp         end (004010b1)
004010B8   pop         edi

递归版本:

int sumr(int n) {
    if (n <= 0) {
        return 0;
    }
    return n + sumr(n-1);
}

对应的汇编:

13:       int c = sumr(36);
0040D4C8   push        24h
0040D4CA   call        @ILT+35(sumr) (00401028)    // call启动
………………………………………………………………………………
4:        if (n <= 0) {
00401088   cmp         dword ptr [ebp+8],0
0040108C   jg          sumr+22h (00401092)
5:            return 0;
0040108E   xor         eax,eax
00401090   jmp         sumr+36h (004010a6) // call 结束,ret 开始
6:        }
7:        return n + sumr(n-1); // 按条件call,且参数构成迭代:n = n-1
00401092   mov         eax,dword ptr [ebp+8]
00401095   sub         eax,1
00401098   push        eax
00401099   call        @ILT+30(sumDownIf) (00401023)
0040109E   add         esp,4
004010A1   mov         ecx,dword ptr [ebp+8]
004010A4   add         eax,ecx
8:    }
004010A6   pop         edi
004010A7   pop         esi
004010A8   pop         ebx
004010A9   add         esp,40h
004010AC   cmp         ebp,esp
004010AE   call        __chkesp (004010c0)
004010B3   mov         esp,ebp
004010B5   pop         ebp
004010B6   ret                    // ret

迭代版本同goto版本一样,通过条件判断不断构成跳转,形成循环:

call……call……call…………ret……ret……ret…………

在不断的call中,参数可以构成迭代:n = n-1

在不断的ret中,返回结果存储在%eax寄存器(在非递归版本中使用临时变量total保存)。

-End-

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/63167.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信