The EMPTYCHAR structure in your program fits the DOS.BufferedInput function 0Ah that you say you don't want to use (this time). However it doesn't serve any purpose with the functions you intend to use today.
The READCHAR macro doesn't need an argument at all. The DOS.GetCharacter function 01h will return the ASCII code for the pressed key in the AL
register.
On the other hand the PRINTCHAR macro does require an argument to be of any use. After all the DOS.PrintCharacter function 02h expects to receive an ASCII code in the DL
register.
This is how your macros should be written:
READCHAR MACRO
mov ah, 01h ; DOS.GetCharacter
int 21h ; -> AL
ENDM
PRINTCHAR MACRO TheArg
mov dl, TheArg
mov ah, 02h ; DOS.PrintCharacter
int 21h
ENDM
and how you can use them:
.data
Char DB 0
.code
READCHAR ; -> AL
mov [Char], al ; Only in case you desire to save a copy in memory, else strike this line!
PRINTCHAR al
Specifying the parameter for the PRINTCHAR macro is not limited to just the AL
register. You could also supply an immediate number like in PRINTCHAR 13
(to output carriage return) and PRINTCHAR "-"
(to output a hyphen), or even a memory reference like in PRINTCHAR [Char]
.
Note also that sometimes it could be useful to preserve some register(s) like shown below:
PRINTCHAR MACRO TheArg
push dx
mov dl, TheArg
mov ah, 02h ; DOS.PrintCharacter
int 21h
pop dx
ENDM