飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 2753|回复: 0

[VB] 关于acme_pjz的call msvcrt.dll@qsort的分析

[复制链接]
  • TA的每日心情
    擦汗
    2019-3-1 23:51
  • 签到天数: 559 天

    [LV.9]以坛为家II

    发表于 2015-5-9 16:49:47 | 显示全部楼层 |阅读模式


    原贴:http://www.vbgood.com/thread-92406-1-1.html
    主题:VC中的qsort源代码翻译成VB的了

    下面是CallWindowProc VarPtr(m_bCode(0)), VarPtr(idxArray(nStart)), nEnd - nStart + 1, m_lpFunc, 0的od分析:

    00402B89   .  8B55 D0       mov edx,dword ptr ss:[ebp-30]            ;  msvcrt.qsort
    00402B8C   .  8B45 D4       mov eax,dword ptr ss:[ebp-2C]
    00402B8F   .  6A 00         push 0
    00402B91   .  52            push edx                                 ;  将msvcrt.qsort的地址压入
    00402B92   .  40            inc eax
    00402B93   .  50            push eax                                 ;  数组的大小
    00402B94   .  56            push esi                                 ;  数组的首地址
    00402B95   .  53            push ebx                                 ;  一段asm代码
    00402B96   .  E8 C9F3FFFF   call 工程1.00401F64                      ;  USER32.CallWindowProcA


    一段asm的代码:
    002FE470    89E0            mov eax,esp
    002FE472    E8 00000000     call 002FE477
    002FE477    830424 15       add dword ptr ss:[esp],15
    002FE47B    6A 04           push 4
    002FE47D    FF70 08         push dword ptr ds:[eax+8]
    002FE480    FF70 04         push dword ptr ds:[eax+4]
    002FE483    FF50 0C         call dword ptr ds:[eax+C]
    002FE486    83C4 10         add esp,10
    002FE489    C2 1000         retn 10
    002FE48C    6A 00           push 0
    002FE48E    89E0            mov eax,esp
    002FE490    8B15 38E32F00   mov edx,dword ptr ds:[2FE338]
    002FE496    50              push eax
    002FE497    FF35 3CE32F00   push dword ptr ds:[2FE33C]
    002FE49D    8B48 0C         mov ecx,dword ptr ds:[eax+C]
    002FE4A0    8B40 08         mov eax,dword ptr ds:[eax+8]
    002FE4A3    FF31            push dword ptr ds:[ecx]
    002FE4A5    FF30            push dword ptr ds:[eax]
    002FE4A7    8B0A            mov ecx,dword ptr ds:[edx]
    002FE4A9    52              push edx
    002FE4AA    FF51 1C         call dword ptr ds:[ecx+1C]
    002FE4AD    58              pop eax
    002FE4AE    C3              retn

    我们跟进USER32.CallWindowProcA:
    75C52BD3 >  8BFF            mov edi,edi                              ; USER32.CallWindowProcA函数首地址
    75C52BD5    55              push ebp
    75C52BD6    8BEC            mov ebp,esp
    75C52BD8    6A 01           push 1
    75C52BDA    FF75 18         push dword ptr ss:[ebp+18]               ; 0
    75C52BDD    FF75 14         push dword ptr ss:[ebp+14]               ; msvcrt.qsort
    75C52BE0    FF75 10         push dword ptr ss:[ebp+10]               ; 数组大小
    75C52BE3    FF75 0C         push dword ptr ss:[ebp+C]                ; 数组首地址
    75C52BE6    FF75 08         push dword ptr ss:[ebp+8]                ; 一段asm代码
    75C52BE9    E8 F2EEFDFF     call USER32.75C31AE0                     ; 这里要跟进去
    75C52BEE    5D              pop ebp
    75C52BEF    C2 1400         retn 14

    跟进call USER32.75C31AE0:

    75C31AE0    8BFF            mov edi,edi                          ; edi=0
    75C31AE2    55              push ebp
    75C31AE3    8BEC            mov ebp,esp
    75C31AE5    56              push esi
    75C31AE6    8B75 08         mov esi,dword ptr ss:[ebp+8]         ; 一段asm代码的首地址
    75C31AE9    85F6            test esi,esi                         ; 是否为0
    75C31AEB    0F84 EA2E0100   je USER32.75C449DB
    75C31AF1    B8 0000FFFF     mov eax,FFFF0000
    75C31AF6    8BCE            mov ecx,esi
    75C31AF8    23C8            and ecx,eax                          ; 取一段asm代码首地址的高位
    75C31AFA    57              push edi
    75C31AFB    8B7D 10         mov edi,dword ptr ss:[ebp+10]        ; 数组的大小
    75C31AFE    3BC8            cmp ecx,eax                          ; 一段asm代码首地址的高位是否等于FFFF
    75C31B00  ^ 0F84 7C77FFFF   je USER32.75C29282
    75C31B06    8B4D 0C         mov ecx,dword ptr ss:[ebp+C]         ; 数组的首地址
    75C31B09    E8 02AA0000     call USER32.75C3C510                 ; 跟进去
    75C31B0E    85C0            test eax,eax                         ; eax=0
    75C31B10    0F84 CE2D0100   je USER32.75C448E4                   ; 直接跳走

    75C3C510    64:A1 18000000  mov eax,dword ptr fs:[18]
    75C3C516    05 CC060000     add eax,6CC
    75C3C51B    85C9            test ecx,ecx                             ; 数组的首地址
    75C3C51D    74 09           je short USER32.75C3C528
    75C3C51F    3B48 28         cmp ecx,dword ptr ds:[eax+28]            ; 其实是比较第二个参数是否为0
    75C3C522  ^ 0F84 148AFFFF   je USER32.75C34F3C
    75C3C528    B2 01           mov dl,1
    75C3C52A    E9 61050000     jmp USER32.75C3CA90
    ......
    75C3CA90    8BFF            mov edi,edi                          ; edi等于数组的大小,其实就是第三个参数
    75C3CA92    55              push ebp
    75C3CA93    8BEC            mov ebp,esp
    75C3CA95    51              push ecx                             ; 数组的首地址
    75C3CA96    53              push ebx                             ; 一段asm代码的首地址
    75C3CA97    56              push esi                             ; 一段asm代码的首地址
    75C3CA98    64:8B35 1800000>mov esi,dword ptr fs:[18]
    75C3CA9F    A1 F490C875     mov eax,dword ptr ds:[75C890F4]
    75C3CAA4    8BD9            mov ebx,ecx                          ; 数组的首地址
    75C3CAA6    0FB7CB          movzx ecx,bx                         ; 取数组首字节的低位
    75C3CAA9    57              push edi
    75C3CAAA    33FF            xor edi,edi
    75C3CAAC    81C6 CC060000   add esi,6CC
    75C3CAB2    8855 FC         mov byte ptr ss:[ebp-4],dl
    75C3CAB5    3B48 04         cmp ecx,dword ptr ds:[eax+4]         ; 数组首字节的低位是否小于955
    75C3CAB8    73 52           jnb short USER32.75C3CB0C            ; 直接跳走
    ......
    75C3CB0C    85F6            test esi,esi
    75C3CB0E    74 0D           je short USER32.75C3CB1D
    75C3CB10    F746 14 0000002>test dword ptr ds:[esi+14],20000000
    75C3CB17  ^ 0F85 F2FDFEFF   jnz USER32.75C2C90F
    75C3CB1D    85FF            test edi,edi
    75C3CB1F  ^\0F84 F2FDFEFF   je USER32.75C2C917                   ; 直接跳走
    ......
    75C2C917    0FB645 FC       movzx eax,byte ptr ss:[ebp-4]        ; eax=1
    75C2C91B    48              dec eax
    75C2C91C    83F8 07         cmp eax,7
    75C2C91F    77 6B           ja short USER32.75C2C98C             ; 没有跳走
    75C2C921    FF2485 A0C9C275 jmp dword ptr ds:[eax*4+75C2C9A0]    ; 没有跳走
    75C2C928    B8 78050000     mov eax,578
    75C2C92D    50              push eax
    75C2C92E    E8 D0FFFFFF     call USER32.75C2C903                 ; 跟进去,好像只是有关错误的处理
    75C2C933    5F              pop edi
    75C2C934    5E              pop esi
    75C2C935    33C0            xor eax,eax
    75C2C937    5B              pop ebx
    75C2C938    8BE5            mov esp,ebp
    75C2C93A    5D              pop ebp
    75C2C93B    C3              retn

    75C448E4    33C0            xor eax,eax
    75C448E6  ^ E9 31D2FEFF     jmp USER32.75C31B1C
    75C31B1C    6A 00           push 0
    75C31B1E    6A 00           push 0
    75C31B20    FF75 18         push dword ptr ss:[ebp+18]           ; 0
    75C31B23    FF75 14         push dword ptr ss:[ebp+14]           ; msvcrt.qsort
    75C31B26    57              push edi                             ; edi等于数组的大小,其实就是第三个参数
    75C31B27    FF75 0C         push dword ptr ss:[ebp+C]            ; 数组首地址
    75C31B2A    56              push esi                             ; 一段asm代码的首地址
    75C31B2B    50              push eax                             ; 0
    75C31B2C    E8 03AA0000     call USER32.75C3C534                 ; 跟进这个call
    75C31B31    5F              pop edi
    75C31B32    5E              pop esi
    75C31B33    5D              pop ebp
    75C31B34    C2 1800         retn 18

    75C3C534    6A 3C           push 3C
    75C3C536    68 08C6C375     push USER32.75C3C608
    75C3C53B    E8 E0FEFFFF     call USER32.75C3C420                 ; 不明白是做什么
    75C3C540    33DB            xor ebx,ebx
    75C3C542    895D E4         mov dword ptr ss:[ebp-1C],ebx
    75C3C545    64:A1 18000000  mov eax,dword ptr fs:[18]
    75C3C54B    8B80 08070000   mov eax,dword ptr ds:[eax+708]
    75C3C551    3BC3            cmp eax,ebx
    75C3C553    74 0C           je short USER32.75C3C561             ; 没跳
    75C3C555    F600 04         test byte ptr ds:[eax],4
    75C3C558    C745 E0 0100000>mov dword ptr ss:[ebp-20],1
    75C3C55F    75 03           jnz short USER32.75C3C564            ; 没跳
    75C3C561    895D E0         mov dword ptr ss:[ebp-20],ebx
    75C3C564    C745 B4 2400000>mov dword ptr ss:[ebp-4C],24
    75C3C56B    C745 B8 0100000>mov dword ptr ss:[ebp-48],1
    75C3C572    6A 07           push 7
    75C3C574    59              pop ecx
    75C3C575    33C0            xor eax,eax
    75C3C577    8D7D BC         lea edi,dword ptr ss:[ebp-44]
    75C3C57A    F3:AB           rep stos dword ptr es:[edi]
    75C3C57C    895D DC         mov dword ptr ss:[ebp-24],ebx
    75C3C57F    395D E0         cmp dword ptr ss:[ebp-20],ebx
    75C3C582    75 14           jnz short USER32.75C3C598            ; 没跳
    75C3C584    8B55 08         mov edx,dword ptr ss:[ebp+8]
    75C3C587    8D4D B4         lea ecx,dword ptr ss:[ebp-4C]
    75C3C58A    FF15 0811C275   call dword ptr ds:[<&ntdll.RtlActiva>; ntdll.RtlActivateActivationContextUnsafeFast
    75C3C590    E8 F4FEFFFF     call USER32.75C3C489
    75C3C595    8945 DC         mov dword ptr ss:[ebp-24],eax
    75C3C598    895D FC         mov dword ptr ss:[ebp-4],ebx
    75C3C59B    395D DC         cmp dword ptr ss:[ebp-24],ebx
    75C3C59E  ^ 0F84 FE1DFFFF   je USER32.75C2E3A2                   ; 没跳
    75C3C5A4    395D 24         cmp dword ptr ss:[ebp+24],ebx
    75C3C5A7  ^ 0F84 F51DFFFF   je USER32.75C2E3A2                   ; 直接跳

    75C2E3A2    8B75 14         mov esi,dword ptr ss:[ebp+14]
    75C2E3A5    E9 19E20000     jmp USER32.75C3C5C3

    75C3C534    6A 3C           push 3C
    75C3C536    68 08C6C375     push USER32.75C3C608
    75C3C53B    E8 E0FEFFFF     call USER32.75C3C420                 ; 不明白是做什么
    75C3C540    33DB            xor ebx,ebx
    75C3C542    895D E4         mov dword ptr ss:[ebp-1C],ebx
    75C3C545    64:A1 18000000  mov eax,dword ptr fs:[18]
    75C3C54B    8B80 08070000   mov eax,dword ptr ds:[eax+708]
    75C3C551    3BC3            cmp eax,ebx
    75C3C553    74 0C           je short USER32.75C3C561             ; 没跳
    75C3C555    F600 04         test byte ptr ds:[eax],4
    75C3C558    C745 E0 0100000>mov dword ptr ss:[ebp-20],1
    75C3C55F    75 03           jnz short USER32.75C3C564            ; 没跳
    75C3C561    895D E0         mov dword ptr ss:[ebp-20],ebx
    75C3C564    C745 B4 2400000>mov dword ptr ss:[ebp-4C],24
    75C3C56B    C745 B8 0100000>mov dword ptr ss:[ebp-48],1
    75C3C572    6A 07           push 7
    75C3C574    59              pop ecx
    75C3C575    33C0            xor eax,eax
    75C3C577    8D7D BC         lea edi,dword ptr ss:[ebp-44]
    75C3C57A    F3:AB           rep stos dword ptr es:[edi]
    75C3C57C    895D DC         mov dword ptr ss:[ebp-24],ebx
    75C3C57F    395D E0         cmp dword ptr ss:[ebp-20],ebx
    75C3C582    75 14           jnz short USER32.75C3C598            ; 没跳
    75C3C584    8B55 08         mov edx,dword ptr ss:[ebp+8]
    75C3C587    8D4D B4         lea ecx,dword ptr ss:[ebp-4C]
    75C3C58A    FF15 0811C275   call dword ptr ds:[<&ntdll.RtlActiva>; ntdll.RtlActivateActivationContextUnsafeFast
    75C3C590    E8 F4FEFFFF     call USER32.75C3C489
    75C3C595    8945 DC         mov dword ptr ss:[ebp-24],eax
    75C3C598    895D FC         mov dword ptr ss:[ebp-4],ebx
    75C3C59B    395D DC         cmp dword ptr ss:[ebp-24],ebx
    75C3C59E  ^ 0F84 FE1DFFFF   je USER32.75C2E3A2                   ; 没跳
    75C3C5A4    395D 24         cmp dword ptr ss:[ebp+24],ebx
    75C3C5A7  ^ 0F84 F51DFFFF   je USER32.75C2E3A2                   ; 直接跳
    75C3C5AD    68 B097C875     push USER32.75C897B0                 ; UNICODE "锭痈e"
    75C3C5B2    8B75 14         mov esi,dword ptr ss:[ebp+14]
    75C3C5B5    56              push esi
    75C3C5B6    E8 8C000000     call USER32.75C3C647
    75C3C5BB    85C0            test eax,eax
    75C3C5BD  ^ 0F85 9B99FFFF   jnz USER32.75C35F5E
    75C3C5C3    8B4D 0C         mov ecx,dword ptr ss:[ebp+C]         ; 一段asm代码的首地址
    75C3C5C6    B8 000000C0     mov eax,C0000000
    75C3C5CB    23C8            and ecx,eax
    75C3C5CD    3BC8            cmp ecx,eax
    75C3C5CF    0F84 45DE0100   je USER32.75C5A41A                   ; 没跳
    75C3C5D5    FF75 1C         push dword ptr ss:[ebp+1C]           ; 第五个参数
    75C3C5D8    FF75 18         push dword ptr ss:[ebp+18]           ; msvcrt.qsort,其实就是第四个参数
    75C3C5DB    56              push esi                             ; edi等于数组的大小,其实就是第三个参数
    75C3C5DC    FF75 10         push dword ptr ss:[ebp+10]           ; 数组的首地址
    75C3C5DF    FF75 0C         push dword ptr ss:[ebp+C]            ; 一段asm代码的首地址
    75C3C5E2    E8 DDFEFFFF     call USER32.75C3C4C4                 ; 跟进去这段代码
    75C3C5E7    8945 E4         mov dword ptr ss:[ebp-1C],eax
    75C3C5EA    C745 FC FEFFFFF>mov dword ptr ss:[ebp-4],-2
    75C3C5F1    E8 33000000     call USER32.75C3C629
    75C3C5F6    8B45 E4         mov eax,dword ptr ss:[ebp-1C]
    75C3C5F9    E8 72FEFFFF     call USER32.75C3C470
    75C3C5FE    C2 2000         retn 20

    75C3C4C4    55              push ebp
    75C3C4C5    8BEC            mov ebp,esp
    75C3C4C7    56              push esi                             ; 数组的大小
    75C3C4C8    57              push edi
    75C3C4C9    53              push ebx                             ; 0
    75C3C4CA    68 CDABBADC     push DCBAABCD                        ; 固定的一个数值
    75C3C4CF    56              push esi                             ; 数组的大小
    75C3C4D0    FF75 18         push dword ptr ss:[ebp+18]           ; 0
    75C3C4D3    FF75 14         push dword ptr ss:[ebp+14]           ; msvcrt.qsort,其实就是第四个参数
    75C3C4D6    FF75 10         push dword ptr ss:[ebp+10]           ; 数组的大小
    75C3C4D9    FF75 0C         push dword ptr ss:[ebp+C]            ; 数组的首地址
    75C3C4DC    64:800D CA0F000>or byte ptr fs:[FCA],1
    75C3C4E4    FF55 08         call dword ptr ss:[ebp+8]            ; 这里是call asm里面的代码,跟进去

    /*****************************************************************/
    /**********************这里就是asm的一段代码**********************/
    002FE470    89E0            mov eax,esp
    002FE472    E8 00000000     call 002FE477                        ; 不是很明白这段代码的作用,好像是得到当前的esp
    002FE477    830424 15       add dword ptr ss:[esp],15            ; 这里[esp]=2FE48C,就是asm里面的下一个call
                                                                     ; 其实就是修改当前指令的地址,相当于第四个参数
    002FE47B    6A 04           push 4                               ; 这里应该是字长
    002FE47D    FF70 08         push dword ptr ds:[eax+8]            ; 数组的大小
    002FE480    FF70 04         push dword ptr ds:[eax+4]            ; 数组的首地址
    002FE483    FF50 0C         call dword ptr ds:[eax+C]            ; 这里调用msvcrt.qsort,我们跟进去
    002FE486    83C4 10         add esp,10
    002FE489    C2 1000         retn 10
    002FE48C    6A 00           push 0
    002FE48E    89E0            mov eax,esp
    002FE490    8B15 38E32F00   mov edx,dword ptr ds:[2FE338]
    002FE496    50              push eax
    002FE497    FF35 3CE32F00   push dword ptr ds:[2FE33C]
    002FE49D    8B48 0C         mov ecx,dword ptr ds:[eax+C]
    002FE4A0    8B40 08         mov eax,dword ptr ds:[eax+8]
    002FE4A3    FF31            push dword ptr ds:[ecx]
    002FE4A5    FF30            push dword ptr ds:[eax]
    002FE4A7    8B0A            mov ecx,dword ptr ds:[edx]
    002FE4A9    52              push edx
    002FE4AA    FF51 1C         call dword ptr ds:[ecx+1C]      ; 这里调用004016F0,作用不明
    002FE4AD    58              pop eax
    002FE4AE    C3              retn
    /*****************************************************************/

    我们跟进msvcrt.qsort:

    7611D3E6 >  8BFF            mov edi,edi
    7611D3E8    55              push ebp
    7611D3E9    8BEC            mov ebp,esp
    7611D3EB    81EC 00010000   sub esp,100
    7611D3F1    53              push ebx
    7611D3F2    8B5D 08         mov ebx,dword ptr ss:[ebp+8]                    ; 数组的首地址
    7611D3F5    56              push esi
    7611D3F6    8B75 0C         mov esi,dword ptr ss:[ebp+C]                    ; 数组的大小
    7611D3F9    85DB            test ebx,ebx                                    ; 数组的首地址
    7611D3FB    0F84 26100100   je msvcrt.7612E427
    7611D401    57              push edi
    7611D402    8B7D 10         mov edi,dword ptr ss:[ebp+10]                   ; 这里应该是字长
    7611D405    85FF            test edi,edi
    7611D407    0F86 30AB0300   jbe msvcrt.76157F3D
    7611D40D    837D 14 00      cmp dword ptr ss:[ebp+14],0                     ; 检测msvcrt.qsort的第四个参数是否为0
    7611D411    0F84 26AB0300   je msvcrt.76157F3D
    7611D417    83FE 02         cmp esi,2                                       ; 数组的大小是否小于2
    7611D41A    72 5A           jb short msvcrt.7611D476
    7611D41C    4E              dec esi                                         ; 从数组后面往前取数组的数值
    7611D41D    0FAFF7          imul esi,edi
    7611D420    03F3            add esi,ebx
    7611D422    C745 F4 0000000>mov dword ptr ss:[ebp-C],0
    7611D429    895D FC         mov dword ptr ss:[ebp-4],ebx
    7611D42C    8975 F8         mov dword ptr ss:[ebp-8],esi
    7611D42F    8BC6            mov eax,esi
    7611D431    2BC3            sub eax,ebx
    7611D433    33D2            xor edx,edx
    7611D435    F7F7            div edi
    7611D437    40              inc eax
    7611D438    83F8 08         cmp eax,8
    7611D43B    0F87 B8000000   ja msvcrt.7611D4F9
    7611D441    8B45 14         mov eax,dword ptr ss:[ebp+14]                   ; 这里调用asm里面的第二个call
    7611D444    50              push eax
    7611D445    57              push edi
    7611D446    53              push ebx
    7611D447    8BC6            mov eax,esi
    7611D449    E8 34000000     call msvcrt.7611D482
    7611D44E    83C4 0C         add esp,0C
    7611D451    8B45 F4         mov eax,dword ptr ss:[ebp-C]
    7611D454    83E8 01         sub eax,1
    7611D457    8945 F4         mov dword ptr ss:[ebp-C],eax
    7611D45A    78 1A           js short msvcrt.7611D476
    7611D45C    8B9485 78FFFFFF mov edx,dword ptr ss:[ebp+eax*4-88]
    7611D463    8B8485 00FFFFFF mov eax,dword ptr ss:[ebp+eax*4-100]
    7611D46A    8955 FC         mov dword ptr ss:[ebp-4],edx
    7611D46D    8945 F8         mov dword ptr ss:[ebp-8],eax
    7611D470    8BDA            mov ebx,edx
    7611D472    8BF0            mov esi,eax
    7611D474  ^ EB B9           jmp short msvcrt.7611D42F
    7611D476    5F              pop edi
    7611D477    5E              pop esi
    7611D478    5B              pop ebx
    7611D479    8BE5            mov esp,ebp
    7611D47B    5D              pop ebp
    7611D47C    C3              retn
    由于call进msvcrt.qsort后要频繁调用asm里的第二个函数,而第二个函数又调用vb程序里的004016F0

    上面代码中调用004016F0其实就是
    Public Function Compare(ByVal Index1 As Long, ByVal Index2 As Long, ByVal nUserData As Long) As Long
        'default implementation (???)
        If Index1 < Index2 Then Compare = -1 Else _
        If Index1 > Index2 Then Compare = 1 Else Compare = 0
    End Function

    就是
    void qsort(void *base,size_t num,size_t width, int (__cdecl *compare )(const void *, const void *) )
    的那个比较函数。

    下面是优化那个比较函数:

    Option Explicit
    Private Declare Function GetTickCount Lib "kernel32 " () As Long
    Implements ISort2

    Private Sub Command1_Click()
        Dim obj As New ISort2
        Dim i As Long
        Dim tt As Long
        Dim a(3000000) As Long
        For i = 0 To 3000000
            a(i) = 10000000 * Rnd()
        Next
        tt = GetTickCount()
        'RadixSort a
        'ShakerSort a
        obj.QuickSort a, 0, 3000000
        'ShellSort2 a, 30
        MsgBox GetTickCount() - tt
    End Sub

        s = "89 E0 E8 00 00 00 00 83 04 24 15 6A 04 FF 70 08" + _
        "FF 70 04 FF 50 0C 83 C4 10 C2 10 00 6A 00 89 E0" + _
        "8B 15 ObjPtr 50 FF 35 UserData 8B 48 0C" + _
        "8B 40 08 FF 31 FF 30 8B 0A 52 FF 51 1C 58 C3"


    需要耗时2590毫秒!

    红色代码就是那个自定义比较函数,我们改变一下这个比较函数。
    int Comp(const void* p1,const void* p2)
    {
        if (*(int *)p1==*(int *)p2)
        return 0;
        if (*(int *)p1>*(int *)p2)
        return 1;
        else
        return -1;
    }
    函数的反汇编代码为:
    002FE8E4    55                                   push    ebp
    002FE8E5    89E5                               mov     ebp, esp
    002FE8E7    83EC 04                          sub     esp, 4
    002FE8EA    8B45 08                          mov     eax, dword ptr [ebp+8]
    002FE8ED    8B55 0C                         mov     edx, dword ptr [ebp+C]
    002FE8F0    8B00                               mov     eax, dword ptr [eax]
    002FE8F2    3B02                               cmp     eax, dword ptr [edx]
    002FE8F4    75 09                              jnz     short 002FE8FF
    002FE8F6    C745 FC 0000000>        mov     dword ptr [ebp-4], 0
    002FE8FD    EB 1C                             jmp     short 002FE91B
    002FE8FF    8B45 08                          mov     eax, dword ptr [ebp+8]
    002FE902    8B55 0C                         mov     edx, dword ptr [ebp+C]
    002FE905    8B00                              mov     eax, dword ptr [eax]
    002FE907    3B02                              cmp     eax, dword ptr [edx]
    002FE909    7E 09                             jle     short 002FE914
    002FE90B    C745 FC 0100000>       mov     dword ptr [ebp-4], 1
    002FE912    EB 07                             jmp     short 002FE91B
    002FE914    C745 FC FFFFFFF>         mov     dword ptr [ebp-4], -1
    002FE91B    8B45 FC                         mov     eax, dword ptr [ebp-4]
    002FE91E    C9                                  leave
    002FE91F    C3                                  retn
    函数反汇编后的hex为:
        "55 89 E5 83 EC 04 8B 45 08 8B 55 0C 8B 00 3B 02 75 09 C7 45 FC 00 00 00 00 EB 1C 8B 45 08 8B 55 " + _
        "0C 8B 00 3B 02 7E 09 C7 45 FC 01 00 00 00 EB 07 C7 45 FC FF FF FF FF 8B 45 FC C9 C3"
    将反汇编的代码替换为:
        s = "89 E0 E8 00 00 00 00 83 04 24 15 6A 04 FF 70 08 " + _
        "FF 70 04 FF 50 0C 83 C4 10 C2 10 00" + _
        "55 89 E5 83 EC 04 8B 45 08 8B 55 0C 8B 00 3B 02 75 09 C7 45 FC 00 00 00 00 EB 1C 8B 45 08 8B 55 " + _
        "0C 8B 00 3B 02 7E 09 C7 45 FC 01 00 00 00 EB 07 C7 45 FC FF FF FF FF 8B 45 FC C9 C3"


    需要耗时765毫秒!

    其实还有更简单的代码:
    int Comp(const void* p1,const void* p2)
    {
        return (*(int *)p1-*(int *)p2);
    }
    函数的反汇编代码为:
    002FE8E4    55                  push    ebp
    002FE8E5    89E5              mov     ebp, esp
    002FE8E7    8B4D 08        mov     ecx, dword ptr [ebp+8]
    002FE8EA    8B45 0C        mov     eax, dword ptr [ebp+C]
    002FE8ED    8B10              mov     edx, dword ptr [eax]
    002FE8EF    8B01               mov     eax, dword ptr [ecx]
    002FE8F1    29D0              sub     eax, edx
    002FE8F3    5D                  pop     ebp
    002FE8F4    C3                  retn
    函数反汇编后的hex为:
        "55 89 E5 8B 4D 08 8B 45 0C 8B 10 8B 01 29 D0 5D C3"
    将反汇编的代码替换为:
        s = "89 E0 E8 00 00 00 00 83 04 24 15 6A 04 FF 70 08 " + _
        "FF 70 04 FF 50 0C 83 C4 10 C2 10 00" + _
        "55 89 E5 8B 4D 08 8B 45 0C 8B 10 8B 01 29 D0 5D C3"
    需要耗时593毫秒!

    继续精简一下上面的代码:
    002FE8E4    8B4C24 04       mov     ecx, dword ptr [esp+4]
    002FE8E8    8B4424 08       mov     eax, dword ptr [esp+8]
    002FE8EC    8B10                mov     edx, dword ptr [eax]
    002FE8EE    8B01                mov     eax, dword ptr [ecx]
    002FE8F0    29D0                sub     eax, edx
    002FE8F2    C3                    retn
    将反汇编的代码替换为:
        s = "89 E0 E8 00 00 00 00 83 04 24 15 6A 04 FF 70 08 " + _
        "FF 70 04 FF 50 0C 83 C4 10 C2 10 00" + _
        "8B 4C 24 04 8B 44 24 08 8B 10 8B 01 29 D0 C3"
    需要耗时562毫秒!

    这个应该是msvcrt.dll@qsort函数的极限结果吧,C语言的里的速度也应该跟这个差不多。



    PYG19周年生日快乐!
    您需要登录后才可以回帖 登录 | 加入我们

    本版积分规则

    快速回复 返回顶部 返回列表