News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Faster GetProcAddress

Started by lingo, October 26, 2006, 09:18:54 PM

Previous topic - Next topic

lingo

I know the topic "Fast GetProcAddress" by Petroizki:
http://www.masm32.com/board/index.php?topic=1144.0

But my GetProcAddress function should be faster..
Why?
- He uses as a 1st parameter hModule and
that is standard
From:MSDN
[in] Handle to the DLL module that contains the function or variable.
The LoadLibrary or GetModuleHandle function returns this handle."


I use as a 1st parameter pointer to zero ended string with
the name of the module
Example:
   db "c:\Windows\system32\Kernel32.dll",0 
or
   db "Kernel32.dll",0 
Hence, one Windows API less..
and  our Windows program may be just
with one imported API -> LoadLibrary...
(which is mandatory to run properly)
.686           
.mmx           
;k3d           
.xmm           
.model  flat, stdcall     
option  casemap:none, language:stdcall, dotname
assume  fs:nothing

include c:\masm32\include\windows.inc
include c:\masm32\include\user32.inc   
include c:\masm32\include\kernel32.inc   
include c:\masm32\macros\macros.asm
include c:\masm32\macros\ucmacros.asm
includelib c:\masm32\lib\user32.lib
includelib c:\masm32\lib\kernel32.lib

GetProcAddr proto  :DWORD, :DWORD
dwtoa proto :DWORD, :DWORD

.data

;szDllName   db    "c:\windows\system32\Kernel32.dll",0
szDllName    db    "Kernel32.dll",0
;szDllName   db    "Ws2_32.dll",0

;szProcName  db    "WriteFile",0,0,0,0
;szProcName  db    "WSAStartup",0,0,0,0
szProcName   db    "HeapAlloc",0,0,0,0

.code                                    ;
Start:                                   ;
        push  offset szDllName           ; lp Dir name
        push  offset szProcName          ; lp Proc Name
        ;push 908                        ; ordinal of WriteFile API
        call  GetProcAddr                ;
        jmp   ExitProcess                ;
                                         ;
;........................................;     

                                       
;.......................................;       
;  Local  Variables:       
; [esp+0*4] ->  ExportDirectory  address + ExportDirectorySize   
; [esp+1*4] ->  flag for forwarded proc   
;
;  Proc  Parameters:                     
; [esp+1*4+(4*4+2*4)] -> lpProc         ; lp of proc name or ordinal value
; [esp+2*4+(4*4+2*4)] -> lpDll          ; lp Dll name
;.......................................;
OPTION PROLOGUE:NONE                    ;
OPTION EPILOGUE:NONE                    ;
GetProcAddr   proc lpProc:DWORD,lpDll:DWORD
                                        ;
                                        ;
       add    esp,-2*4-4*4              ; room for 4 registers and 2 local variables
       mov    [esp+2*4+0*4], edi        ; saving registers
       mov    [esp+2*4+1*4], ebp        ;
       mov    [esp+2*4+2*4], esi        ;
       mov    [esp+2*4+3*4], ebx        ;
       mov    dword ptr [esp+1*4], 0    ; [esp+1*4]-> clear flag for forwarded proc
GetStart:                               ;
       mov    edx, [esp+2*4+4*4+2*4]    ; edx->lp Dll name
       mov    ebp, 20h                  ; ebp-> BaseDllName address (Unicode)
       cmp    byte ptr [edx+1], ":"     ; "c:\...." Is it full path or just dll name?
       jne    @f                        ;
       mov    ebp, 18h                  ; ebp-> FullDllName (Unicode)
@@:                                     ;
; Get module base address...............;
       mov    eax, fs:[30h]             ; PEB base in eax
       cmp    dword ptr [esp+1*4], -1   ; If it is forwarded esi->ntdll.dll
       mov    eax, [eax+0Ch]            ; eax-> PEB_LDR_DATA
       mov    edi, edx                  ; edi->lp Dll name
       mov    esi, [eax+1Ch]            ; esi-> 1st entry in InitOrderModuleList
       je     @f                        ; else
       mov    esi, [esi]                ; esi->Kernel32.dll
@@:                                     ;
       mov    eax, [esi+ebp]            ; eax-> BaseDllName or FullDllName (Unicode)
       mov    ebx, esi                  ; ebx-> the 1st LDR_MODULE in the chain
; Comparing strings ....................;
                                        ;
FindNextCharw:                          ;
       mov    ch,  [eax]                ; eax-> BaseDllName or FullDllName (Unicode)
       add    eax, 2                    ;
       cmp    ch,  5Ah                  ;
       ja     @f                        ;
       cmp    ch,  41h                  ;
       jl     @f                        ;
       or     ch,  20h                  ;
@@:                                     ;
       mov    cl,  [edx]                ; edx->lp dll name string "." or zero ended
       add    edx, 1                    ;
       cmp    cl,  5Ah                  ;
       ja     @f                        ;
       cmp    cl,  41h                  ;
       jl     @f                        ;
       or     cl,  20h                  ;
@@:                                     ;
       cmp    cl,  ch                   ;
       jne    Next_LDRw                 ;
       test   ch,  ch                   ;
       je     @f                        ;
       cmp    ch,  "."                  ;
       jne    FindNextCharw             ;
       cmp    dword ptr [esp+1*4], -1   ; flag for forwarded proc ->  If it is forwarded
       jne    FindNextCharw             ;           copy until "." , else until zero
@@:                                     ;
       mov    ebx, [esi+8]              ; ebx-> Base Dll Name address
       je     GetNextApi                ;
                                        ;
; Next forward LDR_MODULE ..............;
Next_LDRw:                              ;
       mov    esi, [esi]                ; we go forwards
       mov    edx, edi                  ; edx->lp Dll name
       cmp    ebx, esi                  ; If current module = 1st module -> Dll is Not Loaded
       mov    eax, [esi+ebp]            ; eax-> BaseDllName or FullDllName (Unicode) address
       jne    FindNextCharw             ;
                                        ; 
; The module is not loaded in memory and;
; we will try LoadLibrary to load it....;
                                        ; 
       cmp    dword ptr [esp+1*4],-1    ; If it is forwarded
       je     Forwarded_Dll             ; copy dll name in the stack and call oadLibrary
       xor    ebx, ebx                  ; ebx = 0
       invoke LoadLibrary, edx          ; call API
       add    ebx, eax                  ; ebx-> BaseDllName address or zero
       je     End_NotFound              ; No such dll -> exit with ebx=0-> error
; End of Get module base address........;
                                        ;
GetNextApi:                             ;
       mov    edx, [ebx+3Ch]            ; edx-> beginning of PE header
       mov    esi, ebx                  ; ebp-> current dll base address
       mov    edi, [ebx+edx+78h]        ; edi-> RVA of ExportDirectory -> 78h
       mov    ecx, [ebx+edx+7Ch]        ; ecx-> RVA of ExportDirectorySize ->7Ch
       add    esi, [ebx+edi+20h]        ; esi-> AddressOfNames ->20h
       add    edi, ebx                  ; ebx-> current dll base address
       movd   MM5, edi                  ; MM5-> edi-> ExportDirectory
       mov    ebp, [esp+1*4+(4*4+2*4)]  ; ebp->proc name address or ordinal value
       add    ecx, edi                  ; ecx= ExportDirectory address + ExportDirectorySize
       mov    eax, [edi+18h]            ; eax = num of API Names-> nMax NumberOfNames->18h
       test   ebp, 0ffff0000h           ; is it proc name address or ordinal value?
       mov    [esp+0*4], ecx            ; [esp+0*4] = ExportDirectory address + ExportDirectorySize
       je     GetByOrdinal              ;GetProcAddress by Ordinal
                                        ;   
; Binary search ........................;GetProcAddress by Name
       movd   MM7, esp                  ; save the stack here
       movzx  ecx, byte ptr [ebp]       ; ebp->proc name address
       lea    edi, [esi+4]              ;      cl-> 1st character of the proc name 
       mov    esp, ebx                  ; esp-> current dll base address
       neg    edi                       ; set carry flag
       movd   MM6, edi                  ; MM6= -(esi+4]
Bin_Search:                             ; 
      ;cmova  esi, edx                  ; see Note 1
       sbb    edi, edi                  ; edi->mask  -1 or 0
       xor    esi, edx                  ; mix esi and edx
       and    esi, edi                  ; esi=esi or esi=0
       mov    ebx, esp                  ; ebx-> current dll base address
       xor    esi, edx                  ; esi=esi or esi=edx
       shr    eax, 1                    ;
       je     End_ZeroIndex             ;
IndexIsZero:                            ;
       add    ebx, [esi+4*eax]          ;
       lea    edx, [esi+4*eax+4]        ;
       cmp    cl,  [ebx]                ; ebx-> API Names Table 
       jne    Bin_Search                ;
; End Binary search ....................;
                                        ;
; Compare next bytes of two strings.....;
       lea    edi, [ebp+1]              ;     
@@:                                     ;
       mov    ch,  [edi]                ; comparing bytes   
       add    ebx, 1                    ;   
       cmp    ch,  [ebx]                ; ebx-> API Names Table 
       jne    Bin_Search                ;
       add    edi, 1                    ;   
       test   ch,  ch                   ;   
       jne    @b                        ;
                                        ;
; Extract the index from EDX to get proc address   
       movd   esi, MM5                  ; esi-> ExportDirectory
       movd   eax, MM6                  ; eax-> -(AddressOfNames+4)
       mov    edi, [esi+24h]            ; edi->AddressOfNameOrdinals ->24h
       mov    ecx, esp                  ; ecx-> current dll base address
       add    ecx, [esi+1Ch]            ; ecx-> AddressOfFunctions->1Ch
       add    eax, edx                  ; edx-> [esi+4*eax+4]
       shr    eax, 1                    ; eax->index-> eax*2 for word table
       add    edi, esp                  ; esp-> current dll base address
       movzx  eax, word ptr [eax+edi]   ; eax = Ordinal number for this index
       mov    ebx, esp                  ; ebx-> current dll base address
       add    ebx, [ecx+eax*4]          ; ebx-> proc address
       movd   esp, MM7                  ; restore the stack
;.......................................;
Is_it_Forwarded:                        ; check if proc address is inside export directory
       cmp    esi, ebx                  ; esi-> ExportDirectory
       jnl    EndProc                   ;
       cmp    ebx, [esp+0*4]            ; [esp+0*4] = ExportDirectory address + ExportDirectorySize
       jl     Forwarded                 ;
;.......................................;
EndProc:                                ;
       mov    edi, [esp+2*4+0*4]        ; restoring registers
       mov    eax, ebx                  ; eax->proc address  or zero
       mov    ebp, [esp+2*4+1*4]        ;
       mov    esi, [esp+2*4+2*4]        ;
       mov    ebx, [esp+2*4+3*4]        ;
       add    esp, 2*4+4*4              ;
       ret    2*4                       ;
;.......................................;
End_ZeroIndex:                          ;   
       jc     IndexIsZero               ; if it is 1st time zero->return, 
       movd   esp, MM7                  ; else (2nd time zero)-> restore the stack 
End_NotFound:                           ; and exit
       xor    ebx, ebx                  ; ebx=0 -> flag not found
       je     EndProc                   ;
;.......................................;
GetByOrdinal:                           ;
       cmp    ebp, [esi].IMAGE_EXPORT_DIRECTORY.NumberOfFunctions
       jnl    End_NotFound              ; esi-> ExportDirectory
       sub    ebp, [esi].IMAGE_EXPORT_DIRECTORY.nBase
       mov    eax, ebx                  ; eax-> current dll base address
       add    eax, [esi].IMAGE_EXPORT_DIRECTORY.AddressOfFunctions
       add    ebx, [eax + ebp*4]        ; ebx-> proc address
       jne    Is_it_Forwarded           ;
;.......................................;
Forwarded_Dll:                          ;
; Copy dll name in the stack............;
       xor    eax, eax                  ; eax->index = 0
       sub    esp, 2048                 ; room for dll name in the stack
       xor    ebx, ebx                  ; ebx=0
@@:                                     ;
       mov    cl,  [edx+eax]            ; edx->lp Dll name->source
       add    eax, 1                    ;
       mov    [esp+eax-1], cl           ; esp->lp target buffer
       test   cl,  cl                   ;
       je     @f                        ;
       cmp    cl,  "."                  ;
       jne    @b                        ;
       mov    [esp+eax-1], ebx          ; ebx=0
@@:                                     ;
       invoke LoadLibrary, esp          ; call API
       add    esp, 2048                 ; restore the stack
       add    ebx, eax                  ; ebx-> BaseDllName address or zero
       jne    GetNextApi                ;
       je     End_NotFound              ; No such dll -> exit with ebx=0-> error
;.......................................;
Forwarded:                              ;
       mov    eax, ebx                  ; eax->proc address 
; Call the proc "recursively"...........;
@@:                                     ;
       cmp    byte ptr [eax], "."       ; looking for "."
       lea    eax, [eax+1]              ;
       jne    @b                        ;
       cmp    byte ptr [eax], "#"       ; Is it forwarded by ordinal?  Ex: "ntdll.#12"
       je     @f                        ;
@GetProc:                               ;
       mov    dword ptr [esp+1*4], -1   ; set flag -> it is forwarded
       mov    [esp+1*4+(4*4+2*4)], eax  ; eax->offset of proc name or ordinal value
       mov    [esp+2*4+(4*4+2*4)], ebx  ; ebx->lp Dll name
       jmp    GetStart                  ; start it again with new proc name and Dll name and flag
@@:                                     ;
; A2Dw..................................;
       lea    edx, [eax+1]              ;
       xor    eax, eax                  ;
@@:                                     ;
       movzx  ecx, byte ptr [edx]       ;
       add    edx, 1                    ;
       test   ecx, ecx                  ;
       je     @GetProc                  ;
       lea    eax, [eax+4*eax]          ;
       lea    eax, [ecx+2*eax-30h]      ; eax=(eax*10 +ecx-30h)
       jne    @b                        ;
; End A2Dw..............................;
GetProcAddr   endp                      ;
;.......................................;
OPTION PROLOGUE:PrologueDef             ;
OPTION EPILOGUE:EpilogueDef             ;
;.......................................;

End Start
       
;.......................................;
Notes:                                  ;
      1.Original code with branch:      ;     
Bin_Search:                             ; 
       jl     @f                 ;
       mov    esi, edx                  ; if cl >[ebx] then esi == edx
@@:                                     ;
       shr    eax, 1                    ; else esi == esi
       mov    ebx, esp                  ; 
       je     End_ZeroIndex             ;
       ...                              ;
       ...                              ;
       cmp    cl,  [ebx]                ;   
       jne    Bin_Search                ;
                                        ;
Avoiding branch  -  Alternative A:      ;
Bin_Search:                             ; best code but works with new CPUs 
       cmova  esi, edx                  ; if cl >[ebx] then esi == edx
       shr    eax, 1                    ; else esi == esi
       mov    ebx, esp                  ; 
       je     End_ZeroIndex             ;
       ...                              ;
       ...                              ;
       cmp    cl,  [ebx]                ;   
       jne    Bin_Search                ;
                                        ;
Avoiding branch  -  Alternative B:      ;
Bin_Search:                             ; CPU compatible code 
      ;cmova  esi, edx                  ; if cl > [ebx] then esi == edx, else esi == esi 
       sbb    edi, edi                  ; edi->mask  -1 or 0
       xor    esi, edx                  ; mix esi and edx
       and    esi, edi                  ; esi=esi or esi=0
       mov    ebx, esp                  ; ebx-> current dll base address
       xor    esi, edx                  ; esi=esi or esi=edx
       shr    eax, 1                    ;
       je     End_ZeroIndex             ;
       ...                              ;
       ...                              ;
       cmp    cl,  [ebx]                ;   
       jne    Bin_Search                ;
;.......................................;



Regards,
Lingo


[attachment deleted by admin]

James Ladd

Lingo,

Thats nice and interesting code.

I have a question and that is how often do you think people need to get the address of a proc?
If it's not a lot of the time the program is running, then do you think that making some other API faster
would be a better challenge and a bigger reward to you and the community?

Whilst I havent measured your code for the performance difference I am assuming there is one.

lingo

#2
I wondering why you don't asked your questions before here:  :lol
http://www.masm32.com/board/index.php?topic=5774.0

So, if I answer your "question" the probability  for moving this thread to The Colosseum
or to Recycle Bin becomes actually high...
Why?

I don't want to say that but all things depend on the level of the people
If they don't understand the art, beauty  and the power of assembly and use
different OLD high level macros, classes and other similar constructions
just to make their code "more readable" and  "easy for newbie"...
Example :
Most of the people here code their programs with "standard" C like
assembly code
Why?
Because it is the "standard" here    and if someone want to change it a bit
in direction to more sophisticated and fast code moderators (some of them)
will delete his message and will say "You don't  respect other people"
They are emotional and can't understand that I respect all the people as  human beings but not their "assembly" code, nor their "In the name of the god/freedom/democracy/fatherland/etc..I will kill you", nor their " It became necessary for me to remove some posts from this thread.  The decision was not an easy one ...", nor their...

So, this site may be good just for newbie in assembly rather than advanced coders
It is not a surprise for me the fact some advanced coders like bitrake,the_svin, nexo,
Mirno,Tomas, etc don't post their code here

The situation in some advanced C/C++ sites is opposite
If you try to mix assembly with C/C++ they will kill you with the arguments like:
"Why you make your code so unreadable and CPU dependable with assembly" and sometimes I agree with them because my best language is C/C++...
but it is other story....

With other words the way of thinking here is against "pure" assembly "in the name of
newbie" , and it one of the a reason for some people to stay newbie forever...

There is some light at the end of the tunnel with new 64bit assembly, it is a big
fun for me, but it is another story as well...

hutch--

#3
This is what we have the LAB for, development of fast code, if its fast, someone will find a use for it.  :bg

Lingo,

It looks good, I will try and put some time in to have a play with it a bit later if I can get in front.

LATER :

Lingo,

See if I have done justice to your algo, I modified the front end code for a simple benchmark against LoadLibrary() GetProcAddress() in one block and you GetProcAddr() in the other as it receives the name of the string rather than the library handle.

It comes in a little faster on my Northwood core PIV.

This is what I get.

765 API timing
703 Lingo timing.

I have only posted in the changes to your front code for the timings.


.data

;szDllName    db    "c:\windows\system32\Kernel32.dll",0
szDllName   db    "Kernel32.dll",0
;szDllName   db    "Ws2_32.dll",0

;szProcName  db    "WriteFile",0,0,0,0
;szProcName  db    "WSAStartup",0,0,0,0
szProcName   db    "HeapAlloc",0,0,0,0

pKernel dd szDllName
hLib dd 0

.code                                    ;
Start:                                   ;

    invoke LoadLibrary,pKernel
    mov hLib, eax

    fn GetProcAddress,hLib,"SetSystemTime"
    fn MessageBox,0,str$(eax),"GetProcAddress Method",MB_OK

    fn GetProcAddr,"SetSystemTime",pKernel
    fn MessageBox,0,str$(eax),"GetProcAddr    Method",MB_OK

    push esi

    mov esi, 5000
    invoke GetTickCount
    push eax
  @@:
    invoke LoadLibrary,pKernel
    mov hLib, eax
    fn GetProcAddress,hLib,"LoadLibraryA"
    invoke LoadLibrary,pKernel
    mov hLib, eax
    fn GetProcAddress,hLib,"LoadLibraryW"
    invoke LoadLibrary,pKernel
    mov hLib, eax
    fn GetProcAddress,hLib,"FreeLibrary"
    invoke LoadLibrary,pKernel
    mov hLib, eax
    fn GetProcAddress,hLib,"GetModuleHandleA"
    invoke LoadLibrary,pKernel
    mov hLib, eax
    fn GetProcAddress,hLib,"GetModuleHandleW"
    invoke LoadLibrary,pKernel
    mov hLib, eax
    fn GetProcAddress,hLib,"LoadResource"
    invoke LoadLibrary,pKernel
    mov hLib, eax
    fn GetProcAddress,hLib,"CreateDirectoryExA"
    invoke LoadLibrary,pKernel
    mov hLib, eax
    fn GetProcAddress,hLib,"CreateDirectoryExW"
    invoke LoadLibrary,pKernel
    mov hLib, eax
    fn GetProcAddress,hLib,"DeleteFileA"
    invoke LoadLibrary,pKernel
    mov hLib, eax
    invoke LoadLibrary,pKernel
    mov hLib, eax
    fn GetProcAddress,hLib,"DeleteFileW"
    invoke LoadLibrary,pKernel
    mov hLib, eax
    fn GetProcAddress,hLib,"GetCommandLineA"
    invoke LoadLibrary,pKernel
    mov hLib, eax
    fn GetProcAddress,hLib,"GetCommandLineW"
    invoke LoadLibrary,pKernel
    mov hLib, eax
    fn GetProcAddress,hLib,"PeekConsoleInputA"
    invoke LoadLibrary,pKernel
    mov hLib, eax
    fn GetProcAddress,hLib,"PeekConsoleInputW"
    invoke LoadLibrary,pKernel
    mov hLib, eax
    fn GetProcAddress,hLib,"SetSystemTime"
    invoke LoadLibrary,pKernel
    mov hLib, eax
    fn GetProcAddress,hLib,"SetVolumeLabelA"
    invoke LoadLibrary,pKernel
    mov hLib, eax
    fn GetProcAddress,hLib,"SetVolumeLabelW"
    invoke LoadLibrary,pKernel
    mov hLib, eax
    fn GetProcAddress,hLib,"WaitForSingleObjectEx"
    invoke LoadLibrary,pKernel
    mov hLib, eax
    fn GetProcAddress,hLib,"WinExec"
    sub esi, 1
    jnz @B
    invoke GetTickCount
    pop ecx
    sub eax, ecx
    fn MessageBox,0,str$(eax),"timing API",MB_OK

    mov esi, 5000
    invoke GetTickCount
    push eax
  @@:
    fn GetProcAddr,"LoadLibraryA",pKernel
    fn GetProcAddr,"LoadLibraryW",pKernel
    fn GetProcAddr,"FreeLibrary",pKernel
    fn GetProcAddr,"GetModuleHandleA",pKernel
    fn GetProcAddr,"GetModuleHandleW",pKernel
    fn GetProcAddr,"LoadResource",pKernel
    fn GetProcAddr,"CreateDirectoryExA",pKernel
    fn GetProcAddr,"CreateDirectoryExW",pKernel
    fn GetProcAddr,"DeleteFileA",pKernel
    fn GetProcAddr,"DeleteFileW",pKernel
    fn GetProcAddr,"GetCommandLineA",pKernel
    fn GetProcAddr,"GetCommandLineW",pKernel
    fn GetProcAddr,"PeekConsoleInputA",pKernel
    fn GetProcAddr,"PeekConsoleInputW",pKernel
    fn GetProcAddr,"SetSystemTime",pKernel
    fn GetProcAddr,"SetVolumeLabelA",pKernel
    fn GetProcAddr,"SetVolumeLabelW",pKernel
    fn GetProcAddr,"WaitForSingleObjectEx",pKernel
    fn GetProcAddr,"WinExec",pKernel
    sub esi, 1
    jnz @B
    invoke GetTickCount
    pop ecx
    sub eax, ecx
    fn MessageBox,0,str$(eax),"timing Lingo",MB_OK

    pop esi

    jmp ExitProcess

;         push  offset szDllName           ; lp Dir name
;         push  offset szProcName          ; lp Proc Name
;         ;push 908                        ; ordinal of Write File API
;         call  GetProcAddr                ;
;         jmp   ExitProcess                ;
                                         ;
;........................................;       

Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

James Ladd

Lingo,

I'm not sure if I have offended you or not, but if I have then sorry. It's not my intention.

I asked for a function that returns all the procs in one go rather than one at a time because I needed all the procs in
a single table and because the API allows me to find all procs without knowing their names etc.

Anyhow, sorry if I offended.

Rgs, James.

zooba

It looks to me that your code searches a list of currently loaded DLLs before trying LoadLibrary. I'm just wondering if this is based on an assumption that LoadLibrary either doesn't do this or is slow at it, or based on knowledge, ie. is this the performance gain or is the search for the function the performance gain?

Looks good. :bg

Cheers,

Zooba :U

lingo

#6
Thank you Hutch,  :wink
I appreciate your testing efforts
and wondering why Petroizki has
other timing results..



James,
I'm not sure what you need but
you can try included Iczelion's
PE Tutorial no.7



Zooba,

"It looks to me that your code searches a list of currently loaded DLLs
before trying LoadLibrary.


Correct!

"I'm just wondering if this is based on an assumption that
LoadLibrary either doesn't do this or is slow at it..


LoadLibrary does it a bit slowly
See Hutch's test..

Regards,
Lingo

[attachment deleted by admin]

lingo

#7
Hutch,
after error correction I used your test program and
my results are:

timing API ->  586
timing lingo -> 47

My CPU is P4 3,60 GHz Prescott

Thanks again,
Lingo

lingo

Hutch,

When I change dll name from
Kernel32.dll to c:\windows\system32\Kernel32.dll
the execution time for the original APIs rises 5 times...  :lol
See: gettest1.exe and gettest2.exe

I have made small speed improvements and have updated
the included files

Regards,
Lingo

hutch--

Lingo,

I will give it a try, I have both a Prescott and a Northwood core  PIV handy so I will see how it works. I just happen to have my main box as win2k as the directory where the other box uses winnt like normal so i was wary of hard coding the path.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

lingo

Small speed improvements again  :lol

Regards,
Lingo

Ghirai

Tested with your first attachment on an AMD Athlon64 3000+, XP Pro SP2:

Timing API: 547
Timing Lingo: 31
MASM32 Project/RadASM mirror - http://ghirai.com/hutch/mmi.html

Seb

Wow, that's a very nice pice of code you got there lingo (not to mention slightly unreadable for ASM-noobs like myself). :U

I like the way you setup variables/registers on the stack yourself - does any one know where to find documentation about this? Thanks in advance.

On-topic:

The results on my AMD Athlon 64 X2 Dual Core were:

515
31

ecube


GetKernelBase proc
assume fs:nothing
mov eax, fs:[30h]
mov edx, 0B8h
mov ecx, [eax+30h]
test eax, eax
jns @F
mov ebx, [eax+34h]
test ecx, ecx
jnz XI_1
@@:
mov eax, [eax+0Ch]
sub edx, 0B0h
mov eax, [eax+1Ch]
mov ebx, [eax]
XI_1:
mov eax, [ebx+edx]
ret
GetKernelBase endp

ic2

E^cube, assume fs:nothing mov eax, fs:[30h] only works on 9x and from my experience  i never got it to work on XP... Have i missed something AGAIN javascript:void(0);
Eek