Dos will load your program at 100h... because that's what it does with a .com file (determined by the lack of an "MZ" signature - you could name it ".exe" and it would still be a .com file!). The "org 100h" merely tells Nasm that this is true, so it can calculate the address of "msg" correctly. Try it without the "org 100h". Then try:
mov dx, msg + 100h
You could try "org 80h" and "msg + 80h", too. That's what "org" does for us...
When we type "hello", dos finds a free segment and builds a "Program Segment Prefix" of 256 (100h) bytes. The first half of this "PSP" contains some information, some of which is "interesting"... the segment where the environment variables can be found, for example. The upper half serves as a "buffer" - if we type "hello one two three", the "one two three" will appear there, and it's used a a default "Data Transfer Area" for "directory" functions "findfirst" and "findnext".
Our program is loaded after that. The chosen segment is loaded into the segment registers, a word (two bytes) zero is pushed on the stack, and execution jumps to cs:100h. We're on!
I showed you to exit via int 21h with 4Ch in ah. Another way to do it would be with int 20h. Another way to do it is "ret". "ret" takes its return address (to return to) off the stack. Dos pushed a zero there, remember, so we "ret" to... the beginning of the PSP. The first two bytes of the PSP are CDh, 20H - int 20h - so we're still using int 20h to exit, not really "returning" to dos...
Dos is fun to play with, and can be educational, but there isn't a lot of "commercial potential" to it, these days. You probably want to get on to 32-bit code fairly soon...
Dr. Carter's "driver.c" just calls "asm_main" (a label declared "global" in our asm code so the linker can find it). "asm_io.asm" will have to be assembled first into "asm_io.obj". You'll have to define "OBJ_TYPE" on Nasm's command line, I think... It contains the functions "print_int", "read_int", etc. The file "asm_io.inc" which has to be "%include"ed in our code, takes care of declaring "print_int" etc. as "extern", so we can just go ahead and use them freely without having to worry about it. It also provides a few useful macros like "dump_regs"...
Once you've got DJGPP installed, it should go pretty smoothly. (one can hope...)
Best,
Frank