What is MASM?
MASM is a Macro Assembler from Microsoft (ml.exe). It has been around since the early 80's. It is a multi pass x86 assembler that produces COFF exes.

Where can I get it?
Microsoft does not sell MASM anymore, but ml does come with Visual Studio, Windows Driver Development Kit, Windows Software Development Kit. Along with ml, you will also need a linker and a few other files. I will not discuss getting the files from MS, since you will have to get and convert all the C header files and make sure you have the proper dlls. Instead I will discuss MASM32 - MASM32 contains:
cvtres
lib
link
link16 - 16bit linker
ml
ml614 - 16bit vertsion
rc

and a few more binaries. It also comes with an editor to edit your asm files, tons of examples with source, C header files converted for MASM, lib files, and the MASM32 library wich contains MANY usefull functions and source.

Why MASM? When I chose Assembly MANY years ago, MASM had a large user base (read - support), tons of sample code and a prebuilt library of functions so I did not have to reinvent the wheel. Users of other Assemblers will say MASM is a HLL. Why, because of macros, invoke, if/while loops? BLAH, many of those Assemblers now have invoke and if/while loops.

There are 2 ways you can "call" functions - with invoke and with the mnuemonic call. Invoke is just a macro that makes sure the correct number of parameters are passed to the stack and also some type checking.

At runtime, the address of the Hello buffer is not known, it's address is somewhere on the stack... Behind the scenes, ADDR will do

lea eax, Hello

so this:

invoke MessageBox, NULL, addr Hello, NULL, NULL

will get assembled as:

push NULL
push NULL
lea eax, Hello
push eax
push NULL
call MessageBox

ADDR uses eax to get addresses, remember that... You cannot use eax BEOFRE ADDR or you will get the error - A2133 register value overwritten by INVOKE

mov eax, 0
invoke MessageBox, eax, addr Hello, NULL, NULL

is incorrect as eax will be overwritten by ADDR

OFFSET -

invoke MessageBox, NULL, offset lpszHello, NULL, NULL

The address of lpszHello IS known at link time since it is in the .data? section. OFFSET returns its address offset from the base starting address of your exe.

You will see code using ADDR all the time. I am against that, you should be able to look at code and know if it is a local or global variable. I only use ADDR for local variables. OFFSET for anything in the .data, .data? sections and to get the address of a proc.