News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Resilient stack frame

Started by jj2007, January 26, 2024, 10:12:12 AM

Previous topic - Next topic

jj2007

Inspired by Raymond Chen

A single push is sufficient to trash esi & edi in this example:

OldFrame proc uses esi edi a1, a2
Local LocVar1, LocVar2, LocVar3
  print hex$(a1), " = arg1", 13, 10
  print hex$(a2), " = arg2", 13, 10
  m2m LocVar1, a1
  m2m LocVar2, a2
  print hex$(LocVar1), " = LocVar1 in OldFrame", 13, 10
  print hex$(LocVar2), " = LocVar2 in OldFrame", 13, 10
  push eax        ; a single push is sufficient to create chaos
  ret
OldFrame endp
...
  print hex$(esi), " = esi before the invoke", 13, 10
  print hex$(edi), " = edi before the invoke", 13, 10
  invoke OldFrame, 11h, 22h             ; <<<<<<< OldFrame will trash esi and edi
  print hex$(esi), " = esi after OldFrame", 13, 10
  print hex$(edi), " = edi after OldFrame", 13, 10

Output:
11111111 = esi before the invoke
22222222 = edi before the invoke
00000011 = arg1
00000022 = arg2
00000011 = LocVar1 in OldFrame
00000022 = LocVar2 in OldFrame
22222222 = esi after OldFrame
00000018 = edi after OldFrame

For those who are curious and not too lazy to download a tiny pure Masm32 SDK example: there is a technique to make the stack frame more resilient, so that esi & edi don't get trashed so easily ;-)

If there is sufficient interest, I might volunteer to write the PROLOG macro :cool:

NoCforMe

Re: your example: well, duh; if you displace the stack pointer before leaving the subroutine, the registers that you supposedly protected with uses esi edi are gonna get trashed. That's because of this code "behind the scenes":
something    PROC  uses esi edi

; prologue code added by assembler:
    PUSH    ESI
    PUSH    EDI

... procedure code here ...

    PUSH    EAX    ;Oh noes, I screwed up the stack!

;  epilogue code added by assembler:
    POP     EDI
    POP     ESI
    RET
Which is why I choose not to use the uses facility; I'd rather explicitly PUSH and POP my registers so I know what the state of the stack is without having to figure in any "hidden" code.
Assembly language programming should be fun. That's why I do it.

sinsi

Quote from: NoCforMe on January 26, 2024, 11:04:23 AMWhich is why I choose not to use the uses facility; I'd rather explicitly PUSH and POP my registers so I know what the state of the stack is without having to figure in any "hidden" code.
A few times I've decided to use EDI and added it to my push list but forgotten to add it to the pop list which was hard to track down. USES is a lot easier.
Using Win32 you don't really have to know anything about where ESP is, anything on it (parameters, locals etc) is accessible by EBP.

NoCforMe

Quote from: sinsi on January 26, 2024, 11:44:56 AMUsing Win32 you don't really have to know anything about where ESP is, anything on it (parameters, locals etc) is accessible by EBP.
I almost never have done anything with ESP in any of my code. Once or twice I adjusted it when I had some loops that started with PUSHes but exited the loop around the corresponding POPs, so I adjusted the stack manually. Otherwise it's nothing to me.

And I have never, never explicitly done anything with EBP, other than accessing proc parms and locals.

I guess my code just isn't fancy schmancy enough ...
Assembly language programming should be fun. That's why I do it.

sinsi

Quote from: NoCforMe on January 26, 2024, 04:25:40 PMI guess my code just isn't fancy schmancy enough ...
? not sure what you mean by that ?
It's obsolete, anyway  :badgrin:
Join the 64-bit future  :biggrin:

My alternate forum nick would be NoMacrosForMe - I even dislike using INVOKE

TimoVJL

Quote from: sinsi on January 26, 2024, 04:59:55 PMMy alternate forum nick would be NoMacrosForMe - I even dislike using INVOKE
I might use NoMasmForMe  :tongue:
May the source be with you

NoCforMe

Both of you gonna have to pay me royalties for those names.
Assembly language programming should be fun. That's why I do it.

jj2007

Once upon a time, in this forum, and especially in the Lab, members would have had a thorough look at the code posted and discussed the consequences of the neat tricks shown there. Nowadays, attachments are ignored, and the "discussion" limits itself to the question whether macros are evil and how to signal to the rest of the World with a cute nick that one has lost interest in coding. Congrats :biggrin:

sinsi

Quote from: jj2007 on January 26, 2024, 08:59:14 PMOnce upon a time, in this forum, and especially in the Lab, members would have had a thorough look at the code posted and discussed the consequences of the neat tricks shown there. Nowadays, attachments are ignored, and the "discussion" limits itself to the question whether macros are evil and how to signal to the rest of the World with a cute nick that one has lost interest in coding. Congrats :biggrin:
The trouble for me is that there's nothing to discuss about the code/attachment - if you're dumb enough not to match your pushes and pops you deserve the consequences. In other words, it's bleedin' obvious  :biggrin:

Speaking of prologues, I am working on one for 64-bit, but it won't play well with what I've seen in masm64  :sad:

jj2007

Quote from: sinsi on January 27, 2024, 06:48:37 AMSpeaking of prologues, I am working on one for 64-bit, but it won't play well with what I've seen in masm64

Post what you have. What are the symptoms of "won't play well"?

NoCforMe

Quote from: sinsi on January 27, 2024, 06:48:37 AMThe trouble for me is that there's nothing to discuss about the code/attachment - if you're dumb enough not to match your pushes and pops you deserve the consequences. In other words, it's bleedin' obvious  :biggrin:
What you said. As I posted:
Quote from: NoCforMe on January 26, 2024, 11:04:23 AMRe: your example: well, duh; if you displace the stack pointer before leaving the subroutine, the registers that you supposedly protected with uses esi edi are gonna get trashed.
So what, now we need rubber-covered walls to protect stupid programmmers like at Disneyland so they can't hurt themselves?

And again, using macros and othe "high-level" features of MASM can hide this from the programmer, which is yet another reason I avoid them.
Assembly language programming should be fun. That's why I do it.