menglv 发表于 2015-5-9 16:49:47

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



原贴: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:            ;msvcrt.qsort
00402B8C   .8B45 D4       mov eax,dword ptr ss:
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:,15
002FE47B    6A 04         push 4
002FE47D    FF70 08         push dword ptr ds:
002FE480    FF70 04         push dword ptr ds:
002FE483    FF50 0C         call dword ptr ds:
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:
002FE496    50            push eax
002FE497    FF35 3CE32F00   push dword ptr ds:
002FE49D    8B48 0C         mov ecx,dword ptr ds:
002FE4A0    8B40 08         mov eax,dword ptr ds:
002FE4A3    FF31            push dword ptr ds:
002FE4A5    FF30            push dword ptr ds:
002FE4A7    8B0A            mov ecx,dword ptr ds:
002FE4A9    52            push edx
002FE4AA    FF51 1C         call dword ptr ds:
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:               ; 0
75C52BDD    FF75 14         push dword ptr ss:               ; msvcrt.qsort
75C52BE0    FF75 10         push dword ptr ss:               ; 数组大小
75C52BE3    FF75 0C         push dword ptr ss:                ; 数组首地址
75C52BE6    FF75 08         push dword ptr ss:                ; 一段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:         ; 一段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:      ; 数组的大小
75C31AFE    3BC8            cmp ecx,eax                        ; 一段asm代码首地址的高位是否等于FFFF
75C31B00^ 0F84 7C77FFFF   je USER32.75C29282
75C31B06    8B4D 0C         mov ecx,dword ptr ss:         ; 数组的首地址
75C31B09    E8 02AA0000   call USER32.75C3C510               ; 跟进去
75C31B0E    85C0            test eax,eax                         ; eax=0
75C31B10    0F84 CE2D0100   je USER32.75C448E4                   ; 直接跳走

75C3C510    64:A1 18000000mov eax,dword ptr fs:
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:            ; 其实是比较第二个参数是否为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:
75C3CA9F    A1 F490C875   mov eax,dword ptr ds:
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:,dl
75C3CAB5    3B48 04         cmp ecx,dword ptr ds:         ; 数组首字节的低位是否小于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:,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:      ; 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:    ; 没有跳走
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:         ; 0
75C31B23    FF75 14         push dword ptr ss:         ; msvcrt.qsort
75C31B26    57            push edi                           ; edi等于数组的大小,其实就是第三个参数
75C31B27    FF75 0C         push dword ptr ss:            ; 数组首地址
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:,ebx
75C3C545    64:A1 18000000mov eax,dword ptr fs:
75C3C54B    8B80 08070000   mov eax,dword ptr ds:
75C3C551    3BC3            cmp eax,ebx
75C3C553    74 0C         je short USER32.75C3C561             ; 没跳
75C3C555    F600 04         test byte ptr ds:,4
75C3C558    C745 E0 0100000>mov dword ptr ss:,1
75C3C55F    75 03         jnz short USER32.75C3C564            ; 没跳
75C3C561    895D E0         mov dword ptr ss:,ebx
75C3C564    C745 B4 2400000>mov dword ptr ss:,24
75C3C56B    C745 B8 0100000>mov dword ptr ss:,1
75C3C572    6A 07         push 7
75C3C574    59            pop ecx
75C3C575    33C0            xor eax,eax
75C3C577    8D7D BC         lea edi,dword ptr ss:
75C3C57A    F3:AB         rep stos dword ptr es:
75C3C57C    895D DC         mov dword ptr ss:,ebx
75C3C57F    395D E0         cmp dword ptr ss:,ebx
75C3C582    75 14         jnz short USER32.75C3C598            ; 没跳
75C3C584    8B55 08         mov edx,dword ptr ss:
75C3C587    8D4D B4         lea ecx,dword ptr ss:
75C3C58A    FF15 0811C275   call dword ptr ds:[<&ntdll.RtlActiva>; ntdll.RtlActivateActivationContextUnsafeFast
75C3C590    E8 F4FEFFFF   call USER32.75C3C489
75C3C595    8945 DC         mov dword ptr ss:,eax
75C3C598    895D FC         mov dword ptr ss:,ebx
75C3C59B    395D DC         cmp dword ptr ss:,ebx
75C3C59E^ 0F84 FE1DFFFF   je USER32.75C2E3A2                   ; 没跳
75C3C5A4    395D 24         cmp dword ptr ss:,ebx
75C3C5A7^ 0F84 F51DFFFF   je USER32.75C2E3A2                   ; 直接跳

75C2E3A2    8B75 14         mov esi,dword ptr ss:
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:,ebx
75C3C545    64:A1 18000000mov eax,dword ptr fs:
75C3C54B    8B80 08070000   mov eax,dword ptr ds:
75C3C551    3BC3            cmp eax,ebx
75C3C553    74 0C         je short USER32.75C3C561             ; 没跳
75C3C555    F600 04         test byte ptr ds:,4
75C3C558    C745 E0 0100000>mov dword ptr ss:,1
75C3C55F    75 03         jnz short USER32.75C3C564            ; 没跳
75C3C561    895D E0         mov dword ptr ss:,ebx
75C3C564    C745 B4 2400000>mov dword ptr ss:,24
75C3C56B    C745 B8 0100000>mov dword ptr ss:,1
75C3C572    6A 07         push 7
75C3C574    59            pop ecx
75C3C575    33C0            xor eax,eax
75C3C577    8D7D BC         lea edi,dword ptr ss:
75C3C57A    F3:AB         rep stos dword ptr es:
75C3C57C    895D DC         mov dword ptr ss:,ebx
75C3C57F    395D E0         cmp dword ptr ss:,ebx
75C3C582    75 14         jnz short USER32.75C3C598            ; 没跳
75C3C584    8B55 08         mov edx,dword ptr ss:
75C3C587    8D4D B4         lea ecx,dword ptr ss:
75C3C58A    FF15 0811C275   call dword ptr ds:[<&ntdll.RtlActiva>; ntdll.RtlActivateActivationContextUnsafeFast
75C3C590    E8 F4FEFFFF   call USER32.75C3C489
75C3C595    8945 DC         mov dword ptr ss:,eax
75C3C598    895D FC         mov dword ptr ss:,ebx
75C3C59B    395D DC         cmp dword ptr ss:,ebx
75C3C59E^ 0F84 FE1DFFFF   je USER32.75C2E3A2                   ; 没跳
75C3C5A4    395D 24         cmp dword ptr ss:,ebx
75C3C5A7^ 0F84 F51DFFFF   je USER32.75C2E3A2                   ; 直接跳
75C3C5AD    68 B097C875   push USER32.75C897B0               ; UNICODE "锭痈e"
75C3C5B2    8B75 14         mov esi,dword ptr ss:
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:         ; 一段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:         ; 第五个参数
75C3C5D8    FF75 18         push dword ptr ss:         ; msvcrt.qsort,其实就是第四个参数
75C3C5DB    56            push esi                           ; edi等于数组的大小,其实就是第三个参数
75C3C5DC    FF75 10         push dword ptr ss:         ; 数组的首地址
75C3C5DF    FF75 0C         push dword ptr ss:            ; 一段asm代码的首地址
75C3C5E2    E8 DDFEFFFF   call USER32.75C3C4C4               ; 跟进去这段代码
75C3C5E7    8945 E4         mov dword ptr ss:,eax
75C3C5EA    C745 FC FEFFFFF>mov dword ptr ss:,-2
75C3C5F1    E8 33000000   call USER32.75C3C629
75C3C5F6    8B45 E4         mov eax,dword ptr ss:
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:         ; 0
75C3C4D3    FF75 14         push dword ptr ss:         ; msvcrt.qsort,其实就是第四个参数
75C3C4D6    FF75 10         push dword ptr ss:         ; 数组的大小
75C3C4D9    FF75 0C         push dword ptr ss:            ; 数组的首地址
75C3C4DC    64:800D CA0F000>or byte ptr fs:,1
75C3C4E4    FF55 08         call dword ptr ss:            ; 这里是call asm里面的代码,跟进去

/*****************************************************************/
/**********************这里就是asm的一段代码**********************/
002FE470    89E0            mov eax,esp
002FE472    E8 00000000   call 002FE477                        ; 不是很明白这段代码的作用,好像是得到当前的esp
002FE477    830424 15       add dword ptr ss:,15            ; 这里=2FE48C,就是asm里面的下一个call
                                                               ; 其实就是修改当前指令的地址,相当于第四个参数
002FE47B    6A 04         push 4                               ; 这里应该是字长
002FE47D    FF70 08         push dword ptr ds:            ; 数组的大小
002FE480    FF70 04         push dword ptr ds:            ; 数组的首地址
002FE483    FF50 0C         call dword ptr ds:            ; 这里调用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:
002FE496    50            push eax
002FE497    FF35 3CE32F00   push dword ptr ds:
002FE49D    8B48 0C         mov ecx,dword ptr ds:
002FE4A0    8B40 08         mov eax,dword ptr ds:
002FE4A3    FF31            push dword ptr ds:
002FE4A5    FF30            push dword ptr ds:
002FE4A7    8B0A            mov ecx,dword ptr ds:
002FE4A9    52            push edx
002FE4AA    FF51 1C         call dword ptr ds:      ; 这里调用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:                  ; 数组的首地址
7611D3F5    56            push esi
7611D3F6    8B75 0C         mov esi,dword ptr ss:                  ; 数组的大小
7611D3F9    85DB            test ebx,ebx                                    ; 数组的首地址
7611D3FB    0F84 26100100   je msvcrt.7612E427
7611D401    57            push edi
7611D402    8B7D 10         mov edi,dword ptr ss:                   ; 这里应该是字长
7611D405    85FF            test edi,edi
7611D407    0F86 30AB0300   jbe msvcrt.76157F3D
7611D40D    837D 14 00      cmp dword ptr ss:,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:,0
7611D429    895D FC         mov dword ptr ss:,ebx
7611D42C    8975 F8         mov dword ptr ss:,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:                   ; 这里调用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:
7611D454    83E8 01         sub eax,1
7611D457    8945 F4         mov dword ptr ss:,eax
7611D45A    78 1A         js short msvcrt.7611D476
7611D45C    8B9485 78FFFFFF mov edx,dword ptr ss:
7611D463    8B8485 00FFFFFF mov eax,dword ptr ss:
7611D46A    8955 FC         mov dword ptr ss:,edx
7611D46D    8945 F8         mov dword ptr ss:,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
002FE8ED    8B55 0C                         mov   edx, dword ptr
002FE8F0    8B00                               mov   eax, dword ptr
002FE8F2    3B02                               cmp   eax, dword ptr
002FE8F4    75 09                              jnz   short 002FE8FF
002FE8F6    C745 FC 0000000>      mov   dword ptr , 0
002FE8FD    EB 1C                           jmp   short 002FE91B
002FE8FF    8B45 08                        mov   eax, dword ptr
002FE902    8B55 0C                         mov   edx, dword ptr
002FE905    8B00                              mov   eax, dword ptr
002FE907    3B02                              cmp   eax, dword ptr
002FE909    7E 09                           jle   short 002FE914
002FE90B    C745 FC 0100000>       mov   dword ptr , 1
002FE912    EB 07                           jmp   short 002FE91B
002FE914    C745 FC FFFFFFF>         mov   dword ptr , -1
002FE91B    8B45 FC                         mov   eax, dword ptr
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
002FE8EA    8B45 0C      mov   eax, dword ptr
002FE8ED    8B10            mov   edx, dword ptr
002FE8EF    8B01               mov   eax, dword ptr
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
002FE8E8    8B4424 08       mov   eax, dword ptr
002FE8EC    8B10                mov   edx, dword ptr
002FE8EE    8B01                mov   eax, dword ptr
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语言的里的速度也应该跟这个差不多。



页: [1]
查看完整版本: 关于acme_pjz的call msvcrt.dll@qsort的分析