Sulaiman Chang Personal Website
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 :
Copyright © 2004 Sulaiman Chang. All Rights Reserved.