official macro set breaks paradigm of producing minimal possible code
There is no matter present args & locals or not. Only matter used they or not.
Test sequence:
proc test arg1,arg2
locals
a dd ?
endl
xor eax, eax
ret
endp
how to fix proc32.inc for proper handling?
1) replace condition "parmbytes | localbytes" with "used@frame" in prologuedef & epiloguedef macros pass that condition via macro args.
2) Also make used@frame as local for macro define@proc because outside of proc using it is unusable.
3) In every proc used@frame is setted only once in finish@proc macro by assignig final value of global used@frame@test: used@frame = used@frame@test
4) before handling of args (before using macro prologue) we initialize used@frame@test: used@frame@test = 0
5) then we make accumulation of used@frame@test if any arg or local var used in proc - we doing that in 2 macros:
for every arg of defargs@proc (for every - in any forward block)
if used ..arg
used@frame@test = 1
end if
for every local defined with deflocal@proc macro (here in common block because forwarding goes via values of current local)
if used name
used@frame@test = 1
end if
affected pieces:
macro prologuedef procname,flag,used@frame,parmbytes,localbytes,reglist ; patch line
{ local loc
loc = (localbytes+3) and (not 3)
parmbase@proc equ ebp+8
localbase@proc equ ebp-loc
if used@frame ; patch line
push ebp
mov ebp,esp
if localbytes
sub esp,loc
end if
end if
irps reg, reglist \{ push reg \} }
...
macro epiloguedef procname,flag,used@frame,parmbytes,localbytes,reglist ; patch line
{ irps reg, reglist \{ reverse pop reg \}
if used@frame ; patch line
leave
end if
if flag and 10000b
retn
else
retn parmbytes
end if }
...
macro define@proc name,statement
{ local params,flag,regs,parmbytes,localbytes,current,used@frame ; patch line
...
match =regs, regs \{ regs equ \}
used@frame@test = 0 ; patch line
match prologue:reglist, prologue@proc:<regs> \{ prologue name,flag,used@frame,parmbytes,localbytes,reglist \} ; patch line
...
match , operand \\{ match epilogue:reglist, epilogue@proc:<regs> \\\{ epilogue name,flag,used@frame,parmbytes,localbytes,reglist \\\} \\} \} ; patch line
macro finish@proc
\{ localbytes = current
used@frame = used@frame@test ; patch line
match close:reglist, close@proc:<regs> \\{ close name,flag,parmbytes,localbytes,reglist \\}
end if \} }
...
macro defargs@proc [arg]
{ common
if ~ arg eq
forward
local ..arg,current@arg
match argname:type, arg
\{ current@arg equ argname
label ..arg type
argname equ ..arg
if qqword eq type
dd ?,?,?,?,?,?,?,?
else if dqword eq type
dd ?,?,?,?
else if tbyte eq type
dd ?,?,?
else if qword eq type | pword eq type
dd ?,?
else
dd ?
end if \}
match =current@arg,current@arg
\{ current@arg equ arg
arg equ ..arg
..arg dd ? \}
if used ..arg ; patch line
used@frame@test = 1 ; patch line
end if ; patch line
common
args@proc equ current@arg
forward
restore current@arg
common
end if }
...
macro deflocal@proc name,def,[val]
{ common
match vars, all@vars \{ all@vars equ all@vars, \}
all@vars equ all@vars name
forward
local ..var,..tmp
..var def val
match =?, val \{ ..tmp equ \}
match any =?, val \{ ..tmp equ \}
match any (=?), val \{ ..tmp equ \}
match =label, def \{ ..tmp equ \}
match tmp : value, ..tmp : val
\{ tmp: end virtual
initlocal@proc ..var,def value
virtual at tmp\}
common
match first rest, ..var, \{ name equ first \}
if used name ; patch line
used@frame@test = 1 ; patch line
end if } ; patch line