Author Topic: Calling a leaf proc maintaining alignment.  (Read 4627 times)

hutch--

  • Administrator
  • Member
  • ******
  • Posts: 10573
  • Mnemonic Driven API Grinder
    • The MASM32 SDK
Calling a leaf proc maintaining alignment.
« on: September 25, 2018, 02:00:06 PM »
The technique is very simple, when you call a leaf procedure with no stack frame, it enters the proc misaligned by 8 bytes. With pure mnemonic code, it does not matter but if you try and call other code, it fails due to the misalignment. Solution is simple, sub rsp by 8 bytes and in the leaf proc, set RET as "ret 8" and the leaf proc is aligned the same as the calling proc and you can make high level calls from within the leaf proc.

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    include \masm32\include64\masm64rt.inc

    .code

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

 STACKFRAME

 entry_point proc

    LOCAL ptxt  :QWORD

    sas ptxt, "This is a test of a new stack frame macro"

    rcall MessageBox,0," RSP Before",str$(rsp),0

    sub rsp, 8
    rcall testproc,ptxt

    rcall MessageBox,0," RSP After",str$(rsp),0

    rcall ExitProcess,0

    ret

 entry_point endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

 NOSTACKFRAME

 testproc proc

    rcall MessageBox,0,rcx,"Title",0

    ret 8

 testproc endp

 STACKFRAME

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    end
hutch at movsd dot com
http://www.masm32.com    :biggrin:  :skrewy:

sinsi

  • Guest
Re: Calling a leaf proc maintaining alignment.
« Reply #1 on: September 25, 2018, 02:58:05 PM »
I think it's better to always assume RSP is misaligned on any proc entry and adjust RSP within the proc. Using SUB RSP,8 and RET 8 seems counter-intuitive and means there are now two places to remember to add code.
On proc entry I always assume the stack is misaligned, with no stack frame a simple PUSH will align it (and save a few bytes).

Code: [Select]
  push rbx        ;aligns RSP to 16
;tricks
  sub ebx,ebx     ;can be useful as a zero byte/word/dword/qword
  lea rcx,[rbx+4] ;same as mov ecx,4 but shorter
  mov var1,rbx    ;shorter than mov var1,0
;
  pop rbx
  ret

hutch--

  • Administrator
  • Member
  • ******
  • Posts: 10573
  • Mnemonic Driven API Grinder
    • The MASM32 SDK
Re: Calling a leaf proc maintaining alignment.
« Reply #2 on: September 25, 2018, 05:29:46 PM »
Any combination will work, sub before the call and add after it, inside the leaf proc a sub at the start and add before the ret and you can automate any variant with a macro, this one above was the simplest in terms of calling code but they all work.

This probably the easiest to use.

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    include \masm32\include64\masm64rt.inc

  ; -------------------------
  ; maintain caller alignment
  ; -------------------------
    calla MACRO args:VARARG
      sub rsp, 8
      rcall args
      add rsp, 8
    ENDM

    .code

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

 STACKFRAME

 entry_point proc

    LOCAL ptxt  :QWORD

    sas ptxt, "This is a test of a new stack frame macro"

    rcall MessageBox,0," RSP Before",str$(rsp),0

    calla testproc,ptxt

    rcall MessageBox,0," RSP After",str$(rsp),0

    rcall ExitProcess,0

    ret

 entry_point endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

 NOSTACKFRAME

 testproc proc

    rcall MessageBox,0,rcx,"Title",0

    ret

 testproc endp

 STACKFRAME

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    end
hutch at movsd dot com
http://www.masm32.com    :biggrin:  :skrewy:

sinsi

  • Guest
Re: Calling a leaf proc maintaining alignment.
« Reply #3 on: September 25, 2018, 06:09:11 PM »
I still think that alignment should happen within the called proc, use it if the proc calls others.
64-bit code can get "bloated", using the calla macro could result in code like this
Code: [Select]
  sub rsp,8
  rcall args
  add rsp,8
  sub rsp,8
  rcall args
  add rsp,8
  ...

hutch--

  • Administrator
  • Member
  • ******
  • Posts: 10573
  • Mnemonic Driven API Grinder
    • The MASM32 SDK
Re: Calling a leaf proc maintaining alignment.
« Reply #4 on: September 25, 2018, 06:13:46 PM »
 :biggrin:

You might like this then. No manual stack twiddling at all.

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    include \masm32\include64\masm64rt.inc

    LeafProc MACRO procname, flag, argbytes, localbytes, reglist, userparms:VARARG
      sub rsp, 8
      EXITM <localbytes>
    ENDM

    EndLeaf MACRO procname, flag, argbytes, localbytes, reglist, userparms:VARARG
      add rsp, 8
      ret
    ENDM

    LEAFPROC MACRO
      OPTION PROLOGUE:LeafProc
      OPTION EPILOGUE:EndLeaf
    ENDM

    .code

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

 entry_point proc

    rcall testit
    waitkey
    rcall ExitProcess,0

 entry_point endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

 LEAFPROC

 testit proc

    rcall MessageBox,0,"Leaf Proc Here","About",MB_OK
    ret

 testit endp

 STACKFRAME

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    end

 comment #

    sub_140001033   proc
    .text:0000000140001033 4883EC08                   sub rsp, 8
    .text:0000000140001037 49C7C100000000             mov r9, 0x0
    .text:000000014000103e 4C8B0551100000             mov r8, qword ptr [0x140002096]
    .text:0000000140001045 488B1563100000             mov rdx, qword ptr [0x1400020af]
    .text:000000014000104c 4833C9                     xor rcx, rcx
    .text:000000014000104f FF15FF110000               call qword ptr [MessageBoxA]
    .text:000000014000104f
    .text:0000000140001055 4883C408                   add rsp, 8
    .text:0000000140001059 C3                         ret

    #
hutch at movsd dot com
http://www.masm32.com    :biggrin:  :skrewy:

sinsi

  • Guest
Re: Calling a leaf proc maintaining alignment.
« Reply #5 on: September 25, 2018, 06:36:33 PM »
 :biggrin:

I still dislike macros though...
Code: [Select]
    LeafProc MACRO procname, flag, argbytes, localbytes, reglist, userparms:VARARG
      push rcx
      EXITM <localbytes>
    ENDM

    EndLeaf MACRO procname, flag, argbytes, localbytes, reglist, userparms:VARARG
      pop rcx
      ret
    ENDM

more bloat  :biggrin:
Code: [Select]
49C7C100000000             mov r9, 0x0
edited: changed rax to rcx because rax is used to return a value sometimes.

hutch--

  • Administrator
  • Member
  • ******
  • Posts: 10573
  • Mnemonic Driven API Grinder
    • The MASM32 SDK
Re: Calling a leaf proc maintaining alignment.
« Reply #6 on: September 25, 2018, 07:06:24 PM »
I will have a play with that macro when I get time, if its a "0" it does the xor reg, reg but if its a constant, you get mov reg, 0.
hutch at movsd dot com
http://www.masm32.com    :biggrin:  :skrewy:

wjr

  • Member
  • **
  • Posts: 242
    • WJR's website
Re: Calling a leaf proc maintaining alignment.
« Reply #7 on: September 27, 2018, 03:24:20 AM »
If you adjust rsp and do so as well with a call, then you no longer have a leaf function, and for exception handling purposes there should also be xdata and pdata as with non-leaf functions.

hutch--

  • Administrator
  • Member
  • ******
  • Posts: 10573
  • Mnemonic Driven API Grinder
    • The MASM32 SDK
Re: Calling a leaf proc maintaining alignment.
« Reply #8 on: September 27, 2018, 04:22:33 AM »
That's why I put the stack alterations in a prologue/epilogue, a stack frame proc provides more than correct alignment, LOCAL's etc .... the prologue/epilogue above does nothing more than align the stack pointer. It is properly an aligned no stack frame prologue/epilogue technique.
hutch at movsd dot com
http://www.masm32.com    :biggrin:  :skrewy: