The MASM Forum

64 bit assembler => UASM Assembler Development => Topic started by: Vortex on October 03, 2017, 06:18:49 AM

Title: Preserving eax and address of variables relative to stack
Post by: Vortex on October 03, 2017, 06:18:49 AM
While pushing the address of variables relative to stack, the assembler uses the lea instruction destroying the content of eax :

lea     eax,var
push    eax


Inspired by GoAsm's method, I wrote a simple macro and modified my custom invoke macro to preserve eax while pushing the addresses to the stack :

push    ebp
sub     DWORD PTR [esp],offset_to_ebp


The @p macro calculates the offsets and this information is used by the custom invoke macro to pass the adress :

WinMain PROC hInst:DWORD,hPrevInst:DWORD,CmdLine:DWORD,CmdShow:DWORD

    lcounter=0

    LOCAL @p(wc,WNDCLASSEX) : WNDCLASSEX
    LOCAL @p(msg,MSG) : MSG
    LOCAL @p(hwnd,DWORD) : DWORD


@p MACRO _name,_type

    lcounter=lcounter+SIZEOF(_type)

    @CatStr(<bytes>,<_name>) = lcounter

    EXITM <_name>

ENDM
Title: Re: Preserving eax and address of variables relative to stack
Post by: jj2007 on October 03, 2017, 07:38:15 AM
Interesting idea :t

00401095   ³.  55           push ebp
00401096   ³.  832C24 30    sub dword ptr [esp], 30              ; ÚpWndclassex => offset LOCAL.12
0040109A   ³.  E8 B8000000  call <jmp.&USER32.RegisterClassExA>  ; ÀUSER32.RegisterClassExA
Title: Re: Preserving eax and address of variables relative to stack
Post by: mabdelouahab on October 03, 2017, 04:55:08 PM
 :t

@p MACRO _name,_type
    lcounter=lcounter+SIZEOF(_type)
    @CatStr(<bytes>,<_name>) = lcounter
    EXITM <_name : _type >
ENDM
...
LOCAL @p(wc,WNDCLASSEX) : WNDCLASSEX


Maybe better
Title: Re: Preserving eax and address of variables relative to stack
Post by: jj2007 on October 03, 2017, 07:14:07 PM
include \masm32\include\masm32rt.inc ; plain Masm32
include local.mac

.code
somecode proc argText, argTitle, argMode
Local_ rc:RECT, buffer[8]:BYTE, L1:DWORD, @ ; last arg marks end of locals
  mov L1, 12345678h
  mov rc.left, 11111111h
  mov rc.top, 22222222h
  mov rc.right, 33333333h
  mov rc.bottom, 44444444h
  ; int 3
  invoke_ lstrcpy, addr buffer, argText
  print hex$(L1), "h is the DWORD var", 13, 10
  print hex$(rc.left), "h is rc.left", 13, 10
  print hex$(rc.top), "h is rc.top", 13, 10
  print hex$(rc.right), "h is rc.right", 13, 10
  print hex$(rc.bottom), "h is rc.bottom", 13, 10
  invoke_ MessageBox, 0, addr buffer, argTitle, argMode
  ret_
somecode endp

start:
  print "let's do a little test", 13, 10
  invoke_ somecode, chr$("text567"), chr$("title"), MB_OK
  inkey "we are done here"
  exit

end start


00401029   ³.  CC           int3
0040102A   ³.  FF75 08      push dword ptr [ebp+8]               ; ÚSrc = "text567"
0040102D   ³.  55           push ebp                             ; ³
0040102E   ³.  830424 E8    add dword ptr [esp], -18             ; ³Dest => offset LOCAL.6
00401032   ³.  E8 11020000  call <jmp.&kernel32.lstrcpyA>        ; ÀKERNEL32.lstrcpy


Tested with MASM 6.14 and some others ;)
Title: Re: Preserving eax and address of variables relative to stack
Post by: Vortex on October 04, 2017, 04:30:08 AM
Hi mabdelouahab,

Thanks for the modification. It looks like that I missed that notation.

Hi Jochen,

Nice work. Me too, I have a custom version of the LOCAL statement.
Title: Re: Preserving eax and address of variables relative to stack
Post by: Biterider on October 08, 2017, 08:17:27 AM
Hi
@habran/johnsa: is there a way to get the offsets of local vars from ebp or another address, like the proc entry point?

Regards, Biterider
Title: Re: Preserving eax and address of variables relative to stack
Post by: johnsa on October 09, 2017, 08:20:34 PM
Hi,

I don't believe so, we would need to implement some sort of operator for it, which isn't a bad idea.. perhaps something like:



myProc PROC
   LOCAL aVar:DWORD

   mov eax,STACKOFS(aVar)        ; if stackbase=ebp this is the offset relative to ebp post prologue, else esp.
   mov eax,[ebp+eax]   
   mov eax,[ebp+STACKOFS(aVar)]   

...


Title: Re: Preserving eax and address of variables relative to stack
Post by: Biterider on October 09, 2017, 08:55:23 PM
Hi
Yes, I like the idea. I would suggest FRAMEOFS or LOCALOFS or something similar.


Biterider
Title: Re: Preserving eax and address of variables relative to stack
Post by: johnsa on October 10, 2017, 01:51:05 AM

www.terraspace.co.uk/uasm242.zip (http://www.terraspace.co.uk/uasm242.zip)

supporting FRAMEOFS operator. Can be used as follows in 32bit and 64bit :




main proc c aParam:dword
local   dwWritten:dword
local   hConsole:dword

mov eax,FRAMEOFS(dwWritten)
mov eax,[ebp+FRAMEOFS(hConsole)]
;for comparison
mov eax,hConsole
mov ebx,dwWritten
mov eax,FRAMEOFS(aParam)
mov eax,aParam


Title: Re: Preserving eax and address of variables relative to stack
Post by: Vortex on October 10, 2017, 06:12:10 AM
Hi johnsa,

Thanks for the FRAMEOFS operator. It works fine with my custom invoke macro :

            IF ((OPATTR(@SubStr(%arg,5+1))) EQ 98) OR ((OPATTR(@SubStr(%arg,5+1))) EQ 34)

                add     DWORD PTR [esp],FRAMEOFS(@SubStr(%arg,5+1))


Title: Re: Preserving eax and address of variables relative to stack
Post by: Biterider on October 10, 2017, 10:29:07 PM
Hi John
I tested FRAMEOFS with a standard prologue & epilogue and all work well.
In case of an non existing FRAME and you want to access hte proc parameters using esp, you have to decrement the offset by 4.


OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE


TestProc proc dArg1:DWORD, dArg2:DWORD
    mov eax, [esp + FRAMEOFS(dArg1)-4]
    mov edx, [esp + FRAMEOFS(dArg2)-4]
    ret
TestProc endp


OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef



Regards, Biterider
Title: Re: Preserving eax and address of variables relative to stack
Post by: johnsa on October 10, 2017, 10:43:58 PM
Please test again..

www.terraspace.co.uk/uasm242.zip (http://www.terraspace.co.uk/uasm242.zip)
Title: Re: Preserving eax and address of variables relative to stack
Post by: Biterider on October 10, 2017, 11:38:35 PM
Hi John
Now I have to add 4 --> [esp + FRAMEOFS(Arg) + 4]
Attached the test file.
Biterider
Title: Re: Preserving eax and address of variables relative to stack
Post by: johnsa on October 11, 2017, 12:48:20 AM
Hi,

Try again.. same URL for download.

The problem actually wasn't the FRAMEOFS but a bug in the proc handling itself. When FPO is on or there is no prologue, there should be no stack frame setup.. but the parameters were still using ebp/rbp instead of esp to reference. that is fixed and this now works 100%:



include c:\masm32\include\masm32rt.inc

.code                                               ;Begin Code segment
TestProc1 proto :DWORD, :DWORD
TestProc2 proto :DWORD, :DWORD

TestProc1 proc dArg1:DWORD, dArg2:DWORD
    local dLoc1:DWORD
    local dLoc2:DWORD
   
    mov dLoc1, 100h
    mov dLoc2, 200h

mov eax, dArg1
mov edx, dArg2

    mov eax, [ebp + FRAMEOFS(dArg1)]
    mov edx, [ebp + FRAMEOFS(dArg2)]

    mov eax, [ebp + FRAMEOFS(dLoc1)]
    mov edx, [ebp + FRAMEOFS(dLoc2)]
    ret
TestProc1 endp

OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE

TestProc2 proc dArg1:DWORD, dArg2:DWORD
    mov eax, [esp + FRAMEOFS(dArg1)]
    mov edx, [esp + FRAMEOFS(dArg2)]
    mov eax, dArg1
    mov edx, dArg2
    ret
TestProc2 endp

OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef


start:                                              ;Program entry point
    invoke TestProc1, 1, 2
    invoke TestProc2, 3, 4

    invoke ExitProcess, 0                           ;Exit program returning 0 to Windows OS
end start                                           ;End of code and define the program entry point



I added a few extra regular movs just to check offsets/stack locations and values.
Title: Re: Preserving eax and address of variables relative to stack
Post by: Biterider on October 11, 2017, 12:58:40 AM
Hi John
Perfect. No extra add/sub needed anymore!  :t
Biterider