Well, Nasm is correct - that's not a valid instruction! Using 16-bit instructions, an effective address contains an (optional) offset, plus an (optional) base register (bx and bp), plus an (optional) index register (si and di). That's it!
Using 32-bit instructions, any GP register can be used as a base register and any but esp can be used as an index register. A "scale" can also be used, such as:
mov al, [ecx + 4 * edx]
In your code, it would "probably" work to do:
mov al, [edx]
... provided that the upper bits of edx are zero - "probably" true, but it might be a good idea to explicitly clear 'em!
More "usual" 16-bit code would use bx, si, or di in this position. (If you use si, the single-byte instruction "lodsb" will load al, and increment si.)
I'd have to look it up, but I think you want 0xE in ah for this interrupt, not 0xA. If my memory is correct (quite possibly not!), 0xA does not advance the cursor, and everything will print in the same position... unless you explicitly advance the cursor after each character.
Get back to us if you have trouble getting it working.
Best,
Frank