CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 5 of 5

Thread: Inline Assembly

  1. #1
    Join Date
    Jan 2009
    Posts
    35

    Inline Assembly

    Hi guys. I'm trying to call MessageBoxA from inline assembly using the following code:

    Code:
    int main(int argc,char* argv[]){
    	HWND hwnd=0;
    	char* text="text";
    	char* cap="caption";
    	UINT ty=MB_OK;
    	__asm{
    		push ty
    		push cap
    		push text
    		push hwnd
    		call MessageBoxA
    	};
    	return 0;
    }
    This code doesn't work, however. Can you guys offer some assistance?

    Thanks.

  2. #2
    Join Date
    Mar 2006
    Posts
    151

    Re: Inline Assembly

    Code:
    __asm
    {
        push ty  
        push cap
        push text
        push hwnd  
        call dword ptr MessageBoxA
    }
    Last edited by GeoRanger; May 20th, 2010 at 11:39 PM. Reason: forgot code tags

  3. #3
    Join Date
    Mar 2006
    Posts
    151

    Re: Inline Assembly

    If you are interested, or if you find it helpful, I'll show you how to figure that out, as follows:

    You and I don't know how to write the assembly code for the call, but the compiler does, so all we need to do is look at what the compiler generates if left to its own devices. To do that start by writing

    Code:
    int main(int argc,char* argv[])
    {
        HWND hwnd=0;
        char* text="text";
        char* cap="caption";
        UINT ty=MB_OK;
    
        MessageBoxA(hwnd, text, cap, ty);
    
        return 0;
    }
    and put a breakpoint on the call to MessageBoxA. When you hit the break, open your dissassembly window to see:

    Code:
    008613BE  mov         dword ptr [hwnd],0 
    	char* text="text";
    008613C5  mov         dword ptr [text],offset string "text" (865810h) 
    	char* cap="caption";
    008613CC  mov         dword ptr [cap],offset string "caption" (865804h) 
    	UINT ty=MB_OK;
    008613D3  mov         dword ptr [ty],0 
    
        MessageBoxA(hwnd, text, cap, ty);
    008613DA  mov         esi,esp 
    008613DC  mov         eax,dword ptr [ty] 
    008613DF  push        eax  
    008613E0  mov         ecx,dword ptr [cap] 
    008613E3  push        ecx  
    008613E4  mov         edx,dword ptr [text] 
    008613E7  push        edx  
    008613E8  mov         eax,dword ptr [hwnd] 
    008613EB  push        eax  
    008613EC  call        dword ptr [__imp__MessageBoxA@16 (868338h)]
    The extra instructions are because it is a debug build. We need to see what it looks like in a release build. Unfortunately, that's not necessarily as straightforward because no debugging information is available, so the object code will be more difficult to navigate. A slick trick which can be very useful when you need to debug a release build is to insert a manual interrupt. Interrupt 3 is the same interrupt used by DebugBreak. With that, you can both land-on and bracket the code you want to see by doing the following:

    Code:
    int main(int argc,char* argv[])
    {
        HWND hwnd=0;
        char* text="text";
        char* cap="caption";
        UINT ty=MB_OK;
    __asm int 3
        MessageBoxA(hwnd, text, cap, ty);
    __asm int 3
        return 0;
    }
    Now just simply run it (as a release build, but either run it out of the debugger, or else attach the debugger to the process after it crashes). When you open the dissassembly window, now you'll see what you need:

    Code:
    __asm int 3
    010C1000  int         3    
        MessageBoxA(hwnd, text, cap, ty);
    010C1001  push        0    
    010C1003  push        offset string "caption" (10C210Ch) 
    010C1008  push        offset string "text" (10C2104h) 
    010C100D  push        0    
    010C100F  call        dword ptr [__imp__MessageBoxA@16 (10C20A4h)] 
    __asm int 3
    010C1015  int         3
    Now to get the result in my first post, simply substitute your variables back for the (optimized) stack pushes, replace the MessageBoxA symbol, and you've got it.
    Last edited by GeoRanger; May 21st, 2010 at 12:15 AM. Reason: Forgot to mention that all four stack pushes need to be restored to the original variables.

  4. #4
    Join Date
    Jan 2009
    Posts
    35

    Re: Inline Assembly

    Ahhh, that helps A LOT. And your short dissertation on how to figure it out is much appreciated. I couldn't find any other documentation on how to do it, either on Google or MSDN.

    On a side note, would you happen to know why it's a dword ptr call?

    Thank you for your time :-D.

  5. #5
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: Inline Assembly

    Because it's an indirect jump.

    A direct jump would require the code segment to affectively change at load time to fixup the jump-to address to the actual API call.

    This has as disadvantage:
    - The code memorypage needs to change from Readonly to ReadWrite.
    - lots and lots of address fixups at load time slowing loading.

    The First is the biggest issue, it would mean that a large part of each programs code would end up being private copies, and thus require a lot more memory. Codepages in dlls etc are now all readonly & shared.

    So what happens is that there is a single DWORD variable for each API function being called (the import table) holding the address of where the function actually is.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured