News:

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

Question about masm, proc and leave

Started by GODlike, January 07, 2006, 09:47:32 PM

Previous topic - Next topic

GODlike

When you use "proc" to define a procedure by default masm replaces "ret" with leave and ret <number> (if stdcall). I've read in Intel's Opt Guide that it's better not to use leave. How I suppose to make masm not to replace "ret"?? Thanks.

P.S.: I know that you can do by leaving the "proc" and using label, but in that way the code is really messy and if you have to rewrite something you are dead.

MichaelW

This code times procedures with and without leave (and the corresponding push ebp / mov ebp, esp).

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc
    .586
    include timers.asm

    wleave  PROTO :DWORD,:DWORD
    woleave PROTO :DWORD,:DWORD
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    .data
    .code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    LOOP_COUNT equ 10000000
   
    counter_begin LOOP_COUNT, HIGH_PRIORITY_CLASS
      invoke wleave, 1, 2
    counter_end
    print ustr$(eax)
    print chr$(" cycles",13,10)

    counter_begin LOOP_COUNT, HIGH_PRIORITY_CLASS
      invoke woleave, 1, 2
    counter_end
    print ustr$(eax)
    print chr$(" cycles",13,10)

    inkey "Press any key to exit..."
    exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
nops 4
align 4

wleave proc arg1:DWORD, arg2:DWORD
    mov   eax, arg1
    mov   edx, arg2
    ret
wleave endp
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE

align 4

woleave proc arg1:DWORD, arg2:DWORD
    mov   eax, [esp+4]
    mov   edx, [esp+8]
    ret 8
woleave endp

OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start

(The four nops make the procedures easier to find in the disassembly)

004011FD 90                     nop
004011FE 90                     nop
004011FF 90                     nop
00401200 90                     nop
00401201 8D4900                 lea     ecx,[ecx]
00401204                    fn_00401204:
00401204 55                     push    ebp
00401205 8BEC                   mov     ebp,esp
00401207 8B4508                 mov     eax,[ebp+8]
0040120A 8B550C                 mov     edx,[ebp+0Ch]
0040120D C9                     leave
0040120E C20800                 ret     8
00401211 8D4900                 lea     ecx,[ecx]
00401214                    fn_00401214:
00401214 8B442404               mov     eax,[esp+4]
00401218 8B542408               mov     edx,[esp+8]
0040121C C20800                 ret     8

On my P3 the advantage is 2 clock cycles, IMO meaningful only for very fast procedures.

5 cycles
3 cycles



[attachment deleted by admin]
eschew obfuscation

zooba

Quote from: MichaelW on January 08, 2006, 12:11:34 AM
wleave proc arg1:DWORD, arg2:DWORD
    mov   eax, arg1
    mov   edx, arg2
    ret
wleave endp
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE

align 4

woleave proc arg1:DWORD, arg2:DWORD
    mov   eax, [esp+4]
    mov   edx, [esp+8]
    ret 8
woleave endp

OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef

If you don't have any local variables declared in your procedure then this works fine. Otherwise, if you don't use the default epilogue or the LEAVE opcode, you need to add this to the end of the proc:

mov  esp, ebp
pop  ebx


Which is exactly what LEAVE does, except porting to 64-bit code won't require changing the LEAVE opcode, whereas the code above will need RSP and RBP. I also think LEAVE will throw extra exceptions if there is invalid data anywhere, but I haven't checked nor confirmed this.

Cheers,

Zooba :U

hutch--

Here is a test piece I did for Pelle and on the PIV I use there is no meaningful timing difference.


; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

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

    lcnt equ <300000000>

    .code

start:
   
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

    call main
    inkey
    exit

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

main proc

    LOCAL total1    :DWORD
    LOCAL total2    :DWORD

    invoke SetPriorityClass,FUNC(GetCurrentProcess),REALTIME_PRIORITY_CLASS

    mov total1, 0
    mov total2, 0

  REPEAT 8

  ; =============

    push esi
    mov esi, lcnt

    invoke GetTickCount
    push eax

  @@:
    call with
    sub esi, 1
    jnz @B

    invoke GetTickCount
    pop ecx
    sub eax, ecx
    add total1, eax

    print str$(eax)," leave",13,10

    invoke SleepEx,100,0

  ; =============

    mov esi, lcnt

    invoke GetTickCount
    push eax

  @@:
    call without
    sub esi, 1
    jnz @B

    invoke GetTickCount
    pop ecx
    sub eax, ecx
    add total2, eax

    print str$(eax)," mov-pop",13,10

    invoke SleepEx,100,0

    pop esi

  ; =============

    ENDM

    invoke SetPriorityClass,FUNC(GetCurrentProcess),NORMAL_PRIORITY_CLASS

    shr total1, 3
    shr total2, 3

    print str$(total1)," average for LEAVE",13,10
    print str$(total2)," average for MOV-POP",13,10

    ret

main endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

align 16

with:
    push ebp
    mov ebp, esp
    sub esp, 16

    nop
    nop
    nop
    nop

    leave
    retn

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

align 16

without:

    push ebp
    mov ebp, esp
    sub esp, 16

    nop
    nop
    nop
    nop

    mov esp, ebp
    pop ebp
    retn

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

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

GODlike

Thanks for the help guys. Appreciated!! The "OPTION EPILOGUE:NONE" did the trick.