2 Replies - 6588 Views - Last Post: 19 July 2013 - 02:25 AM Rate Topic: -----

#1 DocNet  Icon User is offline

  • D.I.C Head

Reputation: 0
  • View blog
  • Posts: 118
  • Joined: 11-October 12

How to use ASM inside C++ Win32?

Posted 18 July 2013 - 07:00 AM

Hi,

I'm new in Win32 C++ and Assembler too,

I'm trying to call MessageBox using Assembler inside C++ Win32 code on button click.
For now first problem is with asm code, why he showserrors, and

I have these errors:

Error	1	error C2400: inline assembler syntax error in 'opcode'; found 'constant'	
Error	2	error C2400: inline assembler syntax error in 'opcode'; found 'model'	
Error	3	error C2400: inline assembler syntax error in 'opcode'; found 'casemap'	
Error	4	error C2400: inline assembler syntax error in 'opcode'; found 'MessageBoxA'	
Error	5	error C2400: inline assembler syntax error in 'opcode'; found 'ExitProcess'	
Error	6	error C2400: inline assembler syntax error in 'opcode'; found 'data'	
Error	7	error C2400: inline assembler syntax error in 'opcode'; found 'db'	
Error	8	error C2400: inline assembler syntax error in 'opcode'; found 'db'	
Error	9	error C2400: inline assembler syntax error in 'opcode'; found 'code'	
Error	10	error C2400: inline assembler syntax error in 'opcode'; found 'MessageBoxA'	
Error	11	error C2400: inline assembler syntax error in 'opcode'; found 'constant'	
Error	12	error C2400: inline assembler syntax error in 'opcode'; found 'MsgBoxText'	
Error	13	error C2400: inline assembler syntax error in 'opcode'; found 'MsgBoxCaption'		
Error	14	error C2400: inline assembler syntax error in 'opcode'; found 'constant'	
Error	15	error C2400: inline assembler syntax error in 'opcode'; found 'ExitProcess'	
Error	16	error C2400: inline assembler syntax error in 'opcode'; found 'start'	



Main full code:

// Win32 Vezba02.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "Win32 Vezba02.h"

#define MAX_LOADSTRING 100
#define IDC_MAIN_BUTTON 101

// Global Variables:
HINSTANCE hInst;								// current instance
TCHAR szTitle[MAX_LOADSTRING];					// The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];			// the main window class name

// Forward declarations of functions included in this code module:
ATOM				MyRegisterClass(HINSTANCE hInstance);
BOOL				InitInstance(HINSTANCE, int);
LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK	About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(lpCmdLine);

 	// TODO: Place code here.
	MSG msg;
	HACCEL hAccelTable;

	Vezba02 v;
	
	v.AsmMessage();

	// Initialize global strings
	LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
	LoadString(hInstance, IDC_WIN32VEZBA02, szWindowClass, MAX_LOADSTRING);
	MyRegisterClass(hInstance);

	// Perform application initialization:
	if (!InitInstance (hInstance, nCmdShow))
	{
		return FALSE;
	}

	hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WIN32VEZBA02));

	// Main message loop:
	while (GetMessage(&msg, NULL, 0, 0))
	{
		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	return (int) msg.wParam;
}



//
//  FUNCTION: MyRegisterClass()
//
//  PURPOSE: Registers the window class.
//
//  COMMENTS:
//
//    This function and its usage are only necessary if you want this code
//    to be compatible with Win32 systems prior to the 'RegisterClassEx'
//    function that was added to Windows 95. It is important to call this function
//    so that the application will get 'well formed' small icons associated
//    with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX);

	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= WndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WIN32VEZBA02));
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= MAKEINTRESOURCE(IDC_WIN32VEZBA02);
	wcex.lpszClassName	= szWindowClass;
	wcex.hIconSm		= LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

	return RegisterClassEx(&wcex);
}

//
//   FUNCTION: InitInstance(HINSTANCE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;

   hInst = hInstance; // Store instance handle in our global variable

   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

//
//  FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  PURPOSE:  Processes messages for the main window.
//
//  WM_COMMAND	- process the application menu
//  WM_PAINT	- Paint the main window
//  WM_DESTROY	- post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	int wmId, wmEvent;
	PAINTSTRUCT ps;
	HDC hdc;

	switch (message)
	{
		case WM_COMMAND:
		{

			wmId    = LOWORD(wParam);
			wmEvent = HIWORD(wParam);
			// Parse the menu selections:
			switch (wmId)
			{
				case IDM_about:
				{
					DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
					break;
				}
				case IDM_EXIT:
				{
					DestroyWindow(hWnd);
					break;
				}
				default:
				{
					return DefWindowProc(hWnd, message, wParam, lParam);
				}
			}
		    break;
		}

		case WM_PAINT:
		{
			hdc = BeginPaint(hWnd, &ps);
			// TODO: Add any drawing code here...
			EndPaint(hWnd, &ps);
			break;
		}

		case WM_CREATE:
		{
			//button
			HWND button1 = CreateWindowEx(
				NULL, 
				L"BUTTON", //type
				L"OK",     //title
				WS_TABSTOP|WS_VISIBLE|WS_CHILD|BS_DEFPUSHBUTTON, //config
				50,  //x
				100, //y
				50,  //width
				50,  //height
				hWnd, //parent
				(HMENU)IDC_MAIN_BUTTON,
				GetModuleHandle(NULL),
				NULL);
			break;
		}

		case WM_DESTROY:
		{
			PostQuitMessage(0);
			break;
		}

		default:
		{
			return DefWindowProc(hWnd, message, wParam, lParam);
		}
	}
	return 0;
}

// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	UNREFERENCED_PARAMETER(lParam);
	switch (message)
	{
	case WM_INITDIALOG:
		return (INT_PTR)TRUE;

	case WM_COMMAND:
		if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
		{
			EndDialog(hDlg, LOWORD(wParam));
			return (INT_PTR)TRUE;
		}
		break;
	}
	return (INT_PTR)FALSE;
}

void Vezba02::AsmMessage()
{
	_asm
	{
		.386 
		.model flat,stdcall 
		option casemap:none 
		
		extrn MessageBoxA : PROC
		extrn ExitProcess : PROC

		.data 
		MsgBoxCaption	db "An example of Cancel,Retry,Continue",0 
		MsgBoxText	db "Hello Message Box!",0 

		.code 
		start:
		invoke MessageBoxA,
			NULL,
			addr MsgBoxText,
			addr MsgBoxCaption,
			MB_IConerror

		invoke ExitProcess,NULL
		end start
	}
}



Main problematic code:

void Vezba02::AsmMessage()
{
	_asm
	{
		.386 
		.model flat,stdcall 
		option casemap:none 
		
		extrn MessageBoxA : PROC
		extrn ExitProcess : PROC

		.data 
		MsgBoxCaption	db "An example of Cancel,Retry,Continue",0 
		MsgBoxText	db "Hello Message Box!",0 

		.code 
		start:
		invoke MessageBoxA,
			NULL,
			addr MsgBoxText,
			addr MsgBoxCaption,
			MB_IConerror

		invoke ExitProcess,NULL
		end start
	}




Thanks.

Is This A Good Question/Topic? 0
  • +

Replies To: How to use ASM inside C++ Win32?

#2 NickDMax  Icon User is offline

  • Can grep dead trees!
  • member icon

Reputation: 2255
  • View blog
  • Posts: 9,245
  • Joined: 18-February 07

Re: How to use ASM inside C++ Win32?

Posted 18 July 2013 - 10:01 AM

In my opinion this is not really a very good use of inline assembly. If you want to write a function in assembly then just write it in an .asm file and then run it past the assembler to create a new object file. Create a header and then link against the object file.

You should not need all of the header info you included. The C++ knows what all the symbols are and can place them for you:
#include <iostream>
#include <windows.h>

using namespace std;

int main() {
    const char* msg = "Hello Message Box";
    const char* title = "An example message";
    
    
    //MessageBoxA(NULL, msg, title, MB_OKCANCEL);
    _asm{
    
        push    MB_OKCANCEL
        mov     eax, title
        push    eax
        mov     eax, msg
        push    eax
        push    NULL
        call    DWORD PTR MessageBoxA
    
    }
    
    return 0;
 }



Note that you can't use the invoke directive (as far as I know) in inline assembly. inline assembly does not give you the full featured MASM interface. It is a much smaller subset and so you have to use call.

Generally the way I write assembly is to cheat and let the compiler do it for me and then I edit what it gives me. So to write this little example program I compiled this to assembly:
#include <iostream>
#include <windows.h>

using namespace std;

int main() {
    const char* msg = "Hello Message Box";
    const char* title = "An example message";
    
    
    MessageBoxA(NULL, msg, title, MB_OKCANCEL);
    
    return 0;
}
and copied the code for the MessageBoxA call and edited it a bit. I had some trouble figuring out that I needed the 'DWORD PTR' part of the call.
Was This Post Helpful? 2
  • +
  • -

#3 DocNet  Icon User is offline

  • D.I.C Head

Reputation: 0
  • View blog
  • Posts: 118
  • Joined: 11-October 12

Re: How to use ASM inside C++ Win32?

Posted 19 July 2013 - 02:25 AM

View PostNickDMax, on 18 July 2013 - 10:01 AM, said:

In my opinion this is not really a very good use of inline assembly. If you want to write a function in assembly then just write it in an .asm file and then run it past the assembler to create a new object file. Create a header and then link against the object file.

You should not need all of the header info you included. The C++ knows what all the symbols are and can place them for you:
#include <iostream>
#include <windows.h>

using namespace std;

int main() {
    const char* msg = "Hello Message Box";
    const char* title = "An example message";
    
    
    //MessageBoxA(NULL, msg, title, MB_OKCANCEL);
    _asm{
    
        push    MB_OKCANCEL
        mov     eax, title
        push    eax
        mov     eax, msg
        push    eax
        push    NULL
        call    DWORD PTR MessageBoxA
    
    }
    
    return 0;
 }



Note that you can't use the invoke directive (as far as I know) in inline assembly. inline assembly does not give you the full featured MASM interface. It is a much smaller subset and so you have to use call.

Generally the way I write assembly is to cheat and let the compiler do it for me and then I edit what it gives me. So to write this little example program I compiled this to assembly:
#include <iostream>
#include <windows.h>

using namespace std;

int main() {
    const char* msg = "Hello Message Box";
    const char* title = "An example message";
    
    
    MessageBoxA(NULL, msg, title, MB_OKCANCEL);
    
    return 0;
}
and copied the code for the MessageBoxA call and edited it a bit. I had some trouble figuring out that I needed the 'DWORD PTR' part of the call.


Wow thanks, this works! :)

Thanks for suggestion too, very good explaination :)
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1