News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

PROLOGUE YES or NO

Started by Grincheux, January 07, 2016, 03:47:07 AM

Previous topic - Next topic

Grincheux

When I use the PROLOGUE option that makes easy to make calls, create local varibles...
When I read Jochen sources he does not use the prologue?
Why?
What is the best choice?

dedndave

it's simply a matter of knowing what the assembler generates for automatic prologue and epilogue
once you understand what it does, you can make the choice that best suits the function

when speed is an issue (the function is called thousands of times, perhaps),
it may be best to write your own prologue and epilogue

otherwise, using the assembler automatic prologue and epilogue makes for more readable code

Vortex

Hi Grincheux,

As Dave said, it's a matter of personal choice. You can remove the prologue \ epilogue sections for optimization purposes.

jj2007

Quote from: Grincheux on January 07, 2016, 03:47:07 AMWhen I read Jochen sources he does not use the prologue?

90% of my procs do have a prologue. But occasionally you can produce shorter and/or faster code without, mainly if
- you have enough spare registers (i.e. no need for locals)
- you need to access the arguments only a few times

If you access args frequently, code size will be shorter with a stack frame:
mov eax, [ebp+nn] is one byte shorter than
mov eax, [esp+nn]

Grincheux

Thank you every one it is clear. I have been very pleased to get your help all the time I was programming this utility.

For Jochen : In my program CatchWebImages I have used two functions MbStrLen and InstrJJ.

If you write an InstrJJ backward function think to me.

jj2007

Quote from: Grincheux on January 07, 2016, 07:03:30 AMIf you write an InstrJJ backward function think to me.

There is Rinstr(), but it's not particularly fast:

Intel(R) Core(TM) i5-2450M CPU @ 2.50GHz (SSE4)
34076   cycles for 100 * InString
26291   cycles for 100 * MB Instr_()
7121    cycles for 100 * MB Instr_(FAST, )
29626   cycles for 100 * MB Rinstr()
31901   cycles for 100 * CRT strstr

ragdog

To PROLOGUE option
http://www.masmforum.com/board/index.php?PHPSESSID=786dd40408172108b65a5a36b09c88c0&topic=11514.0

But i have never used if i use Global and local Variables have i problems to calc the esp pointer ::)
And a good tutorial about it have i never found.


hutch--

Philippe,

> If you write an InstrJJ backward function think to me.

They are not that hard to write, once you have the word length to find, subtract that from the text length then scan backwards testing each start character and following characters to see if you get a match. Stop when the 1st search character is the start of the text being searched. return whatever return value you want on match or no match, I usually use 0 for no match or the offset from the front for a match.

RE: The PROLOGUE and EPILOGUE notation, it is mainly used to turn the automatic stack frame off so if you are writing a leaf procedure (one that does not call other procedures) you reduce the stack overhead by writing it with no stack frame. You can do it even faster by using a register to pass the values, its a roll your own version of FASTCALL where you can pass data in EAX, ECX and EDX and return up to 3 values in the same three registers.

Adamanteus

My real code, that solving this problem looks, like this :
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE

strlen  PROC FUNC_IMP_ASM, ; USES preserve,
string : POINTER
ifdef HUTCHSTRLEN
ifidni FUNC_IMP_ASM, <FASTCALL>
    mov     eax, ecx           ; get pointer to string
else
    mov     eax, [esp + 4]           ; get pointer to string
endif
...


But problem is really conceptual, as best way to strip when no need prologue and epilogue, that's automatically by assembler, but that is to JWasm authors request ...

Grincheux

First : Reply to Hutch.

I have wrote my own but Jochen code is very efficient, for this reason I told him to think to me.
You are right for passing the parameters, I continue using standard prologue and epilogue, but if I can write a function which takes its parameters throught the registers, I define the function as a label.

Adamanteus, you are a fox. It's a good idea.

hutch--

Philippe,

Here is a small demo of FASTCALL versus inlined code The second is faster again than a FASTCALL. The algo is a tiny and not that fast byte scanner for a string length but it is trivial, it only demos the technique difference.


; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    include \masm32\include\masm32rt.inc
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

comment * -----------------------------------------------------
                        Build this  template with
                       "CONSOLE ASSEMBLE AND LINK"
        ----------------------------------------------------- *

; *****************************

    lost MACRO                      ; length of string
        mov ecx, eax
        sub eax, 1
      lbl:
        add eax, 1
        cmp BYTE PTR [eax], 0
        jne lbl
        sub eax, ecx
    ENDM

; *****************************

    .data
      item db "12345678901234567890",0

    .code

start:
   
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    call main
    inkey
    exit

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

main proc

    mov eax, OFFSET item
    call sln                ; call procedure
    print str$(eax),13,10

    mov eax, OFFSET item
    lost                    ; run inline macro
    print str$(eax),13,10

    ret

main endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE

sln proc

    mov ecx, eax

    sub eax, 1
  lbl:
    add eax, 1
    cmp BYTE PTR [eax], 0
    jne lbl

    sub eax, ecx

    ret

sln endp

OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

end start

Grincheux

Thank you Hutch

The difference is the time for calling the proc.

I would like to answer you if rather having many local variables we define a structure for accessing these variable, is it good ?
An other thing, if I do a PUSHF, what becomes the flags affected by instructions before I do the POPF?
Would it be better to do :

PUSHF
Instruction 1
Instruction 2
POPF

OR

PUSHF
Instruction 1
.
.
.
Instruction <n>
POPF

When I was programming under MSDOS with the famous INT 21h, the STC instruction was called to signal an error. Why this his not the same now on Windows?

I don't speak to you very often, but now I made it for a year!

hutch--

Here is a better version with simple timing.


; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    include \masm32\include\masm32rt.inc
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

comment * -----------------------------------------------------
                        Build this  template with
                       "CONSOLE ASSEMBLE AND LINK"
        ----------------------------------------------------- *

; *****************************

    lost MACRO                      ; length of string
    LOCAL lbl
        mov ecx, eax
        sub eax, 1
      lbl:
        add eax, 1
        cmp BYTE PTR [eax], 0
        jne lbl
        sub eax, ecx
    ENDM

; *****************************

    .data
      item db "12345678901234567890",0

    .code

start:
   
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    call main
    inkey
    exit

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

main proc

    LOCAL tc    :DWORD

    push ebx
    push esi
    push edi

    mov eax, OFFSET item
    call sln                ; call procedure
    print str$(eax)," correct test",13,10

    mov eax, OFFSET item
    lost                    ; run inline macro
    print str$(eax)," correct test",13,10

; --------------------------------

    mov esi, 100000000

    fn GetTickCount
    push eax

  lbl1:
    mov eax, OFFSET item
    call sln                ; call procedure
    ; print str$(eax),13,10
    sub esi, 1
    jnz lbl1

    fn GetTickCount
    pop ecx
    sub eax, ecx

    print str$(eax)," ms FASTPROC",13,10

; --------------------------------

    mov esi, 100000000

    fn GetTickCount
    push eax

  lbl2:
    mov eax, OFFSET item
    lost
    ; print str$(eax),13,10
    sub esi, 1
    jnz lbl2

    fn GetTickCount
    pop ecx
    sub eax, ecx

    print str$(eax)," ms INLINE CODE",13,10

; --------------------------------

    pop edi
    pop esi
    pop ebx

    ret

main endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE

sln proc

    mov ecx, eax
    sub eax, 1
  lbl:
    add eax, 1
    cmp BYTE PTR [eax], 0
    jne lbl
    sub eax, ecx
    ret

sln endp

OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

end start

hutch--

Using a structure is a tidy and convenient technique but its still memory operands which are slower than registers. On a longer procedure its fine but on very short procedures you are just adding extra memory operands which slow it down.