Hi all.
I'm using the following macro in my ASM Runtime for all the prologues, as well as the default prologue macro for programs using it (to assist with compatibility with the error handling). However, I'm finding that the following statement is causing problems:
ConsoleCreate PROC FORCEFRAME
In theory, and AFAICT the code matches the theory, this should do a push ebp/mov ebp,esp and a leave/ret 0 at the top and bottom of the procedure. However, for some reason it actually does a ret 4, and the code for forcing a stack frame never gets executed. It appears that MASM is interpreting the FORCEFRAME argument as a parameter.
The best workaround I have so far is to define a local variable that never gets used. This only costs a subtract (add esp, -4) so it's alright in performance terms, but I'd rather be able to use the FORCEFRAME parameter.
Here is the prologue function:
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;
; MASM Stack Probing PROLOGUE macro
; by chep, 2005/07/04
;
; Parameter bytes stored in ML equate added by Zooba, 02/01/2006
; Stack frame always created for Assert compatibility, 25/06/2006
; Renamed ASMRTPrologue by Zooba, 25/06/2006
;
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ASMRTPrologue MACRO procname, flags, argbytes, localbytes, reglist, userparms:VARARG
LOCAL parm, reg, probe, max_probe, line, page_size, unrolled, @rolled
;; Memory page size, can be changed for other architectures
page_size = 4096
;; Use unrolled probing by default
unrolled = 1
;; Don't force a stack frame unless told to
forceframe = 0
;; Throw an error if not in FLAT model, because stack probing is irrelevant otherwise
IF @Model NE 7
line TEXTEQU %@Line
% ECHO @FileCur(line) : STACKPROBE prologue ERROR: stack probing is irrelevant if not using FLAT model
.ERR
EXITM <1>
ENDIF
;; Detect macro arguments, give a warning if unknown argument
IFNB <userparms>
FOR parm,<userparms>
IFIDNI <parm>,<ROLLED>
unrolled = 0
ELSEIFIDNI <parm>,<FORCEFRAME>
forceframe = 1
ELSE
line TEXTEQU %@Line
% ECHO @FileCur(line) : STACKPROBE prologue warning: unknown prologue argument : parm
ENDIF
ENDM
ENDIF
parameter_bytes = -1
IF localbytes GT 0
;; Set up stack frame
push ebp
mov ebp, esp
max_probe = (localbytes+page_size-1) AND (-page_size) ;; round up to next page size
IF localbytes LT page_size
;; Normal stack frame, no probing
add esp, (-localbytes)
ELSEIF unrolled
;; Unrolled stack probing
probe = page_size
WHILE probe LE max_probe
;; Probe stack
mov DWORD PTR [ebp-probe], eax
probe = probe + page_size
ENDM
add esp, (-localbytes)
ELSE
;; Rolled stack probing
add ebp, (-max_probe)
@rolled:
mov DWORD PTR [ebp], eax
add ebp, page_size
cmp ebp, esp
jne @rolled
add esp, (-localbytes)
ENDIF
parameter_bytes = argbytes
ELSEIF argbytes GT 0
;; Set up stack frame
push ebp ; this code gets executed instead of the next block
mov ebp, esp
parameter_bytes = argbytes
ELSEIF forceframe NE 0
push ebp ; this code never gets executed
mov ebp, esp
parameter_bytes = argbytes
ENDIF
;; USES clause
IFNB <reglist>
FOR reg,reglist
push reg
ENDM
ENDIF
EXITM <0>
ENDM
I solved my problem.
User parameters for a PROC statement need to be inside angle-brackets:
ConsoleCreate PROC <FORCEFRAME>
Incidentally, I'm no longer using Chep's prologue macro anymore since I've completely rewritten my own from scratch. Thanks for the leg up though, Chep :u