Author Topic: Stack issues  (Read 1365 times)

hutch--

  • Administrator
  • Member
  • ******
  • Posts: 5852
  • Mnemonic Driven API Grinder
    • The MASM32 SDK
Re: Stack issues
« Reply #15 on: September 22, 2018, 10:13:41 PM »
Have a look at this, its why you are having problems. At the entry point the stack is not correctly aligned, the first PUSH aligns the stack. You can use the ENTER LEAVE pair to do the same task but you must align the entry point for the app to start.

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

    include \masm32\include64\masm64rt.inc

    .data
      txt db "MessageBox message text",0
      ttl db "The Title",0

    .code

 NOSTACKFRAME

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

 entry_point proc           ; < stack is misaligned by 8

    push rbp                ; push aligns the stack with extra 8 bytes
    mov rbp, rsp            ; preserve the stack pointer

    mov rcx, 0
    lea rdx, txt
    lea r8, ttl
    mov r9, MB_OK
    call testproc           ; call a remote MessageBox

    xor rcx, rcx
    call ExitProcess

    mov rsp, rbp            ; never called after ExitProcess
    pop rbp

    ret

 entry_point endp

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

 testproc proc

    push rbp                ; push aligns the stack with extra 8 bytes
    mov rbp, rsp            ; preserve the stack pointer

    rcall MessageBox        ; registers already loaded

    mov rsp, rbp            ; restore the stack pointer
    pop rbp                 ; restore rbp

    ret

 testproc endp

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

 STACKFRAME

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

AW

  • Member
  • *****
  • Posts: 1514
  • Let's Make ASM Great Again!
Re: Stack issues
« Reply #16 on: September 22, 2018, 10:30:08 PM »
@LiaoMi

I see now what you mean. What Johnsa told me, and it makes all sense, is that start is just a label. Only the linker knows it will be Entry Point.
So, you either have to manually align the stack on the label that will be entry point or use a procedure for the entry point. In the last case  it will align the stack on entry to the procedure, at least it used to.

nidud

  • Member
  • *****
  • Posts: 1614
    • https://github.com/nidud/asmc
Re: Stack issues
« Reply #17 on: September 22, 2018, 10:38:06 PM »
but in 32-bit version its possible without alignment?!

Not really, no. In 32-bit you may or may not get away with a misaligned stack. You could test this
    inc  esp
    call API

and see what happens.

In 32-bit the alignment is equal to push-size (4) so the stack is (normally) always aligned. In 64-bit the push-size is 8 and the required alignment is 16 so this creates the problem. This means that all calls has to be made with a 16-byte aligned stack. The call pushes IP and jumps which makes all proc-entries aligned 8:

start:          ; aligned 8 on entry
    push rbp    ; add 8 byte
                ; the stack is now aligned 16

LiaoMi

  • Member
  • ***
  • Posts: 320
Re: Stack issues
« Reply #18 on: September 23, 2018, 12:43:18 AM »
Have a look at this, its why you are having problems. At the entry point the stack is not correctly aligned, the first PUSH aligns the stack. You can use the ENTER LEAVE pair to do the same task but you must align the entry point for the app to start.

Thank you!  :t

@LiaoMi

I see now what you mean. What Johnsa told me, and it makes all sense, is that start is just a label. Only the linker knows it will be Entry Point.
So, you either have to manually align the stack on the label that will be entry point or use a procedure for the entry point. In the last case  it will align the stack on entry to the procedure, at least it used to.

Thanks for the explanation! Everything is clear now :icon14:  :eusa_dance: In this case, the skeleton will be similar to this

Code: [Select]
.686
.MMX
.XMM
.x64

option casemap:none
option win64:15;win64:11
option frame:auto
option stackbase:rsp
option dotname
option evex:1
option proc:private
option LITERALS:ON
option PROCALIGN:16
OPTION FIELDALIGN:16; 1|2|4|8|16|32 - The default value is 1 or the value set by cmdline switch -Zp
OPTION FRAME:AUTO;NOAUTO

WIN32_LEAN_AND_MEAN equ 1
.nolist
.nocref

    include C:\masm64\VS2017\include_x86_x64\translate64.inc
    include C:\masm64\sdkrc100\um\windows.inc
    include macros64_Uasm.inc

MBox PROTO
; -----------------------------------------
  ; non branching version with no ELSE clause
  ; -----------------------------------------
      chr$ MACRO any_text:VARARG
        LOCAL txtname
        .data
          IFDEF __UNICODE__
            WSTR txtname,any_text
            ;align 4
            .code
            EXITM <OFFSET txtname>
          ENDIF

          txtname db any_text,0
          ;align 4
          .code
          EXITM <OFFSET txtname>
      ENDM

;     libraries
;     ~~~~~~~~~
    ; ------------------------------------------
    ; import libraries for Windows API functions
    ; ------------------------------------------
   
includelib Kernel32.lib
includelib  User32.lib
includelib  Msimg32.lib
includelib  Comctl32.lib
includelib  Comdlg32.lib
includelib  Shell32.lib
includelib  OleAut32.lib
includelib  Ole32.lib
includelib  Advapi32.lib

.code

WinMainCRTStartup Proc public

    ;enter 16,0 no longer required
    invoke MBox
    invoke ExitProcess,0
    ;leave no longer required
ret

WinMainCRTStartup  Endp

MBox proc

    invoke MessageBox,0,chr$("Test UASM Debug Compiling"),chr$("Test"),0
    ret
   
MBox endp

end WinMainCRTStartup

but in 32-bit version its possible without alignment?!

Not really, no. In 32-bit you may or may not get away with a misaligned stack. You could test this
    inc  esp
    call API

and see what happens.

In 32-bit the alignment is equal to push-size (4) so the stack is (normally) always aligned. In 64-bit the push-size is 8 and the required alignment is 16 so this creates the problem. This means that all calls has to be made with a 16-byte aligned stack. The call pushes IP and jumps which makes all proc-entries aligned 8:

start:          ; aligned 8 on entry
    push rbp    ; add 8 byte
                ; the stack is now aligned 16


All my misunderstandings are corrected, thanks!  :t