Hey guys I've been reading alot lately on how the stack works.
I understand the basics on how it grows and shrinks with push, and pop.

Anyways I wrote this code and Im' not sure why it will only print 44 bytes in my messagebox.


;NASM Win32 monitor off
;
;compile with:
;NASM.EXE -fobj stack.asm
;link with:
;ALINK.EXE stack.obj -c -oPE

%include "e:\nasm\include\windows.inc"

EXTERN ExitProcess
IMPORT ExitProcess kernel32.dll
EXTERN MessageBoxA
IMPORT MessageBoxA user32.dll

;segment .data USE32

segment .code USE32

..start

sub esp,64
lea edi,


mov , byte "F" ;1st byte
mov , byte "D"
mov , byte "C"
mov , byte "B"
mov , byte "A"
mov , byte "9"
mov , byte "8"
mov , byte "7"
mov , byte "6"
mov , byte "5"
mov , byte "4"
mov , byte "3"
mov , byte "2"
mov , byte "1"
mov , byte "9"
mov , byte "8"
mov , byte "7"
mov , byte "6"
mov , byte "5"
mov , byte "4"
mov , byte "3"
mov , byte "2"
mov , byte "1"
mov , byte "F"
mov , byte "D"
mov , byte "C"
mov , byte "B"
mov , byte "A"
mov , byte "9"
mov , byte "8"
mov , byte "7"
mov , byte "6"
mov , byte "5"
mov , byte "4"
mov , byte "3"
mov , byte "2"
mov , byte "1"
mov , byte "0"
mov , byte "F"
mov , byte "D"
mov , byte "C"
mov , byte "B"
mov , byte "A"
mov , byte "9"
mov , byte "8" ;STOPS HERE AT 44 BYTES WHY?
mov , byte "7"
mov , byte "6"
mov , byte "5"
mov , byte "4"
mov , byte "3"
mov , byte "2"
mov , byte "1"
mov , byte "0"
mov , byte "F"
mov , byte "D"
mov , byte "C"
mov , byte "B"
mov , byte "A"
mov , byte "9"
mov , byte "8"
mov , byte "7"
mov , byte "6"
mov , byte "5"
mov , byte "4"
;mov , byte "3"

sub edi,44        ;if i increase this number it prints garbage.
                      ;44 is the max number without printing garbage.
push dword MB_OK
push dword 0
push edi                  ;this holds the pointer to my string of bytes
push dword 0
call

push dword 0
call
Posted on 2006-05-30 09:19:39 by gavin_
Several errors.

1- With your sub esp,64, you reserve that part of the stack between the current "ESP-0" to "ESP-64". No program other than yours would be able to modify that area of the stack memory. That is the area which you must use yourself (as opposed to ESP-64 to ESP-1xx).

2- You use EBP as a pointer for filling memory but you have NOT set up the content of that register. (You only set up the content of EDI but you don't use that register until later on.)

3- The memory address you later pass to the MessageBoxA function is outside the area you had "reserved" on the stack. The 1st parameter you push for that function will effectively subtract 4 from the current ESP (which would be ESP-68 if we consider your original ESP before reserving stack space), and will thus overwrite the dword (4 bytes) at that location. Your other parameters would also overwrite more dwords on the stack. Finally the return address for the call would overwrite more of the data you had filled in. Then the MessageBoxA function would most probably overwrite another portion with its own required data before using your supplied address to display your message. By that time, none of the data you had filled in may have remained intact.

By going over once more what you have read on how the stack works, you will most probably understand it a bit more. Don't give up. Failure is not an option! ;)

BTW the MessageBoxA function expects your message to have a terminating 0.

Raymond
Posted on 2006-05-30 10:13:15 by Raymond
Hi Raymond.

I've made the changes and it works, but I'm sure I'm still not doing it the correct or easier way.


Any guidence would be great.
Thanks alot.




segment .code USE32

..start

sub esp,64
lea edi,

xor eax,eax

;right to left /first in last out
mov ,  eax              ;the zero

mov , byte "D"
mov , byte "C"
mov , byte "B"
mov , byte "A"
;continued--- etc etc >>>
mov , byte "4"
mov , byte "3"

sub edi,64              ;pointer for the first byte
sub esp, 20              ;make room for msgbox arguments

push dword MB_OK ;4 bytes
push dword 0    ;4 bytes
push edi        ;4 bytes   
push dword 0    ;4 bytes
call ;4 bytes for this aswell???

push dword 0
call

Posted on 2006-05-30 12:30:47 by gavin_
A correct way is (masm syntax):

sub esp,64 ; reserve 64 bytes
mov edx,esp
mov byte ptr,'A'
mov byte ptr,'B'
mov byte ptr,'C'
mov byte ptr,'D'
mov byte ptr,'E'
mov byte ptr,'F'
mov byte ptr,'G'
mov byte ptr,'H'
mov byte ptr,'I'
mov byte ptr,'J'
mov byte ptr,'A'
mov byte ptr,'B'
mov byte ptr,'C'
mov byte ptr,'D'
mov byte ptr,'E'
mov byte ptr,'F'
mov byte ptr,'G'
mov byte ptr,'H'
mov byte ptr,'I'
mov byte ptr,'J'
mov byte ptr,'A'
mov byte ptr,'B'
mov byte ptr,'C'
mov byte ptr,'D'
mov byte ptr,'E'
mov byte ptr,'F'
mov byte ptr,'G'
mov byte ptr,'H'
mov byte ptr,'I'
mov byte ptr,'J'
mov byte ptr,'A'
mov byte ptr,'B'
mov byte ptr,'C'
mov byte ptr,'D'
mov byte ptr,'E'
mov byte ptr,'F'
mov byte ptr,'G'
mov byte ptr,'H'
mov byte ptr,'I'
mov byte ptr,'J'
mov byte ptr,'A'
mov byte ptr,'B'
mov byte ptr,'C'
mov byte ptr,'D'
mov byte ptr,'E'
mov byte ptr,'F'
mov byte ptr,'G'
mov byte ptr,'H'
mov byte ptr,'I'
mov byte ptr,'J'
mov byte ptr,'A'
mov byte ptr,'B'
mov byte ptr,'C'
mov byte ptr,'D'
mov byte ptr,'E'
mov byte ptr,'F'
mov byte ptr,'G'
mov byte ptr,'H'
mov byte ptr,'I'
mov byte ptr,'J'
mov byte ptr,'A'
mov byte ptr,'B'
mov byte ptr,'X'
mov byte ptr,0


invoke MessageBox,0,edx,edx,0
add esp,64 ; free the 64 bytes


you can/should use EBP instead of EDX, though ^^".
Note that at address , is the last DWORD pushed onto stack, before executing this code. And this DWORD usually would be the return address for the "ret" instruction.

Just a quick tute on push/pop:

"PUSH EAX" works like these 2 lines:
sub esp,4
mov ,eax


"POP EAX" works like these 2 lines:
mov eax,
add esp,4
Posted on 2006-05-30 16:04:10 by Ultrano
Ultrano

Thanks for the help  ,the push pop info is good ;)

I have a question tho.

First why should i release the stack i allocated?

Oh and here is my code now I'm still not sure if this is the best way to do it?



segment .code USE32

..start

push ebp
mov ebp,esp
sub esp,8

lea edi,

mov ,  byte 0 ;bottum of stack       
mov ,  byte 0
mov , byte "a"
mov , byte "y"
mov , byte "i"
mov , byte "H"
mov , byte ")"
mov , byte ":" ;top of stack

push dword MB_OK ;4 bytes
push edi        ;4 bytes
push edi        ;4 bytes   
push dword 0    ;4 bytes
call ;4 bytes

push dword 0
call


Posted on 2006-05-30 23:17:10 by gavin_

First why should i release the stack i allocated?


Most problems from applications that seem to "hog" lots of memory stems from improper memory management. Releasing the stack after the call is complete ensures the stack space that was just used, is free once again to be used by some other call/procedure.

Without this release, your ESP keeps incrementing and your stack grows huge... and eventually it stops growing as you run out of memory.
Posted on 2006-05-30 23:37:09 by SpooK
A note on the stack's growing:
Windows initially reserves several 4k pages for your stack.
In a nutshell;
When your stack has grown beyond these pages (and you read/write there), you get an internal GPF. But Windows sees it's near the stack (at a bit lower address), allocates memory for those pages, and resumes your thread.


And when the OS can't allocate more for the stack, your app crashes :)

Now for some "fun"
But what happens if Win32 doesn't recognize you're accessing just a bit too far from the stack? The proximity-to-stack threshold is 8-12kB (2-3 pages). Your app gets killed with no warning of GPF ^^.  Try this:

main proc
local par1
local big_one[4080]:DWORD
local par2
mov par1,1
mov par2,2

print "hello stack"


ret
main endp

It'll never print "hello stack" :)


The memory-hogging, mentioned by SpooK, could be a result of their code going through a long chain of procs, that hog lots of stack-space. (do a recursive proc that has many local variables, and you get the idea) . In HLL, generally you can't know of this detail.
I haven't studied if there's a mechanism in the OS for shrinking your stack, so I could be misinforming ^^" .
Posted on 2006-05-31 18:06:56 by Ultrano

First why should i release the stack i allocated?


This becomes important when you are writing subroutines. The subroutine instructions CALL and RET won't work together if the stack pointer is not correctly set.
Posted on 2006-06-02 15:31:14 by tenkey
Guys your posts where very helpful I will definetly be writing software that doesn't hog the stack now. :)

Thanks again. ;)
Posted on 2006-06-02 19:13:32 by gavin_