; ===========================================================================
; FILE    : ILP.asm
; SUBJECT : Program that illustrates some ideas of instruction level parallelism.
; AUTHOR  : Peter Chapin <peter.chapin@vermontstate.edu>
;
; To assemble this program using the Open Watcom assembler use the following commands:
;
;   > wasm ILP.asm
;   > wlink sys nt debug watcom file ILP.obj
;
;===========================================================================

        .586
        .MODEL FLAT
        
        ; Win32 API functions.
        EXTERN   _GetStdHandle@4:PROC
        EXTERN   _WriteConsoleA@20:PROC

        GLOBAL   _WinMain@16:PROC
        
        ; Symbolic names. These special values are meaningful to GetStdHandle.
GET_STDINPUT    EQU    -10
GET_STDOUTPUT   EQU    -11
GET_STDERROR    EQU    -12
CR              EQU     13
LF              EQU     10

        .DATA
stdout  DD      0
Message DB      "Hello, World!", CR, LF
Written DD      15

        
        .CODE

nothing_good_   PROC
        mov     eax, 0
        mov     ebx, 0
        mov     edx, 0
        
        mov     ecx, 10

outer_loop:
        push    ecx
        mov     ecx, 2000000000

        ; The steps below show one possible ordering of execution on a 2-issue machine.
inner_loop:
        inc     eax      ; Step 1
        add     ebx, eax ; Step 2
        add     ebx, ebx ; Step 3
        add     edx, eax ; Step 2
        add     ebx, edx ; Step 4
        add     eax, edx ; Step 3

        ; Interestingly, using the 'loop' instruction is actually slower!
        ; loop    inner_loop
        dec     ecx      ; Step 4
        jne     inner_loop
        
        pop     ecx
        dec     ecx
        jne     outer_loop
        ret
nothing_good_   ENDP

        
_WinMain@16     PROC
        ; Get the handle to the screen buffer.
        push    GET_STDOUTPUT
        call    _GetStdHandle@4
        mov     stdout, eax

        call    nothing_good_

        ; Display a friendly message.
        push    0
        push    OFFSET Written
        push    Written
        push    OFFSET Message
        push    stdout
        call    _WriteConsoleA@20
        ret
_WinMain@16     ENDP

        END _WinMain@16
