How to compile this code in Assembly on Windows?

4

I was seeing a creation of a basic little window in Assembly that displays a message, I already installed the NASM compiler but the 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;
    
asked by anonymous 28.04.2015 / 23:19

1 answer

3

To compile this code, you must use the MASM compiler , do not NASM , are assemblers distinct.

For your code to run, make the following changes:

  • Under the .model directive, use the option casemap directive, option casemap can be ALL , NONE or NOTPUBLIC , the latter being the default. Using option casemap:none , the MASM preserves the identifiers box. Using option casemap:all , MASM passes all identifiers to uppercase, for example, both msgboxtxt and MsgBoxTxt are transformed into MSGBOXTXT ). The goal is to use NONE so that the identifiers box is preserved, then under the .model directive do:

    .386
    .MODEL FLAT, STDCALL
    option casemap:none
    
  • In order to avoid fatal error A1000: can not open file , put the full path of the files .inc and .lib . Change:

    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 Ctrl S file, and in the top menu click Project Build All , then run the program by clicking Run Program .

    Result:

  • Codecanbeshortenedbyusing INVOKE to call a function instead of putting the function arguments in the stack and call 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;
    
        
    29.04.2015 / 01:51