Thread: calling function in asm

  1. #1
    Registered User
    Join Date
    Jul 2007
    Posts
    61

    calling function in asm

    I can call the function by doing this:
    Code:
    typedef void (__cdecl* ZChatOutputFunction)(const char* lpcMsg, int iType,int iLoc,DWORD dwColor);
    ZChatOutputFunction ZChatOutput = (ZChatOutputFunction)ZChatOutputAddress;
    Then make it output "Hello." for example like this:
    Code:
    ZChatOutput("Hello.", 2, 0, 0xFFFFFFFF);
    Now i'm trying to write this in inline asm this is what i think it schould be:

    Code:
    void ZChatOutput(const char *Message)
    {
              _asm{
                      mov eax,ZChatOutputAddress
                      PUSH 0xFFFFFFFF
                      PUSH 0
                      PUSH 2
                      PUSH Message
                      call eax
                      add esp,16
              }
    }
    Then doing
    Code:
    ZChatOutput("Hello.");
    Am I doing this right?
    or do i need pushad and popad to?

  2. #2
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    If you want to preserve the registers, then go ahead and do something like pusha/popa or whatever. I don't think you need to preserve them, though.

    Looks relatively fine to me.

  3. #3
    Registered User
    Join Date
    Jul 2007
    Posts
    61
    So when do you acctualy have to use pushad and popad then?

  4. #4
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    Well, it all depends on your convention of how you handle your registers.

    If you're relying on eax and ebx, let's say, to hold some values, you need to preserve those before a function call which may or may not mess them up. For example, from my experience with the last x86 assembler I was using, printf() tends to mess up all four of the general purpose registers. For whatever reason, I tend to do a lot of work with registers, so I have to push them and pop them a lot.

    If you want to be sure you don't corrupt anything, then go ahead and do the pushing and popping. I think modern compilers should be able to figure out which goes where and what registers are being used, though, so I'm not completely sure you have to do it.

    Someone who is a little more experienced with assembly and modern compilers would probably be better to answer this.

  5. #5
    Registered User
    Join Date
    Jul 2007
    Posts
    61
    Code:
    struct MUID{
                 unsigned long firstID;
                 unsigned long secondID;
    };
    MUID* Char1ID = new MUID;
    MUID* StageID = new MUID;
    
    void Test()
    {
                    Char1ID->firstID = 0;
                    Char1ID->secondID = 1555;
                    StageID->firstID = 0;
                    StageID->secondID = 4844;
                    _asm{
                            mov eax,LeaveStageAddress
                            PUSH StageID
                            PUSH Char1ID
                            call eax
                            add esp,8
                    }
    }
    Schould my add esp be 8 or 16 in this example?

  6. #6
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    I believe unsigned long is 4 bytes, yes? If so, then 8 is presume.

  7. #7
    Registered User
    Join Date
    Jul 2007
    Posts
    61
    But theres
    Code:
    Char1ID->firstID = 0;
                    Char1ID->secondID = 1555;
                    StageID->firstID = 0;
                    StageID->secondID = 4844;
    so schouldn't i use 16 then?

  8. #8
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    You're pushing TWO values to the stack, not 4.
    ONLY clean up what you pushed, and never more.

  9. #9
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Assuming that LeaveStageAddress() is a cdecl function (rather than thiscall or stdcall), and we also assume that you are using 32-bit compiler, then removing 8 bytes from the stack is the correct thing to do.

    It's easy to check these things. Set a breakpoint before the first push, take note of the value in esp, then step or break after the function call and stack cleanup, and check the value again.

    Of course, I don't see ANY point in calling either of these functions from inline assembler - there is absolutely no gain from that at all. But maybe this is just examples of something more complex.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  10. #10
    Registered User
    Join Date
    Jul 2007
    Posts
    61
    Code:
    /*	ZChatOutput	*/
    void ZChatOutput(const char* lpcFmt, ...)
    {
    	char szBuf[0x4000];
    	va_list vaArgs;
    	va_start(vaArgs, lpcFmt);
    	_vsnprintf(szBuf, sizeof(szBuf), lpcFmt, vaArgs);
    	va_end(vaArgs);
    	szBuf[0x4000-1] = 0;
    	_asm{
    		pushad
    		//Move ZChatOutputAddress into eax
    		mov eax,ZChatOutputAddress
    		//Push 0xFFFFFFFF onto the stack
    		PUSH 0xFFFFFFFF
    		//Push 0 onto the stack
    		PUSH 0
    		//Push 2 onto the stack
    		PUSH 2
    		//Push szBuf onto the stack
    		PUSH szBuf
    		//Call ZChatOutput
    		call eax
    		//Cleanup the stack by adding the size of bytes pushed on the stack
    		add esp,16
    		popad
    	}
    }
    Error: warning C4409: illegal instruction size

    How do i fix?

  11. #11
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Can you indicate which line the compiler is complaining about - as I don't have the rest of

    Code:
    		pushad
    		//Move ZChatOutputAddress into eax
    		mov eax,ZChatOutputAddress
    		//Push 0xFFFFFFFF onto the stack
    		PUSH 0xFFFFFFFF
    		//Push 0 onto the stack
    		PUSH 0
    		//Push 2 onto the stack
    		PUSH 2
    		//Push szBuf onto the stack
    		PUSH dword ptr szBuf
    		//Call ZChatOutput
    		call eax
    		//Cleanup the stack by adding the size of bytes pushed on the stack
    		add esp,16
    		popad
    Do you think your comments like "move ZChatOutputAddress into eax" actually adds anything useful?
    Or "push 0xFFFFFFFF onto the stack" - where else would we be pushing it?

    If someone doesn't at all understand assembly language, the effect/purpose of pushing something onto somehting else is pretty much lost anyways, so you are just telling people who don't know something they can't understand, and those who DO know something that is obvious from reading the assembler instructions anyways.

    I'm 99% sure that you don't need to use pushad/popad around your call, unless ZChatOutput isn't a C function.

    The call ZChatOutput comment is meaningfull to some extent, in case you have forgotten what eax was loaded with about 4 lines [not counting meaningless commments] above.

    And of course, I still see ABSOLUTELY no reason why you are doing this in assembler rather than plain C or C++.

    The above code can be written as:
    Code:
    ...
    void (__cdecl *func)(char *szBuf, int a, int b, int c);  // I don't know what the three integer arguments are, so I just named them pointless names.
    ...
    func = ZChatOutput;
    func(szBuf, 2, 0, -1);
    }
    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 4
    Last Post: 05-13-2011, 08:28 AM
  2. Seg Fault in Compare Function
    By tytelizgal in forum C Programming
    Replies: 1
    Last Post: 10-25-2008, 03:06 PM
  3. In over my head
    By Shelnutt2 in forum C Programming
    Replies: 1
    Last Post: 07-08-2008, 06:54 PM
  4. Undefined Reference Compiling Error
    By AlakaAlaki in forum C++ Programming
    Replies: 1
    Last Post: 06-27-2008, 11:45 AM
  5. Replies: 28
    Last Post: 07-16-2006, 11:35 PM