点我下载SRC&EXE...

;汇编64位乘法除法运算(由逆向C代码而来)
;以及如何精确计算运行一段代码耗费的时间
;
;MengXP @ http://www.aogosoft.com/bbs
;2008-6-12

.386
.Model Flat,StdCall
Option CaseMap :None

Include Windows.inc
Include User32.inc
Include Kernel32.inc

IncludeLib User32.lib
IncludeLib Kernel32.lib


_LARGE_INTEGER    struct
  LowPart    dd ?
  HighPart    dd ?
_LARGE_INTEGER    ends


.Code
;下面的mul64和div64是由c编译后的代码逆向得到

div64    Proc    uses esi edi ebx arg_0,arg_4,arg_8,arg_C    ;被除数低32位,被除数高32位,除数低32位,除数高32位
    mov     eax, arg_4
    or      eax, eax
    jge     short @1
    inc     edi
    mov     edx, arg_0
    neg     eax
    neg     edx
    sbb     eax, 0
    mov     arg_4, eax
    mov     arg_0, edx
@1:
    mov     eax, arg_C
    or      eax, eax
    jge     short @2
    inc     edi
    mov     edx, arg_8
    neg     eax
    neg     edx
    sbb     eax, 0
    mov     arg_C, eax
    mov     arg_8, edx
@2:
    or      eax, eax
    jnz     short @3
    mov     ecx, arg_8
    mov     eax, arg_4
    xor     edx, edx
    div     ecx
    mov     ebx, eax
    mov     eax, arg_0
    div     ecx
    mov     edx, ebx
    jmp     short @7
@3:
    mov     ebx, eax
    mov     ecx, arg_8
    mov     edx, arg_4
    mov     eax, arg_0
@4:
    shr     ebx, 1
    rcr     ecx, 1
    shr     edx, 1
    rcr     eax, 1
    or      ebx, ebx
    jnz     short @4
    div     ecx
    mov     esi, eax
    mul     arg_C
    mov     ecx, eax
    mov     eax, arg_8
    mul     esi
    add     edx, ecx
    jb      short @5
    cmp     edx, arg_4
    ja      short @5
    jb      short @6
    cmp     eax, arg_0
    jbe     short @6
@5:
    dec     esi
@6:
    xor     edx, edx
    mov     eax, esi
@7:
    dec     edi
    jnz     short @8
    neg     edx
    neg     eax
    sbb     edx, 0
@8:
    ret
div64    EndP

mul64    Proc    Arg1,Arg2,Arg3,Arg4    ;被乘数低32位,被乘数高32位,乘数低32位,乘数高32位
    mov    eax, Arg2
    mov    ecx, Arg4
    or    ecx, eax
    mov    ecx, Arg3
    jnz    @1
    mov    eax, Arg1
    mul    ecx
    ret
@1:    push    ebx
    mul    ecx
    mov    ebx, eax
    mov    eax, Arg1
    mul    Arg4
    add    ebx, eax
    mov    eax, Arg1
    mul    ecx
    add    edx, ebx
    pop    ebx
    ret
mul64    EndP


CountIt    Proc
    Local    c1:_LARGE_INTEGER,c2:_LARGE_INTEGER,freq:_LARGE_INTEGER
    Local    szTemp[256]:BYTE
    
    invoke    QueryPerformanceFrequency,addr freq
    push    0
    push    1000    ;以毫秒为单位,如果以秒为单位就是 1000*1000
    push    freq.HighPart
    push    freq.LowPart
    call    div64
    push    edx
    push    eax
    
    invoke    QueryPerformanceCounter,addr c1
    
    invoke    Sleep,3        ;这么做其实就是用来证实Sleep的精确性,总之在我的机器上误差是1ms(取值1-1000)
    ;
    ;去掉Sleep,这里也可以放一些耗时的代码。
    ;
    ;
    ;
    
    invoke    QueryPerformanceCounter,addr c2
    mov    eax,c2.LowPart
    sub    eax,c1.LowPart
    mov    edx,c2.HighPart
    sbb    edx,c1.HighPart
    push    edx
    push    eax
    call    div64
    
    invoke    wsprintf,addr szTemp,CTEXT("计算用时: %d ms"),eax
    invoke    MessageBox,0,addr szTemp,CTEXT("信息"),MB_ICONINFORMATION
    
    ret
CountIt    EndP

Start:
    invoke    CountIt
    invoke    ExitProcess,0
End    Start