News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

stack, words and call ...

Started by James Ladd, May 12, 2005, 09:02:48 AM

Previous topic - Next topic

James Ladd

I hope this is a simple question ...

If i push my arguments manually and use call for a routine, do I need to pop the arguments off
the stack after the call if I used the default proc definition ?
eg:
myproc proc arg1:DWORD, arg2:DWORD

Also, how can I push a word and balance the stack ?

rgs, striker

Petroizki

If you are using stdcall calling convention, you don't need to pop the arguments off the stack, the procedure does this itself. With C -calling convention you can pop the arguments off the stack after the call like this;
push 1
push 2
call myproc
add esp, 8 ; balance stack


You can "push" a word for example like this:
sub esp, 4 ; or push 'someregister', just make sure you make room for the value
mov word ptr [esp], dx ; move WORD to the stack

James Ladd


Tedd

For most functions in the windows api you don't need to since they do the cleanup themselves.
You just have to watch out for C type functions (such as wsprintf) where you have to do the cleanup - because they can have any number of arguments and the function doesn't know in advance how many that is.
Most functions you'll use will be 'stdcall' - so you don't need to cleanup, but if they're declared as "proto c" then you've got to do it :wink

Usually word arguments are padded with another null word to keep the other arguments aligned, but it depends what the function expects ::)
No snowflake in an avalanche feels responsible.

hutch--

James,

Just to make life complicated, here is another way to perform STDCALL.


            .data
              TitleTxt db "MOV stack",0
              MsgTxt db "Hi There",0
            .code

            mov DWORD PTR [esp-16], 0
            mov DWORD PTR [esp-12], OFFSET MsgTxt
            mov DWORD PTR [esp-8], OFFSET TitleTxt
            mov DWORD PTR [esp-4], MB_OK
            sub esp, 16

            call MessageBox
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

AeroASM

Quote from: striker on May 12, 2005, 09:02:48 AM
I hope this is a simple question ...

If i push my arguments manually and use call for a routine, do I need to pop the arguments off
the stack after the call if I used the default proc definition ?
eg:
myproc proc arg1:DWORD, arg2:DWORD

Also, how can I push a word and balance the stack ?

rgs, striker

At the top of your source code, you should have the line .model flat,stdcall.
This means that all procs are stdcall by default.
In stdcall the procedure is responsible for stack balancing.

If you push a dword and balance the stack it is like this:

push eax
add esp,4

because a dword is 4 bytes. A word is only two bytes so:

push ax
add esp,2

doomsday

Quote from: Hutch--Just to make life complicated, here is another way to perform STDCALL.

Hutch,

You're a bad, bad man <g>  While it'd very likely work, it's bad practice to write below (E)SP.

I seem to recall it that writing below the stack pointer caused problems under DOS because TSRs and int. handlers use the same stack as the current program and thus you could end up with stack corruption.  Just as a matter of idle curiosity, does anyone know if writing below the stack pointer does cause any problems under Windows?  I'd guess not, but I'm curious if anyone's tried it.

regards,
-Brent

Petroizki

Quote from: doomsday on May 12, 2005, 05:47:48 PMJust as a matter of idle curiosity, does anyone know if writing below the stack pointer does cause any problems under Windows?  I'd guess not, but I'm curious if anyone's tried it.
There was some discussion about this in the other forum: http://board.win32asmcommunity.net/index.php?topic=20128.0.

At least some debuggers can mess the data in the negative offsets of the esp.

MichaelW

Striker,

If your procedure expects a word argument, for a memory operand you could do either of these:

sub   esp,2
push  mem16

push  word ptr 0
push  mem16

And for a register operand, you could just push the dword register.
eschew obfuscation

hutch--

 :bg

> You're a bad, bad man

You are probably right but all it does is occupy the same memory as 4 pushes so one of these days I will have a play to see if 4 MOVs are faster than 4 PUSHs.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

raymond

You can certainly achieve the same goal with slight modifications and without taking any potential risk related to writing below the stack pointer.


            sub esp, 16
            mov DWORD PTR [esp], 0
            mov DWORD PTR [esp+4], OFFSET MsgTxt
            mov DWORD PTR [esp+8], OFFSET TitleTxt
            mov DWORD PTR [esp+12], MB_OK
            call MessageBox


Raymond
When you assume something, you risk being wrong half the time
http://www.ray.masmcode.com

James Ladd


hutch--

 :bg

James,

You are now the victim of a plethora of deviant STDCALL techniques.  :boohoo:
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

Petroizki

Quote from: hutch-- on May 13, 2005, 12:42:50 AMYou are probably right but all it does is occupy the same memory as 4 pushes so one of these days I will have a play to see if 4 MOVs are faster than 4 PUSHs.
I hope i'm not going too off-topic, but i just have to say that in my Athlon, three or more mov's are faster than pushes. It also seems that Visual C++/g++ compiler goes heavily on moving the paramaters to the stack, rather than pushing them.

Vortex

Hi striker,

You can code your own invoke macro, here is an example:

_invoke MACRO funcname:REQ,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15,p16,p17,p18,p19,p20
local pos,counter
counter=0

    FOR arg,<p20,p19,p18,p17,p16,p15,p14,p13,p12,p11,p10,p9,p8,p7,p6,p5,p4,p3,p2,p1>

        IFNB <arg>
             
             counter=counter+1
             pos=@InStr(1,arg,<ADDR>) OR @InStr(1,arg,<addr>) OR @InStr(1,arg,<Addr>)

             IF pos

                IF (OPATTR(@SubStr(arg,%pos+5))) EQ 98
                        lea eax,@SubStr(<arg>,%pos+5)
                        push eax
                ELSE
                        push OFFSET @SubStr(<arg>,%pos+5)
                ENDIF

             ELSE
                        push arg
             ENDIF
        ENDIF
    ENDM
call funcname
ENDM