3 questions:
1. Is it possible to make MASM generate reference for locals instead of ?
2. How to turn off _temporary_ generation of epilogue code
for or how to turn it back without suppling macro.
a1 proc
OPTION EPILOGUE:NONE ;
ret
..
...
ret
;
OPTION EPILOGUE : __? ; now I need to turn it on
ret; exit
endp
3. How to make MASM use pop instead of 'bad' instruction "leave"
in the epilogue code.
1. Is it possible to make MASM generate reference for locals instead of ?
2. How to turn off _temporary_ generation of epilogue code
for or how to turn it back without suppling macro.
a1 proc
OPTION EPILOGUE:NONE ;
ret
..
...
ret
;
OPTION EPILOGUE : __? ; now I need to turn it on
ret; exit
endp
3. How to make MASM use pop instead of 'bad' instruction "leave"
in the epilogue code.
HERE is a more advanced demonstration that answers most of your questions. It is not possible to have MASM automatically use instead of creating the stack frame. Chapter 9 of the MASM manual (towards the end) is a good read.
Here's a sample code on using locals without frames:
myfunc PROC
sub esp, 20 ;Allocate 20 bytes for our variable
mov DWORD PTR [esp], "lleH"
mov DWORD PTR [esp+4], "rC o"
mov DWORD PTR [esp+8], " leu"
mov DWORD PTR [esp+12], "lroW"
mov BYTE PTR [esp+16], "d"
mov BYTE PTR [esp+17], 0
lea eax, [esp] ;Load the address of the variable
invoke MessageBox, NULL, eax, NULL, MB_OK
add esp, 20
retn
myfunc ENDP
Here's a screenshot from a disasm view, to prove that there are no frames.I don't know why you have to make things so hard, stryker. :grin:
proto9 typedef proto :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD
invoke proto9 PTR [MessageBox], 0, ADDR [esp+8], 0, 0, 6C6C6548h, 7243206Fh, 206C6575h, 6C726F57h, 2E64h
add esp,20
lol!!! :grin: I like it this way!
I like that code above too. Never tried that yet!!! :)
I like that code above too. Never tried that yet!!! :)
Can't you make macros for push and pop which keeps track of the offset to the locals. But that would mean that you couldn't push and pop as you want.
gliptic, yes and it works except for loops that push/pop.
What are the internal names for default prologue epilogue macros?
For example
OPTION EPILOGUE: default.
BTW can anybody suggest a link to MASM Programmer's Guide in one downoadable file.
BTW, Intel recommend use for leaf procedures ( ebp only for debug purposes )and avoid using complex instructions like 'leave' (also mov , const
comparing to push ). So comparing to the code generated by compilers in optimized mode (I checked cl.exe /O2 ) , code produced by ASSEMBLER ( MASM) using default macros doesn't look very good. :(
For example
OPTION EPILOGUE: default.
BTW can anybody suggest a link to MASM Programmer's Guide in one downoadable file.
BTW, Intel recommend use for leaf procedures ( ebp only for debug purposes )and avoid using complex instructions like 'leave' (also mov , const
comparing to push ). So comparing to the code generated by compilers in optimized mode (I checked cl.exe /O2 ) , code produced by ASSEMBLER ( MASM) using default macros doesn't look very good. :(
AMD recommends using LEAVE instruction... Now what? :confused:
Can ebp be zero out. Can i kill it sometime or change it. I think someone said he did something like that but did not explain how... i'm not sure...
3 questions:
1. Is it possible to make MASM generate reference for locals instead of ?
2. How to turn off _temporary_ generation of epilogue code
for or how to turn it back without suppling macro.
3. How to make MASM use pop instead of 'bad' instruction "leave"
in the epilogue code.
2. The defaults are turned on with:
OPTION PROLOGUE:PROLOGUEDEF
OPTION EPILOGUE:EPILOGUEDEF
3. You have to write a custom epilogue macro for this.
What are the internal names for default prologue epilogue macros?
BTW, Intel recommend use for leaf procedures ( ebp only for debug purposes )and avoid using complex instructions like 'leave' (also mov , const comparing to push ). So comparing to the code generated by compilers in optimized mode (I checked cl.exe /O2 ) , code produced by ASSEMBLER ( MASM) using default macros doesn't look very good. :(
MASM is old compared to VC++ and is updated less frequently. It is left up to the programmer to create more optimal code than the outdated code produced by the HL syntax. It still does well on an Athlon CPU. A replacement for MASM is long overdue, but it is not an easy task - MASM is very complex.
Here are a couple of simple macros that solve the problem of stack entry and exit. The assigned variable in one holds its value in the next so the value for the byte count in the first used on esp can be used again in the next one to correct the stack.
This generates the code,
Regards,
hutch@movsd.com
; #########################################################################
.486
.model flat, stdcall
option casemap :none ; case sensitive
; #########################################################################
proc_entry MACRO bytes:REQ
LOCAL start
start equ <sub esp, >
var = bytes ;; assignment works across different macros
start CATSTR start,%var ;; use it here locally
start
ENDM
proc_exit MACRO
LOCAL end
end equ <add esp, >
end CATSTR end,%var ;; use it again in next macro
end
ENDM
; #########################################################################
.code
start:
proc_entry 20
xor eax, eax
proc_exit
; #########################################################################
end start
This generates the code,
00401000 start:
00401000 83EC14 sub esp,14h
00401003 33C0 xor eax,eax
00401005 83C414 add esp,14h
Regards,
hutch@movsd.com
Condensed Version:
Super Condensed Version:
proc_entry MACRO bytes:REQ
;; assignment works across different macros
var = bytes
sub esp, bytes
ENDM
proc_exit MACRO
% add esp, var
ENDM
Nesting would be nice. :)
Super Condensed Version:
proc_entry MACRO bytes:REQ
sub esp, bytes
;; assignment works across different macros ;)
proc_exit MACRO
add esp, bytes
ENDM
ENDM
:grin: :grin:
; #########################################################################
proc_entry MACRO name,bytes:REQ
LOCAL start
name:
start equ <sub esp, >
var = bytes ;; assignment works across different macros
start CATSTR start,%var ;; use it here locally
start
ENDM
proc_exit MACRO
LOCAL end
end equ <add esp, >
end CATSTR end,%var ;; use it again in next macro
end
retn
ENDM
; ###################################
.code
start:
call proc1
proc_entry proc1, 20
call proc2
proc_exit
proc_entry proc2, 20
mov eax, 1
proc_exit
Generates the code,
00401000 start:
00401000 E800000000 call fn_00401005
00401005 fn_00401005:
00401005 83EC14 sub esp,14h
00401008 E804000000 call fn_00401011
0040100D 83C414 add esp,14h
00401010 C3 ret
00401011 fn_00401011:
00401011 83EC14 sub esp,14h
00401014 B801000000 mov eax,1
00401019 83C414 add esp,14h
0040101C C3 ret
Regards,
hutch@movsd.com
Well, I mean - nesting:
proc_entry 20
xor eax, eax
proc_entry 20
xor eax, eax
proc_exit
proc_exit
With no CALL overhead.Yes,
you are right, the two macros must be symetrical but this is not really a problem as MASM requires this anyway in its own PROC syntax.
I would imagine that a proc nested in the way your example is done would need to be written differently. A jump to a label and a following RETN within the scope of an existing proc is common use so its a matter of whether the stack needs to be preserved within an existing proc anyway.
Regards,
hutch@movsd.com
you are right, the two macros must be symetrical but this is not really a problem as MASM requires this anyway in its own PROC syntax.
I would imagine that a proc nested in the way your example is done would need to be written differently. A jump to a label and a following RETN within the scope of an existing proc is common use so its a matter of whether the stack needs to be preserved within an existing proc anyway.
Regards,
hutch@movsd.com
AMD recommends using LEAVE instruction... Now what? :confused:
Not just AMD. Intel recommends it for P6, too. (I do not have Intel's optimization guide for P5, so I don' know about P5.) In fact, leave is a 3 micro-op instruction and we don't need to worry about decoding bottleneck on P6. Moreover, it is only one byte long and it is logically plausible that using leave is better than mov esp,ebp / pop ebp combination. I don't know if it is actually better, but I don't care, because leave is usually followed by ret and I don't think I would enjoy any big speed gain by not using leave. :)
I agree with Starless here, if a block of code is small enough and speed critical enough, you write it inline and forget about using the call/ret syntax or the stack. Its when you want block code that can be accessed from a range of different places that you use a procedure.
I have yet to see any blazing speed differences in stack entry and exit and LEAVE does generate small code that seems to work fine.
Regards,
hutch@movsd.com
I have yet to see any blazing speed differences in stack entry and exit and LEAVE does generate small code that seems to work fine.
Regards,
hutch@movsd.com