For those hardy souls who want to manually construct their stack frame, here is a simple example of why I prefer to use the ENTER / LEAVE pair instead of doing it manually. If you dis-assemble this simple code you will see why.
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
include \masm32\include64\masm64rt.inc
.code
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
NOSTACKFRAME ; turn the stackframe off
entry_point proc
push rbp ; manually construct stack frame
mov rbp, rsp ; store stack pointer in rbp
sub rsp, 128 ; allocate local space
mov QWORD PTR [rsp-32], 0 ; write value to local
; ---------------------------
; call a stackframe procedure
; ---------------------------
invoke showtext,"The time has come, the walrus said, to speak of many things"
waitkey ; call a library procedure
; -----------------------------------------------
; call API with a manually defined local variable
; -----------------------------------------------
invoke ExitProcess,QWORD PTR [rsp-32]
mov rsp, rbp ; exit the stack frame
pop rbp
ret
entry_point endp
STACKFRAME ; turn the stack frame back on again
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
showtext proc text:QWORD
conout text,lf,lf ; display the text
ret
showtext endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
end
Works fine here. What exactly should go wrong? Can you post the exe?
Done.
It works like a charm, even in the debugger. What is supposed to go wrong here?
I don't know (almost nothing) of 64 bits yet, but looks pretty much (this code example) as 32 bits. This:
mov QWORD PTR [rsp-32], 0 ; write value to local
Shouldn't be this?:
mov QWORD PTR [rbp-32], 0 ; write value to local
And then this:
invoke ExitProcess,QWORD PTR [rsp-32]
this instead?:
invoke ExitProcess,QWORD PTR [rbp-32]
Quote from: felipe on December 31, 2017, 08:40:57 AM
I don't know (almost nothing) of 64 bits yet, but looks pretty much (this code example) as 32 bits. This:
:biggrin: of course.
This is not local
mov QWORD PTR [rsp-32], 0 ; write value to local
Quote from: aw27 on December 31, 2017, 08:49:33 AM
Quote from: felipe on December 31, 2017, 08:40:57 AM
I don't know (almost nothing) of 64 bits yet, but looks pretty much (this code example) as 32 bits. This:
:biggrin: of course.
:biggrin: Come on, at least tell me which of the statements above (or both) are you referring. :biggrin:
Quote from: sinsi on December 31, 2017, 09:10:25 AM
This is not local
mov QWORD PTR [rsp-32], 0 ; write value to local
Right, it's somewhere in the wild. But that should cause any trouble (and it doesn't, indeed), because it's below the stackpointer.
The code works just fine, so I really wonder what is Hutch' intention here ;)
Worst case (admittedly stretching things here)
;rsp = stackbase + 128 + 16
sub rsp, 128 ; allocate local space
;rsp = stackbase + 16
mov QWORD PTR [rsp-32], 0 ; write value to local
;rsp-32 = stackbase - 16 = access violation?
No harm done usually, since if your stack is that low you have other issues, but not a good habit to form methinks.
:biggrin:
> so I really wonder what is Hutch' intention here
It was supposed to work OK but the answer was in the original post "why I prefer to use the ENTER / LEAVE pair instead of doing it manually".
Sinsi,
You are right but it was not the point of the example.
I also think that [rsp-32] might be clobbered by the conout call, which would eventually end up calling a windows function.
About the only problem I can see with using RSP at the entry point instead of RBP is you have to use addresses for RSP based local values lower than with RBP.
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
include \masm32\include64\masm64rt.inc
.code
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
NOSTACKFRAME
entry_point proc
push rbp ; align the stack
mov rbp, rsp ; store stack pointer in rbp
sub rsp, 128 ; allocate local space
mov QWORD PTR [rbp-16], 0
mov QWORD PTR [rbp-24], 1234
invoke showtext,"The time has come, the walrus said, to speak of many things"
conout str$(QWORD PTR [rbp-16]),lf
conout str$(QWORD PTR [rbp-24]),lf
waitkey
invoke ExitProcess,QWORD PTR [rbp-16]
mov rsp, rbp ; never gets here
pop rbp
ret
entry_point endp
STACKFRAME
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
showtext proc text:QWORD
LOCAL unused1 :QWORD
LOCAL unused2 :QWORD
mov unused1, 100
mov unused2, 200
conout text,lf ; display the text
ret
showtext endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
end