Hello World in ancient Microsoft Assembly

org 100h   
;  Defines this number as the "origin", the starting point when resolving address pointers.

mov dx,msg ;  Look for a "msg" address pointer in the code and load its address into dx
mov ah,9   ;  Load a 9 (stdout display command) into ah
int 21h    ;  Interrupt the processor with a SW interrupt
mov ah,4Ch ;  Load a 4C (exit command) into ah
int 21h    ;  Interrupt the processor with a SW interrupt

msg db 'Hello, world!',0Dh,0Ah,'$'   
;  Define byte(s) for the msg address pointer, include LF/CR, then terminate with a "$"


Hello World in modern Microsoft Assembly

This code was copied from https://stackoverflow.com /questions/4568306/outputting-hello-world-in-masm-using-win32-functions

Those first two commands — .386 and .model flat, stdcall — means that all code, data and stack is in a single 32-bit segment and all addresses are 32-bit relocatable offsets (relative addresses) with a range of up to 4GB.
Addresses and pointers passed to system services are always going to be 32-bit near addresses and pointers. This means Windows manages any address fixups, loading and running the program, and the programmer works through the API (Applications Programming Interface) rather than through interrupts.
Also note, data strings are terminated with a binary zero, not that old "$" character.

.model flat, stdcall
option casemap: none

include windows.inc
include user32.inc
include kernel32.inc
includelib user32.lib
includelib kernel32.lib

    szCaption   db  'Hello', 0
    szText      db  'Hello, World!', 0

            invoke MessageBox, NULL, offset szText, offset szCaption, MB_OK
            invoke ExitProcess, NULL        
    end start

** End of page