How to compile this code in Assembly on Windows?
I was seeing a creation of a basic window in assemblythat displays a message, I have already installed the compiler NASM but da error to compile.
.386
.MODEL FLAT, STDCALL
INCLUDE windows.inc
INCLUDE kernel32.inc
INCLUDE user32.inc
INCLUDELIB kernel32.lib
INCLUDELIB user32.lib
.DATA
WndClsName BYTE "AsmWnd", 0h;
WndTitleName BYTE "Hello, World!", 0h;
MsgBoxTxt BYTE "Programadores de verdade programam assim", 0h;
CmdShow DWORD SW_SHOWDEFAULT;
.DATA?
window WNDCLASSEX {};
hInstance HINSTANCE ?;
hWnd HWND ?;
message MSG {};
.CODE
Entry:
push 0h;
call GetModuleHandle;
mov hInstance, eax;
mov window.cbSize, SIZEOF WNDCLASSEX;
mov window.hbrBackground, COLOR_WINDOW;
mov window.hIcon, 0h;
mov window.hIconSm, 0h;
mov window.cbClsExtra, 0h;
push IDC_HAND;
push 0h;
call LoadCursor;
mov window.hCursor, eax;
push hInstance;
pop window.hInstance;
mov window.lpszMenuName, 0h;
mov window.lpszClassName, OFFSET WndClsName;
mov window.style, CS_VREDRAW or CS_HREDRAW;
mov window.lpfnWndProc, OFFSET WndProc;
push eax;
lea eax, window;
push eax;
call RegisterClassEx;
pop eax;
push 0h;
push hInstance;
push 0h;
push 0h;
push 250d;
push 250d;
push 250d;
push 250d;
push WS_OVERLAPPEDWINDOW;
lea eax, WndTitleName;
push eax;
lea eax, WndClsName;
push eax;
push WS_EX_TOPMOST;
call CreateWindowExA;
mov hWnd, eax;
cmp hWnd, 0h;
jne _Ok;
push 1h;
call ExitProcess;
_Ok:
push CmdShow;
push hWnd;
call ShowWindow;
push hWnd;
call UpdateWindow;
_GetMessageLoop:
push 0h;
push 0h;
push 0h;
lea eax, message;
push eax;
call GetMessage;
cmp eax, 0h;
je _EndMessageLoop;
lea eax, message;
push eax;
call TranslateMessage;
lea eax, message;
push eax;
call DispatchMessage;
jmp _GetMessageLoop;
_EndMessageLoop:
mov eax, message.wParam
WndProc proc hWindow:HWND, uMsg:UINT, wParam:DWORD, lParam:DWORD
cmp uMsg, WM_DESTROY;
je _WM_DESTROY;
cmp uMsg, WM_LBUTTONDOWN;
je _WM_LBUTTONDOWN;
push lParam;
push wParam;
push uMsg;
push hWindow;
call DefWindowProc;
jmp _EndWndProc;
_WM_LBUTTONDOWN:
push MB_OK or MB_ICONINFORMATION;
push OFFSET WndTitleName;
push OFFSET MsgBoxTxt;
push hWindow;
call MessageBoxA;
jmp _EndWndProc;
_WM_DESTROY:
push 0h;
call PostQuitMessage;
_EndWndProc:
Ret
WndProc EndP
END Entry;
1 answers
To compile this code, you must use the MASM, No NASM, are assemblers different.
In order for your code to execute, make the following changes:
-
Below the
.model
directive, use theoption casemap
,option casemap
it can beALL
,NONE
orNOTPUBLIC
, being last the default. Usingoption casemap:none
, the MASM preserves the dos box identifiers. Usingoption casemap:all
, the MASM passes all identifiers to uppercase, for example, bothmsgboxtxt
andMsgBoxTxt
are transformed intoMSGBOXTXT
). The goal is to useNONE
so that the identifiers box is preserved, so below the.model
directive do:.386 .MODEL FLAT, STDCALL option casemap:none
-
To avoid the error fatal error A1000: cannot open file, put the full path of the files
.inc
and.lib
. Swap:INCLUDE windows.inc INCLUDE kernel32.inc INCLUDE user32.inc INCLUDELIB kernel32.lib INCLUDELIB user32.lib
By:
include \masm32\include\windows.inc include \masm32\include\kernel32.inc include \masm32\include\user32.inc includelib \masm32\lib\kernel32.lib includelib \masm32\lib\user32.lib
-
Save the file Ctrl+S , and in the top menu click Project ⇢ Build all , then run the program by clicking Run Program.
Result:
The code can be reduced using the INVOKE
to call a function, instead of putting the function arguments in the stack and calling the function with CALL
.
.386
.model flat, stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
.DATA
WndClsName BYTE "AsmWnd", 0h;
WndTitleName BYTE "Hello, World!", 0h;
MsgBoxTxt BYTE "Programadores de verdade programam assim", 0h;
CmdShow DWORD SW_SHOWDEFAULT;
.DATA?
window WNDCLASSEX {};
hInstance HINSTANCE ?;
hWnd HWND ?;
message MSG {};
.CODE
Entry:
invoke GetModuleHandle, 0h;
mov hInstance, eax;
mov window.cbSize, SIZEOF WNDCLASSEX;
mov window.hbrBackground, COLOR_WINDOW;
mov window.hIcon, 0h;
mov window.hIconSm, 0h;
mov window.cbClsExtra, 0h;
invoke LoadCursor, 0h, IDC_HAND;
mov window.hCursor, eax;
push hInstance;
pop window.hInstance;
mov window.lpszMenuName, 0h;
mov window.lpszClassName, offset WndClsName;
mov window.style, CS_VREDRAW or CS_HREDRAW;
mov window.lpfnWndProc, offset WndProc;
invoke RegisterClassEx, offset window;
invoke CreateWindowExA, WS_EX_TOPMOST, offset WndClsName, offset WndTitleName, WS_OVERLAPPEDWINDOW, 250d, 250d, 250d, 250d, 0h, 0h, hInstance, 0h;
mov hWnd, eax;
cmp hWnd, 0h;
jne _Ok;
invoke ExitProcess, 1h;
_Ok:
invoke ShowWindow, hWnd, CmdShow;
invoke UpdateWindow, hWnd;
_GetMessageLoop:
invoke GetMessage, offset message, 0h, 0h, 0h;
cmp eax, 0h;
je _EndMessageLoop;
invoke TranslateMessage, offset message;
invoke DispatchMessage, offset message;
jmp _GetMessageLoop;
_EndMessageLoop:
mov eax, message.wParam
WndProc proc hWindow:HWND, uMsg:UINT, wParam:DWORD, lParam:DWORD
cmp uMsg, WM_DESTROY;
je _WM_DESTROY;
cmp uMsg, WM_LBUTTONDOWN;
je _WM_LBUTTONDOWN;
invoke DefWindowProc, hWindow, uMsg, wParam, lParam;
jmp _EndWndProc;
_WM_LBUTTONDOWN:
invoke MessageBoxA, hWindow, offset MsgBoxTxt, offset WndTitleName, MB_OK or MB_ICONINFORMATION
jmp _EndWndProc;
_WM_DESTROY:
invoke PostQuitMessage, 0h;
_EndWndProc:
Ret
WndProc EndP
end Entry;