关于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]