; Listing5-1.asm
;
; A program that demonstrates simple multithreading.

            option     casemap:none
            option     prologue:none
            include    aoalib.inc   ;AoA library + constants
            includelib aoalib.lib   ;Link in aoalib library
            include    c:\masm32\include64\win64.inc
            include    c:\masm32\include64\kernel32.inc
            includelib c:\masm32\lib64\kernel32.lib  
            
            .const

; Program title:

            align   word
ttlStr      byte    "Listing 5-1", 0
strToPrint  byte    "Hello, Thread!", nl, 0

            .data
            
globalData  qword   0
threadID    qword   0
            .code

; Here is the thread that will briefly run:

threadProc  proc    public
            push    rbp
            mov     rbp, rsp
            sub     rsp, 64
            
            mov     globalData, rcx
            
; Generally, it is a really bad idea to call
; procedures like "print" from a thread as
; the call could interfere with other threads.
; The main program uses a call to "sleep" in
; order to avoid problems (not a good
; solution, in general).

            mov     rdx, rcx
            call    print
            byte    "Thread started w/parm:%s", nl, 0

; Terminate the thread:

            xor     rax, rax        ;Return result
            leave
            ret
threadProc  endp

        
; Here is the main assembly language function.

            
            public  asmMain
asmMain     proc
            
            push    rbp
            mov     rbp, rsp
            sub     rsp, 64		;Locals and shadow storage
            mov     [rbp-8], rbx

            call    print
            byte    "Creating thread:", nl, 0
            
; Start threadProc running:

            xor     rcx, rcx        ;No security attributes
            xor     rdx, rdx        ;Default stack size
            lea     r8, threadProc  ;Address of thread code
            lea     r9, strToPrint
            xor     rax, rax        ;Default thread flags
            mov     [rsp+32], rax   ;Must pass on stack.
            lea     rax, threadID
            mov     [rsp+40], rax
            call    CreateThread
            
; Give the thread 2 seconds to do its thing and terminate
; before we continue with the main program. This is
; a terrible hack, but works fine for this demo.

            mov     rcx, 2000       ;Delay two seconds
            call    Sleep

; If the thread stored the pointer to the string in
; globalData, print the string.
            
            mov     rdx, globalData
            or      rdx, rdx
            jz      badThread
            call    print
            byte    "Data set by thread: %s", nl, 0
            jmp     allDone
            
badThread:  call    print
            byte    "Thread did not execute properly", nl, 0

allDone:    mov     rbx, [rbp-8]
            leave
            ret     ;Returns to caller
        
asmMain     endp
            end