ok, that is right :), lol, and the other thing?? with the lea, and a new form of call using only mov's instead of pushes??

call will get me the return addres and the jmp i want :)

a yep, only a thing, then the call have some specific circuit that executes like a push eip and the jump, but have (oops.. i am not in my computer :S )have... like two instructions expanded with only one .
Posted on 2003-03-12 07:46:38 by rea
INVOKE can be used with the macros listed above:
	invoke SetWindowLong, WndProc_hWnd[4*2], GWL_USERDATA, ebx
...but it would be better if MASM gave us access to the INVOKE mechanism through macros - like with EPILOGUE/PROLOGUE. In the above line of code WndProc_hWnd is on the stack and defined by an EQU. We add to the offset by the number of pushed parameters times four.

Now the last remaining bits seem to be dynamic code: branches or dynamic allocations on the stack. For dynamic allocations I use a register to hold the size of the dynamic buffer and then add this to the _push/_pop/invoke items:
	invoke GetClientRect, WndProc_hWnd[4 + esi], ADDR [ebx].rek
For branching...I try not to. :) Actually, the code is done manually and looks very ugly presently.
Posted on 2003-03-12 08:15:45 by bitRAKE
Done some more experimenting. Is there any way to get code between the proc declaration and the LOCAL macro?

LclHeapAlloc PROC PUBLIC heapstruc$:PTR DWORD,allocsize$:PTR DWORD
local foo:DWORD
align 4

I'd likie to redirect ebp before the local directive, but inside the proc to point to my own structure in memory. Then I can leverage the fact that using locals will automatically calculate the offset from ebp.

I did manage to get it to work us db and opcodes(MASM wont let me use code, but opcodes are okay :rolleyes: )
There error code I get when using real code:

A2012:PROC, MACRO, or macro repeat directive must precede LOCAL

I guess a macro would work? Dont know anything about how to use macros. Never seen a macro writing tutorial.
Is a macro a text processor, or code processor? Do I need to write opcodes?

I'm trying to get a line like:

lea ebp,

Between the proc definition and LOCAL directive.

Posted on 2003-03-12 09:14:25 by ThoughtCriminal
also is a text preprocesor almost in nasm, but is lie the preprocesor of C/c++ or any other preprocessor the only that do is some operations and insert code, for example a pushn

(a macro isn't a text preprocesor, the text preprocesor have its how directives (one of this is for define macros, include files, etc), the macro is interpreted or expanded by the text preprocesor, also i know a idea about postprocesor.

%macro pushn 1-* ;say to the preprocesor we want define a mutiline macro
%rep %0
push %1
%rotate 1
%endmacro ;terminate


pushn eax, ebp, ecx ;this is now definied by the preprocesor, and then it know where are the implementation, is like a inline procedure or function

will expanded to

push eax
push ebp
push ecx

also, i need to say, the problem regarding to the first write all the LOCAL vars and then write the code like in the old C, that you need put all the locals vars ath the start of the function that are writting, also the version that modificates nguga have this problem, i say in the other post, the problem i wil try explain

i dont know how to explain in words.. then a example

in the nguga modificated version is like this:

funct holaMundo, uno, dos, tres
;no code here
local hwnd, 4, wnd, WNDCLASSEX, msg, MSG
;code here

that is similar to code in masm

holaMundo proc uno:DWORD, dos:DWORD, tres:DWORD
;no code here
local hwnd:HWND
local wnd:WNDCLASSEX
local msg:MSG
;code here

in (1) and (2)the problem is when you know how many to substract to the ESP first think this, in the process of assignate to each name (hwnd, wnd, msg) the respective ebp-4, ebp-42, ebp-60 i dont remember the correct sizes, this definitions are like constants you cant change, but what append if you make some like this:

LOCAL hwnd:HWND ;hwnd is ebp-4
push ebx ;you now modificate esp, then
LOCAL some:HWND ;some is definied by ebp-8 (see, the LOCAL dont know that you make a push and define like ebp-12 instead ebp-8)

example in the stack:

;this is where the normal pushes and pop take place
;<-----this place is where esp are

;the space here are allocated by sub esp, some

;<<---------- this is the base or the ebp

this dont make sense, if you add or not pushes, but the problem is that the definitions for LOCAL are in only one direction, or follow only one direction, never know that you make some pushes or other instructions, then for dont take the posible error while coding some like in the above, in masm you need put all the LOCAL directives or declarations at the start and after any instruction... you understand hwnd always gona be ebp-4, hwnd --> ebp-36, and msg --> ebp-58, for this masm needs that you put your locals at the start :) (if you add a push, you modificate this constant values, and this cant append)

as you can see in the little representation of the stack, if the definitions for the names are secuentially.. that is the correct word, then if you try add a instruction between the LOCALS, the posibility for get a incorrect direction for a name is high (refering to the saved value of ebp, instead the local value of some var), then, this is why masm need all the locals in the start.

Also i can aviod this in the macro i code, but is with the use of sizef, and in the version of nguga modificates for work like in masm, and tasm (all the locals in the start), also the little tip for i can use a local declaration in my own macro elsewhere is count how many space need the locals at the end of the funct, and then substractit with a message, you dont need calculate :D and then i can code some like:

funct WndProc, hWnd, uMsg, wParam, lParam
sizef 58
local wnd, WNDCLASSEX
mov dword[.wnd+WNDCLASSEX.lpszMenuName], 0
;....... more code
local hwnd, 4
mov dword[.hwnd], eax
;....... more code

the trick is with endfunct, i not only terminate the function, also, i have now the count of all the local vars that i add :), and this is correct

have a nice day.
Posted on 2003-03-12 10:39:00 by rea
Interresting in hgb.

If anyone knows a website with MASM macro tutorials, please direct me to it :grin:

I tried writing a macro but only go errors :(

But it seems I did not need a macro at all :)

HeapInit PROC PUBLIC initsize$:PTR DWD
lea ebp,[HeapDesc+(5*4)]

Apparently putting it after is the same as putting it above(with db and opcodes).
I guess LOCAL is link-time resolved?

If anyone wonders what crazy stuff I'm up to...
Since I dont use ebp for a stack frame, I thought I'd modify ebp to point to structures used in a proc.
Then I can leverage LOCALs behavior to get my variavle as an offset from ebp:

mov [LPHEAP+.HeapTop],edx
00401616 89 55 F0 mov dword ptr [ebp-10h],edx
mov [LPHEAP+.HeapPtrCur], eax
00401619 89 45 F8 mov dword ptr [ebp-8],eax

Are memory moves any faster when with reg+offset compared to just an address?
Hmmm reg+offset is 3 byte, but and address is 6 bytes:

mov [HeapDesc+.HeapTop],edx
00401616 89 15 24 61 40 00 mov dword ptr [_HeapTop (406124h)],edx
mov [LPHEAP+.HeapPtrCur], eax
0040161C 89 45 F8 mov dword ptr [ebp-8],eax

There is a size benefit.

Posted on 2003-03-12 21:53:13 by ThoughtCriminal
nope, the are not resolved in the link-time

the locals are definied in the assemble-time, also in the preprocessor (i think if local is most like a macro), the size that the vars will use is know after start assembly, and the real addres of the locals are definied at run-time, for example, now you know that for example:

winProc proc ... , lParam:LPARAM
local hwnd:HWND ;the size is 4 or dowuble word. hwnd isw definied like ebp-4
local hdc:HDC ;the size is 4. hdc is definied like ebp-8 or ebp-(4+4) see the anterior size of the local var
;internally added enter 0,0 and sub esp,8

the total size of the locals are 8 (4+4) --> sub esp,8 or add esp,-8 this is for "preserve space" first, then all the normal pushes and pops (in pairs) dont take effect over the space of the locals, also remember hwnd is definied like ebp-4 and hdc is definied like ebp-8

also you can see stack where is a try to explain how it work in the run-time (only see the 2 figures, the other things.. are my first try).


-- The locals are definied in time of assembly and with the added sub esp, some reserve the space, for the next pushes and pops dont corrupt the data in the locals vars.

-- The space is reserved in runtime, and the addres of the locals are definied in time of assembly (also remember they are ebp-some) is not a effective addres, is a relative addres from ebp, and maybe ebp not always have the same addres, this is way are relative to ebp and why locals vars cant preserve they value between calls.

Have a nice day.
Posted on 2003-03-14 00:17:24 by rea
also i need a little more help, tell me if my concepts are worg, respect to the use with ESP instead EBP

when ypu call, the esp modificates is value , and some call like ths:


call hola, arg1, arg2, arg3, arg4,...,argN will cause this:

------------------------------- <--here is where point esp
; 4


[.....] <--more values
<--- where the ebp point, it dosent matter (dont alterate by the call)

the the values for arg1 is 4 plus 4 of the return addres, then args can be definied some like this:

arg1 esp+8
arg2 esp+12
argN esp+(4*N) where N is is the number of args


if you gona use local vars, i think is not good in time

_push eax, _D ; give it a name, too
_push eax, _E
_push eax, _F
_push eax, _G
_push eax, _H

if i understand right this, you are saying push eaxh value to the stack, and by this way reserve the space in the stack, is right this?? push the locals values for reserve space for they??, if this is, i think is best know how many space need the locals and do the reservation of the space by a sub esp, (spaceForLocals) like in the use with EBP and the sub, spaceForLocals Will Cause some like this:

------------------------------- <--here is where point esp


------------------------------- <--- the anterior place of ESP
; 4


[.....] <--more values
<--- where the ebp point, it dosent matter (dont alterate by the call)


if you push some, you need be carrefull and add to the "offset" or "displacement" to the "anterior" names, like in calls inside your procedure the corresponding pop are valanced in the other procedure and maybe see some like this:

------------------------------- <---here is where point esp


------------------------------- <--the anterior place where point ESP


------------------------------- <--- the anterior place of ESP
; 4


[.....] <--more values
<--- where the ebp point, it dosent matter (dont alterate by the call)

if you join (1), (2), (3)

you will see that are stackDept (referring to normal pushes in a function, like calls, or save of values or registers)
and localsDept(refering to the space that we reserve for the locals)

then the last graph can be showed some like this:

------------------------------- <---here is where point esp _____
[OtherPushes] |
[moreParamsForCalls] |---> this is stack depth (see *)
[...] |
[someargForACall] |
[otherPushForSaveARegister] --------
------------------------------- <--the anterior place where point ESP ____
[more garbage] |
..... | --->this is local Depth (see **)
..... |
[garbage] -------
------------------------------- <--- the anterior place of ESP ________________________
[return address] ;4 |
[arg1] ; 4 |
[arg2] |
[arg3] | -->the args
[...] |
[argN] |
[.....] <--more values |
[some value] <--- where the ebp point, it dosent matter (dont alterate by the call)--------------[EDITED dont create a stack frame]

then you now know how is organized this thing..

then you can say the argument in (1) will be definied some like this

arg1 ebp +8
arg2 ebp +12

but in (2) the argumensta are definied some like

arg1 ebp+8+localDept
arg1 ebp+12+localDept

where localDept we know (we substract the right space for our locals)

the locals are definied if local1 is WNDCLASS and local2 is MSG some like this

local1 esp+32 ;i dont remember the number
local2 esp+32+28

also in (3) the args are definied some like:

arg1 ebp+8+localDept+stackDept
arg2 ebp+12+localDept+stackDept

and the locals are definied if local1 is WNDCLASS and local2 is MSG some like this

local1 esp+32+stackDept
local2 esp+60+stackDept

*The localDept can be knowed and is constant
**The stackDept is not constant, and is modificated by pushes or pops, also the pushes of a call need be balanced in the same call or after, for no alterate the stackdept of the function, for example

;stackDept is 50
call MessageBoxA, NULL, "Hola", "Que pasa", MB_OK ;in this moment, stackdept is 66
;now stackdept is 50, dont get alterations by calls
push eax
;now stackDept is 54
;a finall thing, when we return, the esp need be in the start in (1), the we need make some like add esp, stackDept+localDept and now esp is pointing to the return address and the args passed in (1)

i think that is all, i have the macro near from be usable, also i need see how i am implementing.... remember is in nasm, but i think when done, you can see and maybe if you find some usage you can traslate to your macro language of your assembler


Have any other sugestions??

Have a nice day:alright:
Posted on 2003-03-14 16:03:23 by rea
a yea, i see that the above is right, now i terminate the macro and can be used so easely, only put optionUseESP or optionUseEBP the default is EBP and without any modification you can obtain the two methods ;D directly, like a feature, you can join boot , put the above instructions and you can combine this methods.

Also the only problem to show you is that i am now incomunicated, my comp dont have disk 3,1/2 or Internet, my bro apparently sold or rendered the red cable, also no have CDR lol, but i will take the floppy of this computer and save the macro, also i do some little test, and work like a charm, also i have some observations now, and are:

-- Is easy to use, and change directly without modification to code for use UESP or EBP.

-- Windows dont like the option for use ESP:

for example, i debug the translated icztut5(in nasm) with the ollyDbg, and for example when i use the default option that is with EBP and the stack frame, i can Register the class With RegisterClassEx, get a right value, then CreateTheWindow and get a right value, in fact the programm work good. The values passed to CreateWindowEx are:


ExStyle = "0"
Class = "ClasName"
WindowName ="Usando EBP" ; <------- this string is definied with %if useEBP "EBP" %elif %useESP "ESP" %endif, get the idea???
hParent = NULL
hMenu = NULL
hInst = 0012FFB4
lParam = NULL

the return value in EAX = 003D0282

But when i use the optionUseESP, also i can call RegisterClasEx and the return value in EAX is the same that when i use EBP, also the values passed to CreateWindowEx, are nearly the same escept for the WindowName, that i make a choice with help of the preproscesor and get "Using EBP" or "Using ESP", the values with ESP passed to CreateWindowEx are:

ExStyle = "0" ;equal
Class = "ClasName" ;equal
WindowName ="Usando ESP" ; <------- ESP
X=800000000 ;equal
Y=800000000 ;equal
WIDT=800000000 ;equal
HEIGHT=800000000 ;equal
hParent = NULL ;equal
hMenu = NULL ;equal
hInst = 0012FFB4 ;equal
lParam = NULL ;equal

and the value reurned in EAX = 00000000

now i think that some functions in the WinAPI need the use of the stack frame, i dunno for what, but like you see, the values are right and i check, and the proof case is that i First Use RegisterClassEx and return to me the correct result, also CreateWindowEx isn't do this, the values are almost equals and give for result a EAX=0

The value by RegisterClassExA retornated in bot cases (with ESP and EBP) are

EAX = 0000C144

But no is a problem for the macro, i say you i test with others more simple functions, also the proof is RegisterClassExA.

For terminate, the displacements or the correct values are generated by the macro inbot cases with use of EBP and ESP:

NOTE IN THE NEXT: the values for the locals are saved from start to the end, also you can say for example:

[.hwnd] EBP-80 ;the addres here is 1000-80 = 920 i think
[.msg] EBP-76
[.wndC] EBP-48
#### member 13
;For example address in decimal 1000

****For EBP (Stack Frame) values Generated are:

------------------------- <---ESP point here
[.hwnd] is definied by EBP-80
[.msg] is definied by EBP-(48+28) or EBP-76
[.wndC] is definied by EBP-48
------------------------- <--- EBP point here
;This is the stack frame
THE ret addr at EBP+4
[.hInstancia] is definied by EBP+8
[.hPrevInst] -->EBP+12
[.lpCmdLine] --->EBP+16
[.nCmdShow] ---->EBP+20

****For ESP values Generated are:

[....] posible stackDept here (a modificate ESP), is handle with stackDept
------------------------------- <----ESP point here
[.hwnd] is definied like ESP (remember the order that the values are saved in memory)
[.msg] is definied like ESP+4
[.wndC] is definied like ESP+32
EBP+80 (See no stack frame)
[.hInstance] EBP+84
[.hPrevInstance] EBP+88
[.lpCmdLine] EBP+92
[.nCmdShow] EBP+96

also i be carefull with the stackDept when use ESP.

Now i Think this is done :D, the question is what functions dont need stackFrame like RegisterClassExA, and what other need like CreateWindowEx ????

I will upload this macro to my little site, and send to naguga, also i see a little bug :D in the past (when i get floppy, internet or the cable for connect the LAN)

Have a nice day.
Posted on 2003-03-15 09:23:09 by rea
CreateWindowEx will call your window proc routine, so check that EBP is preserved there. There's at least one C routine being used in the call chain. I'm guessing your EBP option also affects the window proc routine. If you use EBP for some other purpose than as a stack frame, it must be restored before you return.
Posted on 2003-03-16 03:34:20 by tenkey
i thing is restored ok, now i will put my macro here (in nasm) i say you, i think work ok, also i put a little example and the output

hi, here is the macro whit a little example of how to use, like you see, can combine the "technic" or use one and latter use other

%include '\lab\vasm\inc\nagoa.inc'
%include '\lab\vasm\inc\f.inc'

[COLOR=teal];our functions, if not define, get a error[/color]

def unoWhitESP
def unoWhitEBP
def dosWhitESP
def dosWhitEBP
def dummyEBP
def dummyESP

segment code class=code use32

call GetModuleHandle, NULL
var Instancia, 4
mov dword[Instancia], eax
call dummyESP,4,4,2,2
call dummyEBP, 3,3,6,6
call unoWhitESP,1,2,3,4
call unoWhitEBP,5,6,7,8
call dosWhitESP, 9,8,7,6
call dosWhitEBP,5,4,3,2
call ExitProcess, eax

[COLOR=teal];dummy functions only show you the manage without locals
;here we use the default is with stack frames (EBP)[/color]
funct dummyEBP, darg1, darg2, darg3, darg4
mov eax, [.darg1]
mov eax, [.darg4]

funct dummyESP, darg1, darg2, darg3, darg4
mov eax, [.darg1]
mov eax, [.darg4]

[COLOR=teal];unoWhitE.P show you how handle functions without locals and having pushes[/color]
funct unoWhitESP, arg1, arg2, arg3, arg4
mov eax, [.arg1]
mov edx, [.arg4]
push eax
mov eax, [.arg1]
push eax
mov eax, [.arg1]

funct unoWhitEBP, arg1, arg2, arg3, arg4
mov eax, [.arg1]
mov edx, [.arg4]
push eax
mov eax, [.arg1]
push eax
mov eax, [.arg1]

[COLOR=teal];dosWhitE.P show you how handle some with locals and above you use pushes[/color]
funct dosWhitEBP, arg1, arg2, arg3, arg4
sizef 48
mov eax, [.arg1]
mov edx, [.arg4]
local wndC, WNDCLASSEX
mov eax, [.arg1]
mov edx, [.arg4]

funct dosWhitESP, arg1, arg2, arg3, arg4
sizef 48
mov eax, [.arg1]
mov edx, [.arg4]
local wndC, WNDCLASSEX
mov eax, [.arg1]
mov edx, [.arg4]

The olly says :D

00401000 >6A 00 PUSH 0
00401002 FF15 44304000 CALL DWORD PTR DS:[<&kernel32.GetModuleH>; kernel32.GetModuleHandleA
00401008 A3 00204000 MOV DWORD PTR DS:[402000],EAX
0040100D 6A 02 PUSH 2
0040100F 6A 02 PUSH 2
00401011 6A 04 PUSH 4
00401013 6A 04 PUSH 4
00401015 E8 56000000 CALL TESTLO~1.00401070 [COLOR=teal];dummyESP[/color]
0040101A 6A 06 PUSH 6
0040101C 6A 06 PUSH 6
0040101E 6A 03 PUSH 3
00401020 6A 03 PUSH 3
00401022 E8 3B000000 CALL TESTLO~1.00401062 [COLOR=teal];dummyEBP[/color]
00401027 6A 04 PUSH 4
00401029 6A 03 PUSH 3
0040102B 6A 02 PUSH 2
0040102D 6A 01 PUSH 1
0040102F E8 47000000 CALL TESTLO~1.0040107B [COLOR=teal];unoWithESP[/color]
00401034 6A 08 PUSH 8
00401036 6A 07 PUSH 7
00401038 6A 06 PUSH 6
0040103A 6A 05 PUSH 5
0040103C E8 55000000 CALL TESTLO~1.00401096 [COLOR=teal];unoWithEBP[/color]
00401041 6A 06 PUSH 6
00401043 6A 07 PUSH 7
00401045 6A 08 PUSH 8
00401047 6A 09 PUSH 9
00401049 E8 78000000 CALL TESTLO~1.004010C6 [COLOR=teal];dosWhitESP[/color]
0040104E 6A 02 PUSH 2
00401050 6A 03 PUSH 3
00401052 6A 04 PUSH 4
00401054 6A 05 PUSH 5
00401056 E8 51000000 CALL TESTLO~1.004010AC [COLOR=teal];dosWhitEBP[/color]
0040105B 50 PUSH EAX
0040105C FF15 48304000 CALL DWORD PTR DS:[<&kernel32.ExitProces>; kernel32.ExitProcess
00401062 C8 000000 ENTER 0,0
00401066 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]
00401069 8B45 14 MOV EAX,DWORD PTR SS:[EBP+14]
0040106C C9 LEAVE
0040106D C2 1000 RETN 10
[COLOR=teal];dummyESP[/color] [COLOR=blue]optionUseESP[/COLOR]
00401070 8B4424 04 MOV EAX,DWORD PTR SS:[ESP+4]
00401074 8B4424 10 MOV EAX,DWORD PTR SS:[ESP+10]
00401078 C2 1000 RETN 10
0040107B 8B4424 04 MOV EAX,DWORD PTR SS:[ESP+4]
0040107F 8B5424 10 MOV EDX,DWORD PTR SS:[ESP+10]
00401083 50 PUSH EAX
00401084 8B4424 08 MOV EAX,DWORD PTR SS:[ESP+8]
00401088 50 PUSH EAX
00401089 8B4424 0C MOV EAX,DWORD PTR SS:[ESP+C]
0040108D 81C4 08000000 ADD ESP,8
00401093 C2 1000 RETN 10
[COLOR=teal];unoWithEBP[/color] [COLOR=blue]optionUseEBP[/COLOR]
00401096 C8 000000 ENTER 0,0
0040109A 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]
0040109D 8B55 14 MOV EDX,DWORD PTR SS:[EBP+14]
004010A0 50 PUSH EAX
004010A1 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]
004010A4 50 PUSH EAX
004010A5 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]
004010A8 C9 LEAVE
004010A9 C2 1000 RETN 10
004010AC C8 000000 ENTER 0,0
004010B0 81EC 30000000 SUB ESP,30
004010B6 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]
004010B9 8B55 14 MOV EDX,DWORD PTR SS:[EBP+14]
004010BC 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]
004010BF 8B55 14 MOV EDX,DWORD PTR SS:[EBP+14]
004010C2 C9 LEAVE
004010C3 C2 1000 RETN 10
[COLOR=teal];dosWhitESP[/color] [COLOR=blue]optionUseESP[/COLOR]
004010C6 81EC 30000000 SUB ESP,30
004010CC 8B4424 34 MOV EAX,DWORD PTR SS:[ESP+34]
004010D0 8B5424 40 MOV EDX,DWORD PTR SS:[ESP+40]
004010D4 8B4424 34 MOV EAX,DWORD PTR SS:[ESP+34]
004010D8 8B5424 40 MOV EDX,DWORD PTR SS:[ESP+40]
004010DC 81C4 30000000 ADD ESP,30
004010E2 C2 1000 RETN 10

Like you see in the code above. is fine and nice ;), also you see now what is the output, and see that you can mix both.

now i see the debug and all stack frames are restored, also you can combine then, like you say, the technique is ok, but have some problem if with some routines in win32api (the use of ESP), also i think not only CreateWindowEx need you use stack frames in you functions.

you can watch the macro, i think no have errors, but if you can translate to your macro preprocesor that maybe are good, see the code and the output, i think is that, and i say you, can change from one to the other without modify in any way your code :D.

Have a nice day.

a suck.. i forget put the attachment :S lol...mmm i cant edit the attachment.. ops.... in the next :D
Posted on 2003-03-17 10:42:45 by rea
easy of use and good use :D.

what you think??, you can translate tou your macro language ... if you want??
(edit) also if you dont understand some in the macro f.inc, you can ask to me.(/edit)

ok, have a nice day.

(sorry for the double post, but i cant edit the above.. i forget put the attachment.. lol.. )
Posted on 2003-03-17 10:47:52 by rea