INT 21h AH=0Ah reads a line. DOS echoes what is typed, lets the user correct it with Backspace, and returns when Enter is pressed; the program gets the finished line and never sees the editing. The buffer starts with a small header the program prepares:

OffsetSet byHolds
0the programthe buffer size in characters, the final CR included: at most size − 1 can be typed
1DOShow many characters were typed, the CR not counted
2 …DOSthe characters, followed by 0Dh
prints the echoed "hello", then on the next line: 5 hello
MOV SI, OFFSET KEYS1
CALL STUFF1 ; "hello" and Enter wait in the BIOS buffer
MOV DX, OFFSET BUF1
MOV AH, 0Ah ; DOS: read a line into the buffer at DS:DX
INT 21h ; echoes "hello", then a CR only
MOV DX, OFFSET CRLF1
MOV AH, 09h ; DOS: print the string at DS:DX
INT 21h
MOV BL, BUF1[1] ; the count: 5
XOR BH, BH
MOV BYTE PTR BUF1[BX+2], "$" ; over the 0Dh, for 09h
MOV DL, BL
ADD DL, "0"
MOV AH, 02h ; DOS: print the character in DL
INT 21h
MOV DL, " "
MOV AH, 02h ; DOS: print the character in DL
INT 21h
MOV DX, OFFSET BUF1+2
MOV AH, 09h ; DOS: print the string at DS:DX
INT 21h
KEYS1 DW 2368h, 1265h, 266Ch, 266Ch, 186Fh, 1C0Dh, 0 ; h e l l o Enter
BUF1 DB 20, 0, 20 DUP(0) ; room for 19 characters and the CR
CRLF1 DB 13, 10, "$"
STUFF1 PROC NEAR ; "type" the keys at DS:SI: words, 0 ends the list
CLD
ST1:
LODSW ; AH = scan code, AL = ASCII
TEST AX, AX
JZ ST2
MOV CX, AX ; CH = scan code, CL = ASCII
MOV AH, 05h ; BIOS: store a keystroke in the keyboard buffer
INT 16h
JMP ST1
ST2:
RET
STUFF1 ENDP

STUFF1 types the keys first: each word of KEYS1 is a keystroke with the scan code in the high byte and the ASCII code in the low byte, handed to INT 16h AH=05h. After the call the program prints CR LF, because on Enter DOS echoes a carriage return only, and without a line feed the next output would overwrite the line. Then it puts a "$" over the stored 0Dh, whose position byte 1 gives, and prints the text with INT 21h AH=09h.

Editing

Backspace removes the last character from the buffer and from the screen. When the buffer is full DOS beeps and accepts nothing but Backspace and Enter. In MS-DOS the previous contents of the buffer also serve as a template for the function keys: F3 retypes the rest of the last line, F1 one character of it, and Esc throws the current line away; DOSKEY, when loaded, adds a history. DOSBox-X's version knows Backspace only.

Pitfalls

Byte 0 is the size, not a length to fill: BUF DB 20, ?, 20 DUP(?) accepts 19 characters. With a size of 0 the call returns at once. The text is not zero-terminated; use the count, or put a terminator of your own over the 0Dh as the example does. Ctrl+C typed into the line ends the program in the usual way.

With input redirected from a file the service reads one line of the file, skipping the line feed after the CR. In DOSBox-X, reaching the end of the file during this call quits the whole emulator, so a program meant to read redirected input should use INT 21h AH=3Fh instead, which returns 0 bytes at the end of the file.