; This is a very simple 32 bit assembly program
; that uses the Win32 API to display hello world on the
; console.

TITLE Hello World in Win32 ASM       (helloworld.asm)

.386
.MODEL flat, stdcall
.STACK 4096

; ----------------------------------------------------------------------------
; These are prototypes for functions that we use
; from the Microsoft library Kernel32.lib.
; ----------------------------------------------------------------------------

; Win32 Console handle
STD_OUTPUT_HANDLE EQU -11		        ; predefined Win API constant (magic)

GetStdHandle PROTO,                 ; get standard handle
	nStdHandle:DWORD  		             ; type of console handle

WriteConsole EQU <WriteConsoleA>    ; alias

WriteConsole PROTO,		              ; write a buffer to the console
	handle:DWORD,		                   ; output handle
	lpBuffer:PTR BYTE,		             ; pointer to buffer
	nNumberOfBytesToWrite:DWORD, 	     ; size of buffer
	lpNumberOfBytesWritten:PTR DWORD,  ; num bytes written
	lpReserved:DWORD		               ; (not used)

ExitProcess PROTO,                  ; exit program
	dwExitCode:DWORD		               ; return code
	
; ----------------------------------------------------------------------------




; ----------------------------------------------------------------------------
; global data
; ----------------------------------------------------------------------------

.data
consoleOutHandle dd ?     	      ; DWORD: handle to standard output device
bytesWritten     dd ?     	      ; DWORD: number of bytes written
message db "Hello World",13,10,0  ; BYTE: string, with \r, \n, \0 at the end

; ----------------------------------------------------------------------------




.code

; ----------------------------------------------------------------------------
procStrLength PROC USES edi,
	ptrString:PTR BYTE	; pointer to string
;
; walk the null terminated string at ptrString
; incrementing eax. The value in eax is the string length 
;
; parameters: ptrString - a string pointer
; returns: EAX = length of string prtString
; ----------------------------------------------------------------------------
	mov edi,ptrString
	mov eax,0     	            ; character count
L1:                             ; loop
	cmp byte ptr [edi],0	     ; found the null end of string?
	je  L2	                     ; yes: jump to L2 and return
	inc edi	                     ; no: increment to next byte
	inc eax	                     ; increment counter
	jmp L1                       ; next iteration of loop
L2: ret                         ; jump here to return
procStrLength ENDP
; ----------------------------------------------------------------------------




; ----------------------------------------------------------------------------
procWriteString proc
;
; Writes a null-terminated string pointed to by EDX to standard
; output using windows calls.
; ----------------------------------------------------------------------------
	pushad

	INVOKE procStrLength,edx   	   ; return length of string in EAX
	cld                            ; clear the direction flag
	                               ; must do this before WriteConsole

	INVOKE WriteConsole,
	    consoleOutHandle,     	   ; console output handle
	    edx,	                   ; points to string
	    eax,	                   ; string length
	    offset bytesWritten,  	   ; returns number of bytes written
	    0

	popad
	ret
procWriteString endp
; ----------------------------------------------------------------------------




; ----------------------------------------------------------------------------
main PROC
;
; Main procedure. Just initializes stdout, dumps the string, and exits.
; ----------------------------------------------------------------------------
	INVOKE GetStdHandle, STD_OUTPUT_HANDLE ; use Win32 to put 
	                                        ; stdout handle in EAX
	                                        
	mov [consoleOutHandle],eax             ; Put the address of the handle in 
	                                        ; our variable

	mov edx,offset message                 ; load the address of the message 
	                                        ; into edx for procWriteString
	
	INVOKE procWriteString                 ; invoke our write string method. 
	                                        ; It'll check EDX

	INVOKE ExitProcess,0                   ; Windows method to quit

main ENDP
; ----------------------------------------------------------------------------

END main
