News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

ClearLocalVariables timings

Started by jj2007, July 22, 2013, 08:25:30 PM

Previous topic - Next topic

jj2007

Quote from: Ficko on July 23, 2013, 09:18:07 PM
The "ZerorSubVars" proc trashes only "edi" which is saved into "edx" temporally.

I'm trying to test your version:
   push offset MyProc
   call ZeroSubVars

But mov eax, [esp+4] yields 401005, which happens to be
00401005   . /E9 53000000   jmp MyProc


It works for MyProc proc private uses ... args but not for public (the default).

Will keep trying ;-)

Ficko

I am not sure what you are doing jj. :icon_eek:
If you call a proc with a parameter then [esp+4] is the parameter you pushed.
Therefore you push the offset of a PROC than you get the offset of a PROC.


Ficko

Ok, I have a thought.

If you did this:


ZeroSubVars proc public pProc:DWORD
....


It will not work.
It has to be a frameless proc.


ZeroSubVars:mov eax, [esp+4]

jj2007

Quote from: Ficko on July 23, 2013, 11:39:51 PM
I am not sure what you are doing jj. :icon_eek:
If you call a proc with a parameter then [esp+4] is the parameter you pushed.
Therefore you push the offset of a PROC than you get the offset of a PROC.

That sounds entirely plausible. Nonetheless, the bloody beast pushes the jump table, not the actual proc start - unless I declare it private. And of course, ZeroSubVars has option prologue:none etc.
::)

Now the good news is that I found the culprit. Testbed attached - try with and without /debug in the linker's commandline, and prepare for a fat surprise :icon_mrgreen:

P.S.: Don't use polink, use the old Masm32 default linker.

Ficko

Here is my test code (Tested with JWASM and ML the "bloody beast" must be "GoASM":P):


.686p
.model flat,stdcall
option casemap :none ; case sensitive
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
; *********************************************************
; turn stackframe off and on for low overhead procedures
; *********************************************************
Stackframe MACRO arg
  IFIDNI <on>,<arg>
    OPTION PROLOGUE:PrologueDef
    OPTION EPILOGUE:EpilogueDef
  ELSEIFIDNI <off>,<arg>
    OPTION PROLOGUE:NONE
    OPTION EPILOGUE:NONE
  ELSE
    echo -----------------------------------
    echo ERROR IN "stackframe" MACRO
    echo Incorrect Argument Supplied
    echo Options
    echo 1. off Turn default stack frame off
    echo 2. on  Restore stack frame defaults
    echo SYNTAX : frame on/off
    echo -----------------------------------
    .err
  ENDIF
ENDM     
; ---------------------------------------------------------
Pilot PROTO
.data
    CommandLine   dd 0
    hInstance     dd 0
.code
start:
    invoke GetModuleHandle, NULL ; provides the instance handle
    mov hInstance, eax
    invoke GetCommandLine        ; provides the command line address
    mov CommandLine, eax
     invoke Pilot
    invoke ExitProcess,eax

Stackframe off
ZeroSubVars proc public
mov eax, [esp+4]
mov ecx, dword ptr [eax+5]
.if (byte ptr [eax+4] == 0C4h)
neg ecx
.endif
.if (byte ptr [eax+3] == 83h)
movzx ecx, cl
.endif
mov edx, edi
mov edi, ecx
sub edi, ebp
neg edi
shr ecx, 2
xor eax, eax
rep stosd
mov edi, edx
ret 4
ZeroSubVars endp

Stackframe on
Pilot proc public
LOCAL MyVar :QWORD
push offset Pilot
call ZeroSubVars
ret 4
Pilot endp
end start

jj2007

Hi Ficko,
It's the linker. Depending on version and debug settings, it sometimes pushes the real offset, sometimes the offset of the jump table. The snippet below shows this:
00401005        offset MyPublic
00402000        offset MyPrivate

Same with polink:
00401FEE        offset MyPublic
00401FF0        offset MyPrivate


include \masm32\include\masm32rt.inc

.code
start:
   push offset MyPublic
   pop ecx
   print hex$(ecx), 9, "offset MyPublic", 13, 10

   push offset MyPrivate
   pop ecx
   inkey hex$(ecx), 9, "offset MyPrivate", 13, 10

   exit

nops 1000h-72h   ; to make it clearer

MyPublic proc public
  nop
  ret
MyPublic endp

MyPrivate proc private
  nop
  ret
MyPrivate endp

end start

OPT_Linker   link   ; polink works, 6.14 sometimes, 10.0 chokes if /debug is set
OPT_DebugA   /Zi
OPT_DebugL   /debug /DYNAMICBASE:NO
OPT_Assembler   mlv10

Ficko

That's really strange having no explanation. :icon_eek:

Antariy

Hi Jochen :t

When you're using /debug switch with the linker, and do not want to have those "jumps-to" wrappers, add /INCREMENTAL:NO switch to the linker. (Those jumps are things having two targets: fast linking scheme (incremental build), and/or are helpers in a debugging (that was especially important for breakpoints on an APIs on Win9x systems)).

jj2007

Thanks, Alex, that solves the mystery :t

We had a long thread about the IAT jump tables in the old forum. For my "zero locals" macro, the problem is not relevant because I chose to go back and look for mov ebp, esp, but Ficko's version relies on direct calls, so the linker behaviour needs to be watched.

Antariy

Yes, IAT jump thunks are not absolutely equal to "incremental/debug-mode" ones, but very similar things.

Interesting, with search of /INCREMENTAL found this thread on the old forum, too:
http://www.masmforum.com/board/index.php?topic=795.msg5491#msg5491

jj2007

Thanks to everybody :icon14:

The fastest algo is now part of the MasmBasic library (more).