|
Tutorial 15 : Multithreading Programming
; +-------------+
; | tut_15a.asm |
; +-------------+
format PE GUI 4.0
entry start
include '%fasminc%\win32a.inc'
; +-----------------------+
; | menu item declaration |
; +-----------------------+
MI_THREAD_CREATE equ 110
MI_EXIT equ 190
WMU_THREAD_FINISH equ WM_USER + 0x100
section '.data' data readable writeable
wTitle db 'Tutorial 15A',0
wClsName db 'TUT15A',0
hWindow dd ?
hInstance dd ?
msg MSG
wc WNDCLASS
hMenu dd ?
tId dd ?
section '.code' code readable executable
start:
; +------------------------------+
; | registering the window class |
; +------------------------------+
invoke GetModuleHandle,NULL
mov [hInstance],eax
mov [wc.hInstance],eax
mov [wc.lpfnWndProc],window_procedure
mov [wc.lpszClassName],wClsName
mov [wc.lpszMenuName],30
mov [wc.hbrBackground],COLOR_WINDOW+1
invoke LoadIcon,NULL,IDI_APPLICATION
mov [wc.hIcon],eax
invoke LoadCursor,NULL,IDC_ARROW
mov [wc.hCursor],eax
invoke RegisterClass,wc
; +--------------------------+
; | creating the main window |
; +--------------------------+
invoke CreateWindowEx,\
WS_EX_CLIENTEDGE,\
wClsName,\
wTitle,\
WS_OVERLAPPEDWINDOW or WS_VISIBLE,\
CW_USEDEFAULT,\
CW_USEDEFAULT,\
300,\
200,\
NULL,\
NULL,\
[hInstance],\
NULL
mov [hWindow],eax
invoke GetMenu,eax
mov [hMenu],eax
; +---------------------------+
; | entering the message loop |
; +---------------------------+
window_message_loop_start:
invoke GetMessage,msg,NULL,0,0
or eax,eax
je window_message_loop_end
invoke TranslateMessage,msg
invoke DispatchMessage,msg
jmp window_message_loop_start
window_message_loop_end:
invoke ExitProcess,0
; +----------------------+
; | the window procedure |
; +----------------------+
proc window_procedure,hWnd,uMsg,wParam,lParam
push ebx esi edi
cmp [uMsg],WM_COMMAND
je wmCOMMAND
cmp [uMsg],WMU_THREAD_FINISH
je wmuTHREAD_FINISH
cmp [uMsg],WM_DESTROY
je wmDESTROY
wmDEFAULT:
invoke DefWindowProc,[hWnd],[uMsg],[wParam],[lParam]
jmp wmBYE
wmuTHREAD_FINISH:
invoke MessageBox,NULL,wTitle,wTitle,MB_OK
jmp wmBYE
wmCOMMAND:
cmp [wParam],0xFFFF and MI_THREAD_CREATE
je wmCOMMAND_MI_THREAD_CREATE
cmp [wParam],0xFFFF and MI_EXIT
je wmCOMMAND_MI_EXIT
jmp wmBYE
wmCOMMAND_MI_THREAD_CREATE:
mov eax,thread_procedure
invoke CreateThread,NULL,0,eax,NULL,NORMAL_PRIORITY_CLASS,tId
invoke CloseHandle,eax
jmp wmBYE
wmCOMMAND_MI_EXIT:
invoke DestroyWindow,[hWnd]
jmp wmBYE
wmDESTROY:
invoke PostQuitMessage,0
wmBYE:
pop edi esi ebx
return
endp
; +------------------+
; | thread procedure |
; +------------------+
proc thread_procedure
mov ecx,0x3FFFFFFF
loopSTART:
add eax,eax
dec ecx
jz loopEND
jmp loopSTART
loopEND:
invoke SendMessage,[hWindow],WMU_THREAD_FINISH,NULL,NULL
return
endp
section '.idata' import data readable writeable
library KERNEL32, 'KERNEL32.DLL',\
USER32, 'USER32.DLL'
import KERNEL32,\
GetModuleHandle, 'GetModuleHandleA',\
ExitProcess, 'ExitProcess'
import USER32,\
RegisterClass, 'RegisterClassA',\
CreateWindowEx, 'CreateWindowExA',\
DefWindowProc, 'DefWindowProcA',\
LoadCursor, 'LoadCursorA',\
LoadIcon, 'LoadIconA',\
GetMenu, 'GetMenu',\
MessageBox, 'MessageBoxA',\
SendMessage, 'SendMessageA',\
GetMessage, 'GetMessageA',\
DestroyWindow, 'DestroyWindow',\
TranslateMessage, 'TranslateMessage',\
DispatchMessage, 'DispatchMessageA',\
PostQuitMessage, 'PostQuitMessage'
section '.rsrc' resource data readable
directory RT_MENU,appMenu
resource appMenu,\
30,LANG_NEUTRAL,menuMain
menu menuMain
menuitem '&Process',0,MFR_POPUP + MFR_END
menuitem '&Create Thread',MI_THREAD_CREATE,0
menuseparator
menuitem 'E&xit',MI_EXIT,MFR_END
Result :
; +-------------+
; | tut_15b.asm |
; +-------------+
format PE GUI 4.0
entry start
include '%fasminc%\win32a.inc'
; +-----------------------+
; | menu item declaration |
; +-----------------------+
MI_CALCULATE_PRIMARY_THREAD equ 110
MI_EXIT equ 190
WMU_CALCULATE_FINISH equ WM_USER + 0x100
section '.data' data readable writeable
wTitle db 'Tutorial 15B',0
wClsName db 'TUT15B',0
hWindow dd ?
hInstance dd ?
msg MSG
wc WNDCLASS
hMenu dd ?
section '.code' code readable executable
start:
; +------------------------------+
; | registering the window class |
; +------------------------------+
invoke GetModuleHandle,NULL
mov [hInstance],eax
mov [wc.hInstance],eax
mov [wc.lpfnWndProc],window_procedure
mov [wc.lpszClassName],wClsName
mov [wc.lpszMenuName],30
mov [wc.hbrBackground],COLOR_WINDOW+1
invoke LoadIcon,NULL,IDI_APPLICATION
mov [wc.hIcon],eax
invoke LoadCursor,NULL,IDC_ARROW
mov [wc.hCursor],eax
invoke RegisterClass,wc
; +--------------------------+
; | creating the main window |
; +--------------------------+
invoke CreateWindowEx,\
WS_EX_CLIENTEDGE,\
wClsName,\
wTitle,\
WS_OVERLAPPEDWINDOW or WS_VISIBLE,\
CW_USEDEFAULT,\
CW_USEDEFAULT,\
300,\
200,\
NULL,\
NULL,\
[hInstance],\
NULL
mov [hWindow],eax
invoke GetMenu,eax
mov [hMenu],eax
; +---------------------------+
; | entering the message loop |
; +---------------------------+
window_message_loop_start:
invoke GetMessage,msg,NULL,0,0
or eax,eax
je window_message_loop_end
invoke TranslateMessage,msg
invoke DispatchMessage,msg
jmp window_message_loop_start
window_message_loop_end:
invoke ExitProcess,0
; +----------------------+
; | the window procedure |
; +----------------------+
proc window_procedure,hWnd,uMsg,wParam,lParam
push ebx esi edi
cmp [uMsg],WM_COMMAND
je wmCOMMAND
cmp [uMsg],WMU_CALCULATE_FINISH
je wmuCALCULATE_FINISH
cmp [uMsg],WM_DESTROY
je wmDESTROY
wmDEFAULT:
invoke DefWindowProc,[hWnd],[uMsg],[wParam],[lParam]
jmp wmBYE
wmuCALCULATE_FINISH:
invoke MessageBox,NULL,wTitle,wTitle,MB_OK
jmp wmBYE
wmCOMMAND:
cmp [wParam],0xFFFF and MI_CALCULATE_PRIMARY_THREAD
je wmCOMMAND_MI_CALCULATE_PRIMARY_THREAD
cmp [wParam],0xFFFF and MI_EXIT
je wmCOMMAND_MI_EXIT
jmp wmBYE
wmCOMMAND_MI_CALCULATE_PRIMARY_THREAD:
call calculate_procedure
jmp wmBYE
wmCOMMAND_MI_EXIT:
invoke DestroyWindow,[hWnd]
jmp wmBYE
wmDESTROY:
invoke PostQuitMessage,0
wmBYE:
pop edi esi ebx
return
endp
; +------------------+
; | thread procedure |
; +------------------+
proc calculate_procedure
mov ecx,0x3FFFFFFF
loopSTART:
add eax,eax
dec ecx
jz loopEND
jmp loopSTART
loopEND:
invoke SendMessage,[hWindow],WMU_CALCULATE_FINISH,NULL,NULL
return
endp
section '.idata' import data readable writeable
library KERNEL32, 'KERNEL32.DLL',\
USER32, 'USER32.DLL'
import KERNEL32,\
GetModuleHandle, 'GetModuleHandleA',\
CreateThread, 'CreateThread',\
GetExitCodeProcess, 'GetExitCodeProcess',\
GetStartupInfo, 'GetStartupInfoA',\
CreateProcess, 'CreateProcessA',\
TerminateProcess, 'TerminateProcess',\
CloseHandle, 'CloseHandle',\
ExitProcess, 'ExitProcess'
import USER32,\
RegisterClass, 'RegisterClassA',\
CreateWindowEx, 'CreateWindowExA',\
DefWindowProc, 'DefWindowProcA',\
LoadCursor, 'LoadCursorA',\
LoadIcon, 'LoadIconA',\
GetMenu, 'GetMenu',\
EnableMenuItem, 'EnableMenuItem',\
MessageBox, 'MessageBoxA',\
SendMessage, 'SendMessageA',\
GetMessage, 'GetMessageA',\
DestroyWindow, 'DestroyWindow',\
TranslateMessage, 'TranslateMessage',\
DispatchMessage, 'DispatchMessageA',\
PostQuitMessage, 'PostQuitMessage'
section '.rsrc' resource data readable
directory RT_MENU,appMenu
resource appMenu,\
30,LANG_NEUTRAL,menuMain
menu menuMain
menuitem '&Process',0,MFR_POPUP + MFR_END
menuitem '&Calculate in Primary Thread',MI_CALCULATE_PRIMARY_THREAD,0
menuseparator
menuitem 'E&xit',MI_EXIT,MFR_END
Result :
|