Appending character to a 'db' variable in masm assembly - windows

I have just started learning assembly, and I am stuck.
I have a character in a WPARAM variable ( can also be DWORD ), and I have to append it to a db string. I have no idea as to how to do it.
Here is my code:
.386
.model flat, stdcall
option casemap: none
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD
include C:\Program Files\masm32\include\windows.inc
include C:\Program Files\masm32\include\kernel32.inc
include C:\Program Files\masm32\include\user32.inc
include C:\Program Files\masm32\include\gdi32.inc
includelib "C:\Program Files\masm32\lib\kernel32.lib"
includelib "C:\Program Files\masm32\lib\user32.lib"
includelib "C:\Program Files\masm32\lib\gdi32.lib"
.data
cn db "Parth",0
an db "Priydarshi Singh",0
char WPARAM 21h
text db "A",0
ps DWORD ?
hin HINSTANCE ?
cmd LPSTR ?
.code
start:
invoke GetModuleHandle, 0
mov hin, eax
invoke GetCommandLine
mov cmd, eax
invoke WinMain, hin, 0, cmd, SW_SHOWDEFAULT
invoke ExitProcess, 0
WinMain proc inst:HINSTANCE, pinst:HINSTANCE, cml:LPSTR, show:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL hwnd:HWND
mov wc.cbSize, sizeof WNDCLASSEX
mov wc.style, CS_VREDRAW or CS_HREDRAW
mov wc.lpfnWndProc, offset WndProc
mov wc.cbClsExtra, 0
mov wc.cbWndExtra, 0
push hin
pop wc.hInstance
mov wc.hbrBackground,COLOR_WINDOW+1
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,OFFSET cn
invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx, addr wc
invoke CreateWindowEx, NULL, addr cn, addr an, WS_OVERLAPPEDWINDOW, 0, 0, 1366, 750, NULL, NULL, inst, NULL
mov hwnd, eax
invoke ShowWindow, hwnd, show
invoke UpdateWindow, hwnd
.WHILE TRUE
invoke GetMessage, addr msg, NULL, 0, 0
.BREAK .IF(!eax)
invoke TranslateMessage, addr msg
invoke DispatchMessage, addr msg
.ENDW
mov eax, msg.wParam
ret
WinMain endp
WndProc proc hwnd:HWND, umsg:UINT, wp:WPARAM, lp:LPARAM
LOCAL hdc:HDC
LOCAL rect:RECT
.IF umsg==WM_DESTROY
invoke PostQuitMessage, 0
.ELSEIF umsg==WM_CHAR
push wp
pop eax
mov char, eax
; I need some code here to append 'char' to 'text'
invoke InvalidateRect, hwnd, NULL, TRUE
.ELSEIF umsg==WM_PAINT
invoke BeginPaint, hwnd, addr ps
mov hdc, eax
invoke TextOut, hdc, 0, 100, addr text, sizeof text
invoke EndPaint, hwnd, addr ps
.ELSE
invoke DefWindowProc, hwnd, umsg, wp, lp
ret
.ENDIF
xor eax, eax
ret
WndProc endp
end start

You can only append to a string if there's space available for additional characters.
You've declared text as text db "A",0, which reserves 2 bytes at text ('A' and 0), so there's no room for additional characters. If you know the maximum length that the string ever will be you can still allocate it statically; for example text db 1024 dup(0) would give you 1024 bytes of space where all bytes have the initial value 0. If you have another variable that keeps track of the current number of characters in the string you can use that to append to the string:
mov edi,text_length
mov [text + edi],al
inc dword ptr text_length
If your string can shrink as well as grow you'll have to make sure to insert a NUL terminator at right place when you "remove" characters from the string.
If you don't know the maximum length of the string in advance, or if the maximum is very large, you can allocate memory dynamically with one of the memory allocation functions provided by Windows, e.g. HeapAlloc. If the string is about to grow beyond the currently allocated size you increase the size of the allocated block with HeapReAlloc (e.g. to twice the size of the previous size).

Related

Assembly MASM32 push and pop

This is a basic win32 program that I found online. So far I get everything, but what I don't get are those two lines:
push hInstance
pop wc.hInstance
Can someone explain to me what they do and if there is another way to do whatever is done by them using another instruction.
I tried to use google and other documentation and they explained very well what the push and pop instructions do, but I can't fit my understanding of them in the context of this program.
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib ; calls to functions in user32.lib and kernel32.lib
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD
.DATA ; initialized data
ClassName db "SimpleWinClass",0 ; the name of our window class
AppName db "Our First Window",0 ; the name of our window
.DATA? ; Uninitialized data
hInstance HINSTANCE ? ; Instance handle of our program
CommandLine LPSTR ?
.CODE ; Here begins our code
start:
invoke GetModuleHandle, NULL ; get the instance handle of our program.
; Under Win32, hmodule==hinstance mov hInstance,eax
mov hInstance,eax
invoke GetCommandLine ; get the command line. You don't have to call this function IF
; your program doesn't process the command line.
mov CommandLine,eax
invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT ; call the main function
invoke ExitProcess, eax ; quit our program. The exit code is returned in eax from WinMain.
WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
LOCAL wc:WNDCLASSEX ; create local variables on stack
LOCAL msg:MSG
LOCAL hwnd:HWND
mov wc.cbSize,SIZEOF WNDCLASSEX ; fill values in members of wc
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInstance
pop wc.hInstance
mov wc.hbrBackground,COLOR_WINDOW+1
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,OFFSET ClassName
invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx, addr wc ; register our window class
invoke CreateWindowEx,NULL,\
ADDR ClassName,\
ADDR AppName,\
WS_OVERLAPPEDWINDOW,\
CW_USEDEFAULT,\
CW_USEDEFAULT,\
CW_USEDEFAULT,\
CW_USEDEFAULT,\
NULL,\
NULL,\
hInst,\
NULL
mov hwnd,eax
invoke ShowWindow, hwnd,CmdShow ; display our window on desktop
invoke UpdateWindow, hwnd ; refresh the client area
.WHILE TRUE ; Enter message loop
invoke GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.ENDW
mov eax,msg.wParam ; return exit code in eax
ret
WinMain endp
WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
.IF uMsg==WM_DESTROY ; if the user closes our window
invoke PostQuitMessage,NULL ; quit our application
.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam ; Default message processing
ret
.ENDIF
xor eax,eax
ret
WndProc endp
end start
It's pushing hInstance onto the stack, and then popping it into the memory location of wc.hInstance.
The programmer could have equivalently written:
mov eax, hInstance
mov wc.hInstance, eax
if they knew they didn't need to preserve EAX.

How to find out the age of a file in ASM?

Greetings to all the geniuses of the digital age
Yesterday's task is still on the agenda: "Use the GetOpenFileName function to select a file. Check if the file is less than 3 days old, execute it. Otherwise, display a dialog asking to delete the file. If the user needs it, wipe." (Note: If a task is told to use a structure, it must be placed in dynamically allocated memory)"
I figured out how to open the file and now everything works like a Swiss watch. But another trouble arose.
How to determine the age of a file?
In general, I first thought to use GetFileTime to extract all data about the file time, then use FileTimeToLocalFileTime to convert it to local time, and using FileTimeToSystemTime - to system time. Then subtract one from the other using sub, and so on as per the task.
Here, the FileTimeToLocalFileTime function requires a FILETIME structure with the following parameters:
DWORD dwLowDateTime;
DWORD dwHighDateTime;
And the FileTimeToSystemTime function requires a SYSTEMTIME structure with the following parameters:
WORD wYear;
WORD wMonth;
WORD wDayOfWeek;
WORD wDay;
WORD wHour;
WORD wMinute;
WORD wSecond;
WORD wMilliseconds;
And how to be then? How to find the age of a file? Is there any alternative way? And if my method works, then what exactly and from what should I take it?
File.inc
include WINDOWS.inc
include user32.inc
include kernel32.inc
include comdlg32.inc
includelib user32.lib
includelib kernel32.lib
includelib comdlg32.lib
.data
Time_title db ' Lab_3',0
format db 'More than 3 days. Delete file?', 0
buf db 255 dup(0)
hFile dd 0
readed dd 0
hmem dd 0
File.asm
.386
.model flat,STDCALL
option casemap :none ;case sensitive
include Third.inc
include RADbg.inc
Mem_Alloc PROC Buf_Size:DWORD
add Buf_Size,4
invoke GlobalAlloc,GMEM_MOVEABLE or GMEM_ZEROINIT,Buf_Size
push eax
invoke GlobalLock,eax
pop [eax]
add eax,4
Mem_Alloc endp
Mem_Free PROC DATA:DWORD
mov eax,DATA
sub eax,4
mov eax,[eax]
push eax
push eax
call GlobalUnlock
call GlobalFree
Mem_Free endp
.code
Begin:
call main
invoke ExitProcess,NULL
main proc
LOCAL ftCreate, ftLocale: FILETIME;
LOCAL stUTC, stLocal: SYSTEMTIME;
invoke Mem_Alloc, 1000h
mov hmem, eax
invoke Mem_Alloc, sizeof OPENFILENAME
mov edi, eax
assume edi: ptr OPENFILENAME
xor eax, eax
mov [edi].lStructSize, sizeof OPENFILENAME
mov [edi].lpstrFile, offset buf
mov [edi].nMaxFile, 255
invoke GetOpenFileName, edi
invoke CreateFile, [edi].lpstrFile, GENERIC_READ,\
FILE_SHARE_READ, NULL, OPEN_EXISTING,\
FILE_ATTRIBUTE_NORMAL, NULL
mov hFile,eax ;
invoke GetFileTime, hFile, addr ftCreate, NULL, NULL
invoke FileTimeToLocalFileTime, addr ftCreate, addr ftLocale
invoke FileTimeToSystemTime, addr ftCreate, addr stUTC
cmp eax, 1
jz l1
invoke ReadFile, hFile, hmem, 1000h, addr readed, 0
invoke MessageBox, 0, hmem, addr Time_title, MB_OKCANCEL
jmp l2
l1:
invoke MessageBox, 0, addr format, addr Time_title, MB_OKCANCEL
cmp eax, IDOK
jne l2
invoke DeleteFile, addr [edi].lpstrFile
l2:
assume edi: dword
invoke CloseHandle, hFile
invoke Mem_Free, hmem
invoke Mem_Free, edi
ret
main endp
end Begin
As FILETIME and RtlTimeToSecondsSince1970 said, You should copy the low- and high-order parts of the file time to a ULARGE_INTEGER structure, perform 64-bit arithmetic on the QuadPart member.
So, subtract the 64-bit value in the ULARGE_INTEGER structure initialized with the file time from the 64-bit value of the ULARGE_INTEGER structure initialized with the current system time.

ReadConsoleInputA throws an Access Violation

I am trying to learn how to use the windows api (instead of just using C calls, irvine32 or masm32) And are running into issues with ReadConsoleInputA (WriteConsoleA works fine).
Also, I don't get why in the PROC prototype for the function, most examples append either an A or a W at the end of ReadConsoleInput/WriteConsole, can you explain why?
.data
consoleOutHandle dd ?
consoleInHandle dd ?
bufferlen dd ?
buffer db ?
bufferSize DWORD ?
message db "Enter a number:", 0
lmessage equ $-message
.code
main PROC
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov consoleOutHandle, eax
invoke ReadConsoleInputA, consoleOutHandle, offset buffer, 128, bufferSize
main endp
end main
It throws: Access violation writing location 0x00000004.
Following the advice from Michael Petch, I have this code now:
.data
consoleOutHandle dd ?
consoleInHandle dd ?
byteswritten dd ?
bufferlen dd ?
buffer db 128 DUP(?)
bufferSize dd ?
message db "Enter a number:", 0
lmessage equ $-message
.code
main PROC
invoke GetStdHandle, STD_INPUT_HANDLE
mov consoleInHandle, eax
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov consoleOutHandle, eax
mov eax, lmessage
invoke WriteConsoleA, consoleOutHandle, offset message, eax, bytesWritten, 0
invoke ReadConsoleInputA, consoleInHandle, offset buffer, 128, offset bufferSize
main endp
end main
And now it throws "triggered a breakpoint".
Disassembly:
invoke ReadConsoleInputA, consoleInHandle, offset buffer, 128, offset bufferSize
00E71066 push offset bufferSize (0E74090h)
00E7106B push 80h
00E71070 push offset buffer (0E74010h)
00E71075 push dword ptr [consoleInHandle (0E74004h)]
00E7107B call _ReadConsoleInputA#16 (0E7100Ah)
--- No source file -------------------------------------------------------------
00E71080 int 3 **---> Breakpoint here**
00E71081 int 3
You asked what the A and W suffix on the end of the WinAPI functions are for. Functions ending with A denote Ansi, and functions ending with W are Wide. Microsoft documents them this way:
Unicode and ANSI Functions
When Microsoft introduced Unicode support to Windows, it eased the transition by providing two parallel sets of APIs, one for ANSI strings and the other for Unicode strings. For example, there are two functions to set the text of a window's title bar:
SetWindowTextA takes an ANSI string.
SetWindowTextW takes a Unicode string.
In the first version of the code
You don't allocate space necessary for buffer. You had:
buffer db ?
That allocated a single byte to the buffer. It should have been:
buffer db 128 DUP(?)
You used STD_OUTPUT_HANDLE instead of STD_INPUT_HANDLE
The last parameter to ReadConsoleInputA is a pointer to a DWORD that will return the number of events read. Changing the variable name bufferSize might make the code more readable. From the ReadConsoleInputA documentation:
BOOL WINAPI ReadConsoleInput(
_In_ HANDLE hConsoleInput,
_Out_ PINPUT_RECORD lpBuffer,
_In_ DWORD nLength,
_Out_ LPDWORD lpNumberOfEventsRead
);
If you are reading just the keyboard you should be using ReadConsoleA as ReadConsoleInputA will process keyboard and mouse events and may prematurely return before your string is read. ReadConsoleA takes one extra parameter and you can set it to NULL:
BOOL WINAPI ReadConsole(
_In_ HANDLE hConsoleInput,
_Out_ LPVOID lpBuffer,
_In_ DWORD nNumberOfCharsToRead,
_Out_ LPDWORD lpNumberOfCharsRead,
_In_opt_ LPVOID pInputControl
);
To exit the program you need to invoke ExitProcess .
In the second version of the code
Your code does:
invoke WriteConsoleA, consoleOutHandle, offset message, eax, bytesWritten, 0
bytesWritten needs to be a pointer because that is an output parameter. From WriteConsoleA documentation:
BOOL WINAPI WriteConsole(
_In_ HANDLE hConsoleOutput,
_In_ const VOID *lpBuffer,
_In_ DWORD nNumberOfCharsToWrite,
_Out_ LPDWORD lpNumberOfCharsWritten,
_Reserved_ LPVOID lpReserved
);
A version of the code that uses ReadConsoleA instead of ReadConsoleInputA based on your second code example could look like:
.data
consoleOutHandle dd ?
consoleInHandle dd ?
bytesWritten dd ?
bufferlen dd ?
buffer db 128 DUP(?)
numEvents dd ?
message db "Enter a number:", 0
lmessage equ $-message
.code
main PROC
invoke GetStdHandle, STD_INPUT_HANDLE
mov consoleInHandle, eax
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov consoleOutHandle, eax
mov eax, lmessage
invoke WriteConsoleA, consoleOutHandle, offset message, eax, offset bytesWritten, 0
invoke ReadConsoleA, consoleInHandle, offset buffer, 128, offset numEvents, 0
invoke ExitProcess, 0
main endp
end main
This code can be cleaned up a bit by using MASM's sizeof operator. The code could be written as:
.data
consoleOutHandle dd ?
consoleInHandle dd ?
buffer db 128 DUP(?)
bytesWritten dd ?
numEvents dd ?
message db "Enter a number:", 0
.code
main PROC
invoke GetStdHandle, STD_INPUT_HANDLE
mov consoleInHandle, eax
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov consoleOutHandle, eax
invoke WriteConsoleA, consoleOutHandle, offset message, sizeof message, offset bytesWritten, 0
invoke ReadConsoleA, consoleInHandle, offset buffer, sizeof buffer, offset numEvents, 0
invoke ExitProcess, 0
main endp
end main

Failed to create a main window using Windows API and x86 assembly

The program compiles fine, but it fails to create the main window. Specifically, CreateWindowEx fails and prints "Failed to create window".
Would anyone happen to know what I'm doing wrong? I'm following Kip Irvine's book on assembly almost exactly, but it seems I'm missing something.
EDIT: I updated the code based on the recommendations. Now the program fails to register the window class, and the specific error is that a "Parameter is incorrect". I looked over the parameters of my WNDCLASSEX struct, and couldn't fine anything wrong.
EDIT2: I removed the "Ex" from WNDCLASS and RegisterClass and the window shows up and works fine now. So I guess it was some kind of weird redefinition or inconsistency of structs and functions in the masm32rt library?
INCLUDE \masm32\include\masm32rt.inc
.data
windowName BYTE "ASM Windows App",0
className BYTE "ASMWin",0
MainWinClass WNDCLASSEX <NULL,CS_HREDRAW + CS_VREDRAW,WinProc,NULL,NULL,NULL,NULL,NULL,COLOR_WINDOW+1,NULL,className,NULL>
windowHandle DWORD ?
hInstance DWORD ?
.code
WinMain PROC
; Get a handle to the current process.
INVOKE GetModuleHandle, NULL
mov hInstance, eax
mov MainWinClass.hInstance, eax
; Check if the handle was received.
.IF eax == 0
pushad
print "Failed to get handle on current process"
popad
call ErrorHandler
jmp ExitProgram
.ENDIF
; Load the program's icon and cursor.
INVOKE LoadIcon, NULL, IDI_APPLICATION
mov MainWinClass.hIcon, eax
INVOKE LoadCursor, NULL, IDC_ARROW
mov MainWinClass.hCursor, eax
; Create the window class.
INVOKE RegisterClassEx, ADDR MainWinClass
; Check if the class was registered.
.IF eax == 0
pushad
print "Failed to register class."
popad
call ErrorHandler
jmp ExitProgram
.ENDIF
; Create the window.
INVOKE CreateWindowEx, 0, ADDR className, ADDR windowName, WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL
; Check if window was created successfully.
.IF eax == 0
pushad
print "Failed to create window"
popad
call ErrorHandler
jmp ExitProgram
.ENDIF
; Save the window handle and use it to show the window.
mov windowHandle, eax
INVOKE ShowWindow, windowHandle, SW_SHOW
INVOKE UpdateWindow, windowHandle
; Message Loop
;MessageLoop:
; INVOKE GetMessage, ADDR msg, NULL, NULL, NULL
; INVOKE DispatchMessage, ADDR msg
; jmp MessageLoop
ExitProgram:
;CALL ReadChar
INVOKE ExitProcess, 0
WinMain ENDP
; Window Procedure
WinProc PROC,
hWnd:DWORD, localMsg:DWORD, wParam:DWORD, lParam:DWORD
mov eax, localMsg
.IF eax == WM_CREATE
;call WriteString
jmp WinProcExit
.ELSEIF eax == WM_CLOSE
;call WriteString
jmp WinProcExit
.ELSE
;call WriteString
INVOKE DefWindowProc, hWnd, localMsg, wParam, lParam
jmp WinProcExit
.ENDIF
WinProcExit:
ret
WinProc ENDP
ErrorHandler PROC
.data
pErrorMsg DWORD ?
messageID DWORD ?
.code
INVOKE GetLastError
mov messageID, eax
; Get the corresponding message string.
INVOKE FormatMessage, FORMAT_MESSAGE_ALLOCATE_BUFFER + \
FORMAT_MESSAGE_FROM_SYSTEM,NULL,messageID,NULL,
ADDR pErrorMsg,NULL,NULL
; Display the error message.
INVOKE MessageBox, NULL, pErrorMsg, NULL,
MB_ICONERROR+MB_OK
; Free the error message string.
INVOKE LocalFree, pErrorMsg
ret
ErrorHandler ENDP
END WinMain
WNDCLASSEX requires WNDCLASSEX.cbSize to be set. The mistake I made was that I assumed it could be NULL.
So I added this piece of code before registering the class:
; Initializing other parameters of the window class.
mov eax, SIZEOF MainWinClass
mov MainWinClass.cbSize, eax
In addition, Kip Irvine's functions cause errors when used along side some functions of the user interface section of the Windows API. I'm not exactly sure why that happens but it could be that some register values are changed around.

x86 assembly - window does not show up yet no compile-time errors

I am trying to create a window in x86 assembly with masm32 using the CreateWindowEx API. I have gotten my code to have no compile-time errors or anything of the sort- it compiles just fine. Yet when I run the exe, nothing happens. I don't see any obvious errors, and I have practically copied the code out of Iczelion's Win32 Tutorial (Part 3 - A Simple Window). What is wrong with it?
Here is my code:
.386
.model flat, stdcall
option casemap :none
WinMain proto :DWORD,:DWORD, :DWORD,:DWORD
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\gdi32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\gdi32.lib
.data
ClassName db "Testwin", 0
AppName db "Testing Window", 0
.data?
hInstance HINSTANCE ?
CommandLine LPSTR ?
.code
start:
push NULL
call GetModuleHandle
mov hInstance,eax
call GetCommandLine
mov CommandLine, eax
push SW_SHOWDEFAULT
push CommandLine
push NULL
push hInstance
call WinMain
push eax
call ExitProcess
WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE, CmdLine:LPSTR,CmdShow:DWORD
; local vars:
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL hwnd:HWND
; defining the window:
mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInst
pop wc.hInstance
mov wc.hbrBackground,COLOR_WINDOW+1
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,OFFSET ClassName
invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx, addr wc
;create the window
invoke CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
hInst,NULL
invoke ShowWindow,hwnd,SW_SHOWNORMAL
WinMain endp
WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
cmp uMsg, WM_DESTROY
jne _next
invoke PostQuitMessage, NULL
_next:
WndProc endp
end start
Where have I gone wrong? I suspect it has something to do with CreateWindowEx, considering it takes 12 parameters, most of which I don't understand.
Thanks in advance.
I believe you have not assigned the window handle returned by CreateWindowEx to the hwnd variable.
So add the following line after invoke CreateWindowEx and before invoke ShowWindow -
mov hwnd, eax
We do not compile anything when using Assebmly! We Assemble and Link.
This is not C or any other high level language, you do not need WinMain.
The biggie, where is your message loop
After your CreateWindowEx and ShowWindow, you need something like this right after that:
.while TRUE
invoke GetMessage,addr msg,NULL,0,0
.break .if !eax
;invoke IsDialogMessage,hModelessDialog,addr msg
;.if !eax
;invoke TranslateAccelerator,hWnd,hAccel,addr msg
;.if !eax
invoke TranslateMessage,addr msg
invoke DispatchMessage,addr msg
;.endif
;.endif
.endw
You are also missing ret at the end of your procs

Resources