Here is your procedure in the original form, and in a form with no automatic prologue and epilogue code and that shows everthing including the generated code, and with comments that I hope make sense. And in case it’s not obvious, after the procedure returns EAX is pointing into the “free” stack and the next thing pushed will overwrite the start of the now invalid buffer.
;==============================================================================
include \masm32\include\masm32rt.inc
;==============================================================================
.data
.code
;==============================================================================
viewInt proc iNum:DWORD
LOCAL buffer[12]:BYTE
invoke dwtoa,iNum,addr buffer
lea eax, buffer
ret
viewInt endp
;==============================================================================
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
ViewInt proc iNum:DWORD
; [ESP+0]=return address, [ESP+4]=iNum
push ebp ; preserve EBP
; [ESP+0]=preserved EBP,[ESP+4]=return address, [ESP+8]=iNum
mov ebp, esp ; copy ESP into EBP
; [EBP+0]=preserved EBP,[EBP+4]=return address, [EBP+8]=iNum
add esp, -12 ; reserve 12 bytes of stack for buffer
lea eax, BYTE PTR ss:[ebp-12] ; load address of buffer into EAX
push eax ; push address
push DWORD PTR ss:[ebp+8] ; push iNum
call dwtoa
lea eax, BYTE PTR ss:[ebp-12] ; load address of buffer into EAX
mov esp, ebp ; restore ESP
; [ESP+0]=preserved EBP,[ESP+4]=return address, [ESP+8]=iNum
pop ebp ; recover EBP
; Stack now as it was at entry
; [ESP+0]=return address, [ESP+4]=iNum
ret 4 ; return and remove iNum from stack
ViewInt endp
OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef
;==============================================================================
start:
;==============================================================================
inkey
exit
;==============================================================================
END start