• 重学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

    这样看起来就清晰多了。

  • 相关阅读:
    poj 3255
    (DP) bzoj 2091
    (最短路) bzoj 2118
    (点双联通分量) poj 2942
    (树直径) bzoj 1509
    (离线处理+BFS) poi Tales of seafaring
    (并查集+DFS) poi guilds
    (记忆话搜索)POI Fibonacci Representation
    (DP) POI Bytecomputer
    (DP) bzoj 1296
  • 原文地址:https://www.cnblogs.com/tk091/p/2481342.html
Copyright © 2020-2023  润新知