Author Topic: Preserving eax and address of variables relative to stack  (Read 267 times)

Vortex

  • Member
  • *****
  • Posts: 1704
Preserving eax and address of variables relative to stack
« 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 :

Code: [Select]
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 :

Code: [Select]
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 :

Code: [Select]
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

Code: [Select]
@p MACRO _name,_type

    lcounter=lcounter+SIZEOF(_type)

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

    EXITM <_name>

ENDM

jj2007

  • Member
  • *****
  • Posts: 7558
  • Assembler is fun ;-)
    • MasmBasic
Re: Preserving eax and address of variables relative to stack
« Reply #1 on: October 03, 2017, 07:38:15 AM »
Interesting idea :t

Code: [Select]
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

mabdelouahab

  • Member
  • ***
  • Posts: 336
Re: Preserving eax and address of variables relative to stack
« Reply #2 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

jj2007

  • Member
  • *****
  • Posts: 7558
  • Assembler is fun ;-)
    • MasmBasic
Re: Preserving eax and address of variables relative to stack
« Reply #3 on: October 03, 2017, 07:14:07 PM »
Code: [Select]
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

Code: [Select]
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 ;)

Vortex

  • Member
  • *****
  • Posts: 1704
Re: Preserving eax and address of variables relative to stack
« Reply #4 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.

Biterider

  • Member
  • **
  • Posts: 113
  • ObjAsm32
    • ObjAsm32
Re: Preserving eax and address of variables relative to stack
« Reply #5 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

johnsa

  • Member
  • ****
  • Posts: 525
    • Uasm
Re: Preserving eax and address of variables relative to stack
« Reply #6 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:

Code: [Select]

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)]   

...


Biterider

  • Member
  • **
  • Posts: 113
  • ObjAsm32
    • ObjAsm32
Re: Preserving eax and address of variables relative to stack
« Reply #7 on: October 09, 2017, 08:55:23 PM »
Hi
Yes, I like the idea. I would suggest FRAMEOFS or LOCALOFS or something similar.


Biterider

johnsa

  • Member
  • ****
  • Posts: 525
    • Uasm
Re: Preserving eax and address of variables relative to stack
« Reply #8 on: October 10, 2017, 01:51:05 AM »

www.terraspace.co.uk/uasm242.zip

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

Code: [Select]


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


Vortex

  • Member
  • *****
  • Posts: 1704
Re: Preserving eax and address of variables relative to stack
« Reply #9 on: October 10, 2017, 06:12:10 AM »
Hi johnsa,

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

Code: [Select]
            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))


Biterider

  • Member
  • **
  • Posts: 113
  • ObjAsm32
    • ObjAsm32
Re: Preserving eax and address of variables relative to stack
« Reply #10 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.


Code: [Select]
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

johnsa

  • Member
  • ****
  • Posts: 525
    • Uasm
Re: Preserving eax and address of variables relative to stack
« Reply #11 on: October 10, 2017, 10:43:58 PM »

Biterider

  • Member
  • **
  • Posts: 113
  • ObjAsm32
    • ObjAsm32
Re: Preserving eax and address of variables relative to stack
« Reply #12 on: October 10, 2017, 11:38:35 PM »
Hi John
Now I have to add 4 --> [esp + FRAMEOS(Arg) + 4]
Attached the test file.
Biterider

johnsa

  • Member
  • ****
  • Posts: 525
    • Uasm
Re: Preserving eax and address of variables relative to stack
« Reply #13 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%:

Code: [Select]

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.

Biterider

  • Member
  • **
  • Posts: 113
  • ObjAsm32
    • ObjAsm32
Re: Preserving eax and address of variables relative to stack
« Reply #14 on: October 11, 2017, 12:58:40 AM »
Hi John
Perfect. No extra add/sub needed anymore!  :t
Biterider