flat assembler
Message board for the users of flat assembler.

Index > Windows > local variable ~ stack "enter" fails

Author
Thread Post new topic Reply to topic
vbVeryBeginner



Joined: 15 Aug 2004
Posts: 884
Location: \\world\asia\malaysia
vbVeryBeginner
em, the "enter" not work as expected Sad maybe i miss something Confused

fasm manual wrote:

"enter" creates a stack frame that may be used to implement the scope rules of block-structured high-level languages. A "leave" instruction at the end of a procedure complements an "enter" at the beginning of the procedure to simplify stack management and to control access to variables for nested procedures.


the following code is able to be assembled in fasm when i didn't use the enter ~ local variable (stack approach) but fail when using that approach.

Code:
format PE GUI 4.0
entry start

include '%fasminc%\win32a.inc'

struct SECURITY_ATTRIBUTES
        .nLength                dd ?
        .lpSecurityDescriptor   dd ?
        .bInheritHandle         dd ?
ends

section '.data' data readable writeable
        wndH            dd ?
        insH            dd ?
        wndClsName      db 'TUT_21',0
        wndTitle        db 'Tutorial 21',0

        wndCls  WNDCLASS
        wndMsg  MSG
        
        pipeSecAttr     SECURITY_ATTRIBUTES
        pipeReadH       dd ?
        pipeWriteH      dd ?
        
section '.code' code readable executable
   start:
        invoke  GetModuleHandle,0
                mov  [insH],eax
                mov  [wndCls.hInstance],eax
                mov  [wndCls.style],CS_HREDRAW or CS_VREDRAW
                mov  [wndCls.lpfnWndProc],window_procedure
                mov  [wndCls.lpszClassName],wndClsName
                mov  [wndCls.hbrBackground],COLOR_BTNFACE+1
        invoke  LoadIcon,NULL,IDI_APPLICATION
                mov  [wndCls.hIcon],eax
        invoke  LoadCursor,NULL,IDC_ARROW
                mov  [wndCls.hCursor],eax
        invoke  RegisterClass,wndCls

        invoke  CreateWindowEx,WS_EX_CLIENTEDGE,\
                wndClsName,wndTitle,\
                WS_OVERLAPPEDWINDOW + WS_VISIBLE,\
                CW_USEDEFAULT,CW_USEDEFAULT,\
                400,240,\
                NULL,NULL,[insH],NULL
                mov  [wndH],eax

   ;+---------------------------+
   ;| entering the message loop |
   ;+---------------------------+
   window_message_loop_start:
        invoke  GetMessage,wndMsg,NULL,0,0
                or    eax,eax
                je    window_message_loop_end
        invoke  TranslateMessage,wndMsg
        invoke  DispatchMessage,wndMsg
                jmp     window_message_loop_start

   window_message_loop_end:
        invoke  ExitProcess,0

   ;+----------------------+
   ;| the window procedure |
   ;+----------------------+
   proc window_procedure,hWnd,uMsg,wParam,lParam
                push ebx esi edi
                cmp  [uMsg],WM_CREATE
                je   wmCREATE
                cmp  [uMsg],WM_DESTROY
                je   wmDESTROY
        

        wmDEFAULT:
                invoke  DefWindowProc,[hWnd],[uMsg],[wParam],[lParam]
                        jmp  wmBYE
        wmCREATE:
                        mov  [pipeSecAttr.nLength], sizeof.SECURITY_ATTRIBUTES
                        mov  [pipeSecAttr.lpSecurityDescriptor],NULL
                        mov  [pipeSecAttr.bInheritHandle],TRUE
                invoke  CreatePipe,pipeReadH,pipeWriteH,pipeSecAttr,NULL
                        cmp  eax,NULL
                        je   @f
                        jmp  wmBYE
                @@:
                invoke  MessageBox,[hWnd],wndTitle,wndTitle,MB_OK
                        jmp  wmBYE
        wmDESTROY:
                invoke  PostQuitMessage,0

        wmBYE:
                pop edi esi ebx
                return
   endp

section '.idata' import data readable
    library     KERNEL32, 'KERNEL32.DLL',\
                USER32,   'USER32.DLL'
    
    import      KERNEL32,\
                GetModuleHandle,        'GetModuleHandleA',\
                CreatePipe,             'CreatePipe',\
                ExitProcess,            'ExitProcess'
    import      USER32,\
                RegisterClass,          'RegisterClassA',\
                CreateWindowEx,         'CreateWindowExA',\
                DefWindowProc,          'DefWindowProcA',\
                LoadCursor,             'LoadCursorA',\
                LoadIcon,               'LoadIconA',\
                SendMessage,            'SendMessageA',\
                GetMessage,             'GetMessageA',\
                MessageBox,             'MessageBoxA',\
                DestroyWindow,          'DestroyWindow',\
                TranslateMessage,       'TranslateMessage',\
                DispatchMessage,        'DispatchMessageA',\
                PostQuitMessage,        'PostQuitMessage'
    


this code fail, (using local variable)
Code:
format PE GUI 4.0
entry start

include '%fasminc%\win32a.inc'

struct SECURITY_ATTRIBUTES
        .nLength                dd ?
        .lpSecurityDescriptor   dd ?
        .bInheritHandle         dd ?
ends

section '.data' data readable writeable
        wndH            dd ?
        insH            dd ?
        wndClsName      db 'TUT_21',0
        wndTitle        db 'Tutorial 21',0

        wndCls  WNDCLASS
        wndMsg  MSG
        

        
section '.code' code readable executable
   start:
        invoke  GetModuleHandle,0
                mov  [insH],eax
                mov  [wndCls.hInstance],eax
                mov  [wndCls.style],CS_HREDRAW or CS_VREDRAW
                mov  [wndCls.lpfnWndProc],window_procedure
                mov  [wndCls.lpszClassName],wndClsName
                mov  [wndCls.hbrBackground],COLOR_BTNFACE+1
        invoke  LoadIcon,NULL,IDI_APPLICATION
                mov  [wndCls.hIcon],eax
        invoke  LoadCursor,NULL,IDC_ARROW
                mov  [wndCls.hCursor],eax
        invoke  RegisterClass,wndCls

        invoke  CreateWindowEx,WS_EX_CLIENTEDGE,\
                wndClsName,wndTitle,\
                WS_OVERLAPPEDWINDOW + WS_VISIBLE,\
                CW_USEDEFAULT,CW_USEDEFAULT,\
                400,240,\
                NULL,NULL,[insH],NULL
                mov  [wndH],eax

   ;+---------------------------+
   ;| entering the message loop |
   ;+---------------------------+
   window_message_loop_start:
        invoke  GetMessage,wndMsg,NULL,0,0
                or    eax,eax
                je    window_message_loop_end
        invoke  TranslateMessage,wndMsg
        invoke  DispatchMessage,wndMsg
                jmp     window_message_loop_start

   window_message_loop_end:
        invoke  ExitProcess,0

   ;+----------------------+
   ;| the window procedure |
   ;+----------------------+
   proc window_procedure,hWnd,uMsg,wParam,lParam
        pipeSecAttr     SECURITY_ATTRIBUTES
        pipeReadH       dd ?
        pipeWriteH      dd ?
        enter
        
                push ebx esi edi
                cmp  [uMsg],WM_CREATE
                je   wmCREATE
                cmp  [uMsg],WM_DESTROY
                je   wmDESTROY
        

        wmDEFAULT:
                invoke  DefWindowProc,[hWnd],[uMsg],[wParam],[lParam]
                        jmp  wmBYE
        wmCREATE:
                        mov  [pipeSecAttr.nLength], sizeof.SECURITY_ATTRIBUTES
                        mov  [pipeSecAttr.lpSecurityDescriptor],NULL
                        mov  [pipeSecAttr.bInheritHandle],TRUE
                invoke  CreatePipe,pipeReadH,pipeWriteH,pipeSecAttr,NULL
                        cmp  eax,NULL
                        je   @f
                        jmp  wmBYE
                @@:
                invoke  MessageBox,[hWnd],wndTitle,wndTitle,MB_OK
                        jmp  wmBYE
        wmDESTROY:
                invoke  PostQuitMessage,0

        wmBYE:
                pop edi esi ebx
                return
   endp

section '.idata' import data readable
    library     KERNEL32, 'KERNEL32.DLL',\
                USER32,   'USER32.DLL'
    
    import      KERNEL32,\
                GetModuleHandle,        'GetModuleHandleA',\
                CreatePipe,             'CreatePipe',\
                ExitProcess,            'ExitProcess'
    import      USER32,\
                RegisterClass,          'RegisterClassA',\
                CreateWindowEx,         'CreateWindowExA',\
                DefWindowProc,          'DefWindowProcA',\
                LoadCursor,             'LoadCursorA',\
                LoadIcon,               'LoadIconA',\
                SendMessage,            'SendMessageA',\
                GetMessage,             'GetMessageA',\
                MessageBox,             'MessageBoxA',\
                DestroyWindow,          'DestroyWindow',\
                TranslateMessage,       'TranslateMessage',\
                DispatchMessage,        'DispatchMessageA',\
                PostQuitMessage,        'PostQuitMessage'
    


the error message i got is
Code:
H:\tutorial>fasm t2.asm
flat assembler  version 1.55
t2.asm [83]:
                invoke  CreatePipe,pipeReadH,pipeWriteH,pipeSecAttr,NULL
D:\FASM\1.55W\INCLUDE\macro/stdcall.inc [81] invoke [3]:
     pushd arg
error: invalid value.
    


i don't know, but does this mean, not ALL variable can be treated as LOCAL variables?
or i miss the "leave" stuff? or something else?

sincerely,
vbVeryBeginner d(?~?)b
Post 01 Oct 2004, 15:31
View user's profile Send private message Visit poster's website Reply with quote
wanderer



Joined: 18 Jun 2003
Posts: 44
Location: Moldova, Kishinev
wanderer
vbVeryBeginner wrote:

i don't know, but does this mean, not ALL variable can be treated as LOCAL variables?
or i miss the "leave" stuff? or something else?

sincerely,
vbVeryBeginner d(?~?)b


You should know that local variables are placed on stack and that means that you can't just write push <localvar> as it will result in instruction like this: push ebx+14. Write instead "lea eax,[localvar] / push eax" or something like this. Try also searching the forum, this have already been discussed somewhere.

_________________
Best regards,
Antoch Victor
Post 01 Oct 2004, 17:35
View user's profile Send private message Yahoo Messenger Reply with quote
vbVeryBeginner



Joined: 15 Aug 2004
Posts: 884
Location: \\world\asia\malaysia
vbVeryBeginner
yup, you are correct, wanderer, thanks Smile

Code:
push NULL
lea  eax,[pipeSecAttr]
push eax
lea  eax,[pipeWriteH]
push eax
lea  eax,[pipeReadH]
push eax
call [CreatePipe]
    


is equal to
Code:
invoke  CreatePipe,pipeReadH,pipeWriteH,pipeSecAttr,NULL
    


is equal also to

Code:
lea  eax,[pipeSecAttr]
lea  ebx,[pipeWriteH]
lea  ecx,[pipeReadH]
invoke CreatePipe,ecx,ebx,eax,NULL
    


when using local variable Smile

wanderer wrote:

Try also searching the forum

em, i don't know what keyword to identify that particular thread, but i search using ur nick :p, and saw a thread named something like "iStream", which if see from the title ~ totally unassociate with my problem Smile, so i put the link here, (for reference to others)

http://board.flatassembler.net/topic.php?t=152


sincerely,
vbVeryBeginner d(&-&)b
Post 02 Oct 2004, 07:35
View user's profile Send private message Visit poster's website Reply with quote
pelaillo
Missing in inaction


Joined: 19 Jun 2003
Posts: 878
Location: Colombia
pelaillo
Hi vbVeryBeginner,

http://board.flatassembler.net/topic.php?t=2346

Look also that is better to use a dot so you can reuse names for locals through procedures.
Post 02 Oct 2004, 13:32
View user's profile Send private message Yahoo Messenger Reply with quote
vbVeryBeginner



Joined: 15 Aug 2004
Posts: 884
Location: \\world\asia\malaysia
vbVeryBeginner
actually, i am not really so understand about the concept of having a (dot). variable Confused

i know they exists in structure, but what is the meaning of a dot (.) variable? the feature and so on?

i am kinda blur :-/

sincerely,
me d(&9#)b
Post 02 Oct 2004, 18:31
View user's profile Send private message Visit poster's website Reply with quote
vbVeryBeginner



Joined: 15 Aug 2004
Posts: 884
Location: \\world\asia\malaysia
vbVeryBeginner
what is the different of a dot variable that reside in structure and the dot variable that function as local variable in proc stack?
Post 02 Oct 2004, 18:32
View user's profile Send private message Visit poster's website Reply with quote
wanderer



Joined: 18 Jun 2003
Posts: 44
Location: Moldova, Kishinev
wanderer
vbVeryBeginner wrote:
actually, i am not really so understand about the concept of having a (dot). variable Confused

i know they exists in structure, but what is the meaning of a dot (.) variable? the feature and so on?

i am kinda blur :-/

Quote from fasm's manual:
Tomasz Grisztar wrote:

The label whose name begins with dot is treated as local label, and its name is attached to the name of last global label (with name beginning with anything but dot) to make the full name of this label. So you can use the short name (beginning with dot) of this label anywhere before the next global label is defined, and in the other places you have to use the full name. Label beginning with two dots are the exception - they are like global, but they don't become the new prefix for local labels.


vbVeryBeginner wrote:
what is the different of a dot variable that reside in structure and the dot variable that function as local variable in proc stack?

You should read the fasm manual.

_________________
Best regards,
Antoch Victor
Post 02 Oct 2004, 22:41
View user's profile Send private message Yahoo Messenger Reply with quote
wanderer



Joined: 18 Jun 2003
Posts: 44
Location: Moldova, Kishinev
wanderer
vbVeryBeginner wrote:
wanderer wrote:
Try also searching the forum

em, i don't know what keyword to identify that particular thread, but i search using ur nick :p, and saw a thread named something like "iStream", which if see from the title ~ totally unassociate with my problem Smile

Well, I didn't post anything for a long time, so it wasn't best idea Wink. I tryed to find "local variables" with <search for all terms> and found several threads that may be interesting for you. Here is one of them: http://board.flatassembler.net/topic.php?t=441

_________________
Best regards,
Antoch Victor
Post 03 Oct 2004, 01:52
View user's profile Send private message Yahoo Messenger Reply with quote
vbVeryBeginner



Joined: 15 Aug 2004
Posts: 884
Location: \\world\asia\malaysia
vbVeryBeginner
thank you, wanderer for the searching and the thread

Quote:

I didn't post anything for a long time

well, i notice that too, but i sincerely wish you would post a lot in the future, you seem to be a knowledgeable person in ASM Smile

*ps: hopefully i am not wrong Wink Laughing

sincerely,
vbVeryBeginner d(^-^)b
Post 03 Oct 2004, 02:43
View user's profile Send private message Visit poster's website Reply with quote
vbVeryBeginner



Joined: 15 Aug 2004
Posts: 884
Location: \\world\asia\malaysia
vbVeryBeginner
i try this code, it could be assembled but display other than the text i wish to see Sad

Code:
        wmCREATE:
                call    testing_1
                        jmp  wmBYE

   proc testing_1
        txt1    db 'text 1 from proc testing_1',0
        enter
                lea eax,[txt1]
        invoke  MessageBox,NULL,eax,eax,MB_OK
        return
   endp
    


Image
Post 03 Oct 2004, 05:28
View user's profile Send private message Visit poster's website Reply with quote
roticv



Joined: 19 Jun 2003
Posts: 374
Location: Singapore
roticv
Are you crazy? Local variables are not initialized when you are about to use it. They are part of the stack. So you are essentially displaying all the data you pushed onto the stack previously.

If you want strings, declare them as global data.
Post 03 Oct 2004, 07:17
View user's profile Send private message Visit poster's website MSN Messenger Reply with quote
vbVeryBeginner



Joined: 15 Aug 2004
Posts: 884
Location: \\world\asia\malaysia
vbVeryBeginner
Code:
      proc testing_1
        push ebp
        mov  ebp,esp
        push 0x00494847
        push 0x46454443
        push 0x42414020
        mov  eax,esp
        
        invoke MessageBox,NULL,eax,eax,MB_OK
        mov  esp,ebp
        pop  ebp
        return
   endp
    


Image

if this is possible, why pushing string into stack is impossible?


Last edited by vbVeryBeginner on 03 Oct 2004, 08:53; edited 1 time in total
Post 03 Oct 2004, 08:33
View user's profile Send private message Visit poster's website Reply with quote
vbVeryBeginner



Joined: 15 Aug 2004
Posts: 884
Location: \\world\asia\malaysia
vbVeryBeginner
i wonder, if that possible for the "enter" to reverse our string and push them into stack accordingly in dwords

or

string is not suitable to be put on stack?? must (MUST) be treated as global data?

which one is better, optimize or guru ways?
Post 03 Oct 2004, 08:40
View user's profile Send private message Visit poster's website Reply with quote
roticv



Joined: 19 Jun 2003
Posts: 374
Location: Singapore
roticv
It takes lesser number of bytes if they are declared as global data.
Post 03 Oct 2004, 09:06
View user's profile Send private message Visit poster's website MSN Messenger Reply with quote
wanderer



Joined: 18 Jun 2003
Posts: 44
Location: Moldova, Kishinev
wanderer
vbVeryBeginner wrote:
if this is possible, why pushing string into stack is impossible?

Of course, it's possible, but you'll have to do in runtime, not at the time of compilation. I think one should have special reason to do it, because defining strings as global data really takes less bytes, as roticv said. Another way of string definition (for example, used only once) is:
Code:
        push MB_OK
        call @f
        db "Message",0
     @@:
        call @f
        db "Title",0
     @@:
        invoke MessageBox,NULL
    

_________________
Best regards,
Antoch Victor
Post 03 Oct 2004, 10:40
View user's profile Send private message Yahoo Messenger Reply with quote
vbVeryBeginner



Joined: 15 Aug 2004
Posts: 884
Location: \\world\asia\malaysia
vbVeryBeginner
wanderer wrote:

I think one should have special reason to do it


i guess it is better to group a group of proc variable under a place for better management, otherwise, some of the proc variables are on stack, some on global... em... ...

anyway..
u show me a nice trick Smile thanks

Code:
        push MB_OK 
        call @f 
        db "Message",0 
     @@: 
        call @f 
        db "Title",0 
     @@: 
        invoke MessageBox,NULL 
    


sincerely,
vbVeryBeginner
Post 03 Oct 2004, 12:19
View user's profile Send private message Visit poster's website Reply with quote
wanderer



Joined: 18 Jun 2003
Posts: 44
Location: Moldova, Kishinev
wanderer
vbVeryBeginner wrote:
i guess it is better to group a group of proc variable under a place for better management, otherwise, some of the proc variables are on stack, some on global... em... ...

You can have all the variables on stack, however in this case you'll have to provide initialization code if you wish them to be initialized. Global variables can be initialized at the compile time, local - only at runtime. This is because memory for local variables is allocated when entering procedures (and therefore are filled with random values), and global variables exist all the time program runs.

vbVeryBeginner wrote:
anyway..
u show me a nice trick Smile thanks

Feel free to ask Wink.
This trick is used in 'win32ax.inc' to make possible to write something like:
Code:
invoke MessageBox,NULL,"Message","Title",MB_OK    

This macro also lets you use local variables addresses in it.

_________________
Best regards,
Antoch Victor
Post 03 Oct 2004, 17:09
View user's profile Send private message Yahoo Messenger Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2020, Tomasz Grysztar. Also on GitHub, YouTube, Twitter.

Website powered by rwasa.