重学C第三节:求两个整数中的大者

子函数,就像小弟一样,帮我做各种各样的事

 1 #include <stdio.h>
 2 
 3 void main()
 4 {
 5     int max(int x,int y);  //函数的声明
 6     int a,b,c;
 7     scanf("%d,%d",&a,&b);  //获取输入
 8     c=max(a,b);            //调用子函数
 9     printf("max= %d \n",c);
10 }
11 
12 int max(int x,int y)
13 {
14     int z;
15     if(x>y)
16     {
17         z=x;
18     }
19     else
20     {
21         z=y;
22     }
23     return z;
24 }

虽然这个程序有更好的方法,但我们的目标不是优化这个程序,所以。。。

老样子,用OD查看Debug版,当然先看主函数:

 1 00401020 >/> \55            push    ebp
 2 00401021  |.  8BEC          mov     ebp, esp
 3 00401023  |.  83EC 4C       sub     esp, 4C
 4 00401026  |.  53            push    ebx
 5 00401027  |.  56            push    esi
 6 00401028  |.  57            push    edi
 7 00401029  |.  8D7D B4       lea     edi, dword ptr [ebp-4C]
 8 0040102C  |.  B9 13000000   mov     ecx, 13
 9 00401031  |.  B8 CCCCCCCC   mov     eax, CCCCCCCC
10 00401036  |.  F3:AB         rep     stos dword ptr es:[edi]
11 00401038  |.  8D45 F8       lea     eax, dword ptr [ebp-8]
12 0040103B  |.  50            push    eax
13 0040103C  |.  8D4D FC       lea     ecx, dword ptr [ebp-4]
14 0040103F  |.  51            push    ecx
15 00401040  |.  68 28504200   push    00425028                         ; /format = "%d,%d"
16 00401045  |.  E8 26010000   call    scanf                            ; \scanf
17 0040104A  |.  83C4 0C       add     esp, 0C
18 0040104D  |.  8B55 F8       mov     edx, dword ptr [ebp-8]
19 00401050  |.  52            push    edx                              ;第二个参数
20 00401051  |.  8B45 FC       mov     eax, dword ptr [ebp-4]
21 00401054  |.  50            push    eax                              ;第一个参数
22 00401055  |.  E8 ABFFFFFF   call    00401005                         ;子函数的位置
23 0040105A  |.  83C4 08       add     esp, 8
24 0040105D  |.  8945 F4       mov     dword ptr [ebp-C], eax
25 00401060  |.  8B4D F4       mov     ecx, dword ptr [ebp-C]
26 00401063  |.  51            push    ecx                              ; /<%d>
27 00401064  |.  68 1C504200   push    0042501C                         ; |format = "max= %d ",LF,""
28 00401069  |.  E8 82000000   call    printf                           ; \printf
29 0040106E  |.  83C4 08       add     esp, 8
30 00401071  |.  5F            pop     edi
31 00401072  |.  5E            pop     esi
32 00401073  |.  5B            pop     ebx
33 00401074  |.  83C4 4C       add     esp, 4C
34 00401077  |.  3BEC          cmp     ebp, esp
35 00401079  |.  E8 52010000   call    _chkesp
36 0040107E  |.  8BE5          mov     esp, ebp
37 00401080  |.  5D            pop     ebp
38 00401081  \.  C3            retn

我们继续看子函数:

 1 004010A0 >/> \55            push    ebp
 2 004010A1  |.  8BEC          mov     ebp, esp
 3 004010A3  |.  83EC 44       sub     esp, 44
 4 004010A6  |.  53            push    ebx
 5 004010A7  |.  56            push    esi
 6 004010A8  |.  57            push    edi
 7 004010A9  |.  8D7D BC       lea     edi, dword ptr [ebp-44]
 8 004010AC  |.  B9 11000000   mov     ecx, 11
 9 004010B1  |.  B8 CCCCCCCC   mov     eax, CCCCCCCC
10 004010B6  |.  F3:AB         rep     stos dword ptr es:[edi]
11 004010B8  |.  8B45 08       mov     eax, dword ptr [ebp+8]           ;  第一个实参
12 004010BB  |.  3B45 0C       cmp     eax, dword ptr [ebp+C]           ;  与第二个实参比较
13 004010BE  |.  7E 08         jle     short 004010C8                   ;  如果小于等于则跳
14 004010C0  |.  8B4D 08       mov     ecx, dword ptr [ebp+8]
15 004010C3  |.  894D FC       mov     dword ptr [ebp-4], ecx
16 004010C6  |.  EB 06         jmp     short 004010CE
17 004010C8  |>  8B55 0C       mov     edx, dword ptr [ebp+C]
18 004010CB  |.  8955 FC       mov     dword ptr [ebp-4], edx
19 004010CE  |>  8B45 FC       mov     eax, dword ptr [ebp-4]
20 004010D1  |.  5F            pop     edi
21 004010D2  |.  5E            pop     esi
22 004010D3  |.  5B            pop     ebx
23 004010D4  |.  8BE5          mov     esp, ebp
24 004010D6  |.  5D            pop     ebp
25 004010D7  \.  C3            retn

下面用IDA来瞅瞅,首先是主函数

 1 int __cdecl main()
 2 {
 3   char v1; // [sp+Ch] [bp-4Ch]@1
 4   int v2; // [sp+4Ch] [bp-Ch]@1
 5   int v3; // [sp+50h] [bp-8h]@1
 6   int v4; // [sp+54h] [bp-4h]@1
 7 
 8   memset(&v1, 0xCCCCCCCCu, 0x4Cu);
 9   scanf("%d,%d", (unsigned int)&v4);
10   v2 = j_max(v4, v3);
11   printf("max= %d \n", v2);
12   return _chkesp();
13 }

然后是子函数:

 1 int __cdecl max(int a1, int a2)
 2 {
 3   char v3; // [sp+Ch] [bp-44h]@1
 4   int v4; // [sp+4Ch] [bp-4h]@2
 5 
 6   memset(&v3, -858993460, 0x44u);
 7   if ( a1 <= a2 )
 8     v4 = a2;
 9   else
10     v4 = a1;
11   return v4;
12 }

我修改了下,变成

 1 int __cdecl max(int x, int y)
 2 {
 3   char v3; // [sp+Ch] [bp-44h]@1
 4   int z; // [sp+4Ch] [bp-4h]@2
 5 
 6   memset(&v3, 0xCCCCCCCCu, 0x44u);
 7   if ( x <= y )
 8     z = y;
 9   else
10     z = x;
11   return z;
12 }

***************************************************************************************************************************

下面是Release版的分析

首先,OD主函数

 1 00401000  /$  83EC 08       sub     esp, 8
 2 00401003  |.  8D4424 00     lea     eax, dword ptr [esp]
 3 00401007  |.  8D4C24 04     lea     ecx, dword ptr [esp+4]
 4 0040100B  |.  50            push    eax
 5 0040100C  |.  51            push    ecx
 6 0040100D  |.  68 3C804000   push    0040803C                         ;  ASCII "%d,%d"
 7 00401012  |.  E8 6A000000   call    00401081
 8 00401017  |.  8B5424 0C     mov     edx, dword ptr [esp+C]
 9 0040101B  |.  8B4424 10     mov     eax, dword ptr [esp+10]
10 0040101F  |.  52            push    edx
11 00401020  |.  50            push    eax
12 00401021  |.  E8 1A000000   call    00401040                         ;  子函数
13 00401026  |.  50            push    eax
14 00401027  |.  68 30804000   push    00408030                         ;  ASCII "max= %d ",LF
15 0040102C  |.  E8 1F000000   call    00401050
16 00401031  |.  83C4 24       add     esp, 24
17 00401034  \.  C3            retn

然后,OD子函数

1 00401040  /$  8B4424 04     mov     eax, dword ptr [esp+4]
2 00401044  |.  8B4C24 08     mov     ecx, dword ptr [esp+8]
3 00401048  |.  3BC1          cmp     eax, ecx
4 0040104A  |.  7F 02         jg      short 0040104E
5 0040104C  |.  8BC1          mov     eax, ecx
6 0040104E  \>  C3            retn

看来经过优化,代码要比Debug版的少很多。

下面用IDA来看看是不是这样

 1 int __cdecl main(int argc, const char **argv, const char **envp)
 2 {
 3   int v3; // eax@1
 4   int v5; // [sp+0h] [bp-8h]@1
 5   int v6; // [sp+4h] [bp-4h]@1
 6 
 7   scanf("%d,%d", &v6, &v5);
 8   v3 = sub_401040(v6, v5);
 9   return sub_401050("max= %d \n", v3);
10 }

我修改下,变成

 1 int __cdecl main(int argc, const char **argv, const char **envp)
 2 {
 3   int z; // eax@1
 4   int y; // [sp+0h] [bp-8h]@1
 5   int x; // [sp+4h] [bp-4h]@1
 6 
 7   scanf("%d,%d", &x, &y);
 8   z = max(x, y);
 9   return printf("max= %d \n", z);
10 }

进入子函数瞅瞅:

1 int __cdecl max(int a1, int a2)
2 {
3   int result; // eax@1
4 
5   result = a1;
6   if ( a1 <= a2 )
7     result = a2;
8   return result;
9 }

我把它修改为:

1 int __cdecl max(int x, int y)
2 {
3   int result; // eax@1
4 
5   result = x;
6   if ( x <= y )
7     result = y;
8   return result;
9 }

工程下载地址:https://files.cnblogs.com/tk091/rl003.7z

=======================================2012-5-11===================================

 1 ; int __cdecl main(int argc, const char **argv, const char **envp)
 2 _main proc near
 3 
 4 var_8= dword ptr -8
 5 var_4= dword ptr -4
 6 argc= dword ptr  4
 7 argv= dword ptr  8
 8 envp= dword ptr  0Ch
 9 
10 sub     esp, 8
11 lea     eax, [esp+8+var_8]
12 lea     ecx, [esp+8+var_4]
13 push    eax
14 push    ecx
15 push    offset Format   ; "%d,%d"
16 call    _scanf
17 mov     edx, [esp+14h+var_8]
18 mov     eax, [esp+14h+var_4]
19 push    edx
20 push    eax
21 call    sub_401040
22 push    eax
23 push    offset aMaxD    ; "max= %d \n"
24 call    _printf
25 add     esp, 24h
26 retn
27 _main endp

修改下临时变量,就变成了

 1 ; int __cdecl main(int argc, const char **argv, const char **envp)
 2 _main proc near
 3 
 4 b= dword ptr -8
 5 a= dword ptr -4
 6 argc= dword ptr  4
 7 argv= dword ptr  8
 8 envp= dword ptr  0Ch
 9 
10 sub     esp, 8
11 lea     eax, [esp+8+b]
12 lea     ecx, [esp+8+a]
13 push    eax
14 push    ecx
15 push    offset Format   ; "%d,%d"
16 call    _scanf
17 mov     edx, [esp+14h+b]
18 mov     eax, [esp+14h+a]
19 push    edx
20 push    eax
21 call    func_max
22 push    eax
23 push    offset aMaxD    ; "max= %d \n"
24 call    _printf
25 add     esp, 24h
26 retn
27 _main endp

这样看起来就清晰多了。

原文地址:https://www.cnblogs.com/tk091/p/2481342.html