Assembly Console "Hello World"



So, you've read our Getting Started Guide, available here, and just can't wait to get your hands on some code to see what assembly's all about? You've come to the right place!

The files (please note, I have put comments in the files to help explain what is happening; the code may not work, although I've tried to make sure it's properly commented PLEASE DOWNLOAD THE ATTACHED FILE, AND DO NOT COPY & PASTE THE SOURCE CODE BELOW):

hw.asm

; semicolon defines a comment in masm
;╒══════════════════════════════════════════════════════════════════════════╕
;│ HW.ASM                   Console Hello World           created: 05/30/09 │
;│                   Generic Win32 Application Template                     │
;╘══════════════════════════════════════════════════════════════════════════╛
                        TITLE Console Hello World ; Title of our application

include windows.inc ; Include our windows.inc include file which has imports from kernel32.dll

.data
;╒══════════════════════════════════════════════════════════════════════════╕
;│                                 D A T A                                  │
;╘══════════════════════════════════════════════════════════════════════════╛
szMessage       BYTE      "Hello World!",13,10 ; Define a BYTE pointing to a string "Hello World!" followed by \r \n for the WriteConsole, we do not need to null terminate the string (,0)

.data?
;╒══════════════════════════════════════════════════════════════════════════╕
;│                  U N I N I T I A L I Z E D    D A T A                    │
;╘══════════════════════════════════════════════════════════════════════════╛

dwWritten       DWORD   ? ; Define an uninitialized DWORD for use in WriteConsole to get the number of bytes written

.code
;╒══════════════════════════════════════════════════════════════════════════╕
;│                        EXECUTION BEGINS HERE ...                         │
;╘══════════════════════════════════════════════════════════════════════════╛
Start:          invoke  GetStdHandle, STD_OUTPUT_HANDLE ; Call GetStdHandle from kernel32.dll to retrieve a handle to the standard console output
                mov     edx, eax ; Copy the returned handle to the DX register (invokes return to the AX register
                invoke WriteFile, edx, ADDR szMessage, sizeof szMessage, ADDR dwWritten, 0 ; Write our text to the console output handle (edx)
                invoke  ExitProcess, eax ; eax == Exit Code
;╒══════════════════════════════════════════════════════════════════════════╕
;│                      EXECUTION TERMIATES HERE ...                        │
;╘══════════════════════════════════════════════════════════════════════════╛
END     Start


windows.inc

.386 ; Defines 32bit code when first (BEFORE MODEL declaration)
.MODEL  FLAT, STDCALL ; Define the FLAT memory model, and STDCALL
;╒══════════════════════════════════════════════════════════════════════════╕
;│ ************************************************************************ │
;│                                                                          │
;│       MICROSOFT WINDOWS 32-BIT API ASSEMBLY LANGUAGE HEADER FILE         │
;│                             by Jacob Janzen                              │
;│                           * minimal includes *                           │
;│ ************************************************************************ │
;╘══════════════════════════════════════════════════════════════════════════╛
option  casemap:none ; Do not force case matching

;╒══════════════════════════════════════════════════════════════════════════╕
;│                     From KERNEL32.LIB and WINBASE.H                      │
;└──────────────────────────────────────────────────────────────────────────┘

includelib \masm32\lib\kernel32.lib ; Include the library kernel32.lib for the linker

STD_OUTPUT_HANDLE       equ     -11d ; Define the STD_OUT_HANDLE value

GetStdHandle            PROTO   :DWORD ; Function prototype for GetStdHandle from kernel32.dll (defined in \masm\include\kernel32.inc - Retrieves a handle to a standard output
WriteFile               PROTO   :DWORD,:DWORD,:DWORD,:DWORD,:DWORD ; Function prototype for WriteFile from kernel32.dll (defined in \masm\include\kernel32.inc - Writes a buffer to a handle

ExitProcess             PROTO   :DWORD ; Function prototype for ExitProcess from kernel32.dll (defined in \masm\include\kernel32.inc - Stops execution of the program

;┌──────────────────────────────────────────────────────────────────────────┐
;│                       END OF THE WINDOWS.INC FILE                        │
;╘══════════════════════════════════════════════════════════════════════════╛


MAKEFILE

# Number sign defines a comment to nmake
PROJECT   = hw # Name of our project
OBJ_CORE  = hw.obj # Object file for our output

ALL: $(PROJECT).exe # Defines the output for the executable

#╒══════════════════════════════════════════════════════════════════════════╕
#│                      Assembler and Linker Options                        │
#└──────────────────────────────────────────────────────────────────────────┘
AssemblerOptions = /nologo /c /coff /Cp # Defines options sent to the assembler (ml.exe from Microsoft)
LinkerOptions = /SUBSYSTEM:CONSOLE /LIBPATH:J:\masm32\lib # Defines linker options sent to the linker (link.exe from Microsoft)

#╒══════════════════════════════════════════════════════════════════════════╕
#│                Inference Rule for Updating Object Files                  │
#└──────────────────────────────────────────────────────────────────────────┘
.asm.obj: # Defines and executes the assembler (ml.exe)
        J:\DEV\BIN\ML $(AssemblerOptions) $<

#╒══════════════════════════════════════════════════════════════════════════╕
#│                        Build Rule for Executable                         │
#└──────────────────────────────────────────────────────────────────────────┘
$(PROJECT).exe: $(OBJ_CORE) $(OBJ_MORE) # Defines and links the assembled obj file to the linker (link.exe)
        J:\DEV\BIN\LINK $(LinkerOptions) @<


make.bat

ml /c /coff /cp hw.asm  echo Assemble the file (ml.exe from Microsoft)
link /SUBSYSTEM:console /LIBPATH:J:\masm32\lib hw.obj echo Link the generated obj file with the libraries (defined in windows.inc )




Note: MAKEFILE & make.bat do essentially the same thing; except that MAKEFILE uses Microsoft's nmake program to do the work done in make.bat.

Please note that brief comments have been added inline. Currently in the works is code for a full "Windowed" 'Hello World!' program, along with additional comments and language breakdown.

Coming Soon:

Full code walkthrough and break down.

Special thanks to the folks at masm32.com/board for helping me understand my linker issues & support, especially dedndave, hutch--, E^cube & disintx; and I couldn't forget Steve Gibson of GRC.com for the motivation to learn assembler, the excellent tutorials he provided, and his concise and elegant coding style that I completely ripped off - WITH PERMISSION =) (you can contact him if you don't believe me =P)

Please support Steve by purchasing a copy of SpinRite! and view some source code from the master Small is beautiful.

AttachmentSize
console_hw.zip1.6 KB