<p>I have some code which is supposed to display a short message.  Here's the pertinent code:</p>

<pre><code>DATA    SEGMENT 'DATA'
MSG DB  0AH, 0DH, 'Hello, Adam', '$'
CHAR    DB  00H
DATA ENDS

CODE    SEGMENT 'CODE'
PRINT_MSG:
    MOV AH, 09H ;Command to print string of characters
    MOV DX, OFFSET MSG  ;Mov address of message into DX
    INT 21H     ;DOS Interrupt
    JMP WAITING ;Loop back to waiting state
CODE ENDS
</code></pre>

<p>And the output is:</p>

<pre><code>E:\ece323\software\lab2&gt;MAIN.EXE
?F ^?¶ ? N?   ?               -!-

Hello, Adam-
</code></pre>

<p>What is going on here?</p>

My guess is that your DS does not point to your data-segment.
Int21 Function 0x09 takes the string from DS:DX.
Remember that DX is only a 16 bit register. To access data outside the 16 bit range you have to use segment registers. These are called DS and ES for data, CS for code and SS for the stack (there are FS and GS on i386 as well).
The exact address you load from is given by 16 * segment_register + offset_register. Int21 cannot guess where your DS is, so you have to load it prior to call the interrupt.
I guess you have never initialized your DS register, so it most likely points to the code, not the data-segment.
Try to replace your
```
```
MOV DX, offset MSG
```
```
by:
```
```
LDS DX, MSG  ; Check that, it's been ages since I've written 16 bit code.
```
```
Unfortunatley it's been years since I've last played with 16 bit assembler, so I can't check it, but LDS should do the trick.
You may also load DS indirectly at your program startup by something like this:
```
```
MOV AX, SEG DATA  ; check that - can be SEGMENT or so as well.
  MOV DS, AX
```
```