;Reads a string of at most al characters to di until a return and prints a newline. readln: ;Store the input length in the stack mov ah, 0 push ax ;Initialise the destination with spaces mov cx, ax mov al, 0x20 rep stosb pop ax push ax sub di, ax ;Initialise the cursor pointer mov bl, 0x1 ;Initialise the last input line pointer mov ah, 0x3 int 0x10 mov byte [.lastln], dh .loop: ;Read a keypress mov ah, 0x0 int 0x16 ;Check for return cmp al, 0xd je .return ;Check for backspace cmp al, 0x8 je .backspace ;Check for input end pop dx push dx cmp bl, dl je .loop ;Check for space cmp al, 0x20 je .space ;Check for erase cmp al, 0x9 je .erase ;Check for non-printing characters cmp al, 0x1f jle .loop cmp al, 0x7f je .loop .char: ;Store the character stosb ;Print the character mov ah, 0xe int 0x10 ;Move the cursor pointer inc bl call .checkln jmp .loop .erase: ;Replace the cursor position with a space mov al, 0x20 jmp .char .space: call .nextchar jmp .loop .backspace: ;Check for the input beginning cmp bl, 0x1 je .loop call .prevchar jmp .loop .return: ;Go to the end of the input mov bh, 0x0 sub di, bx pop ax add di, ax .findtrailing: ;Check for a trailing space cmp byte [di], 0x20 je .deltrailing jmp .done .deltrailing: ;Delete a trailing space mov al, 0x0 stosb sub di, 0x2 jmp .findtrailing .done: ;Move the cursor to the last line of input mov ah, 0x2 mov dh, [.lastln] int 0x10 ;Print a newline call newline ret .lastln: db 0x0 .nextchar: ;Get the cursor position mov ah, 0x3 int 0x10 ;Move from the end of a line to the beginning of the next one cmp dl, [cpl] je .nextln ;Move forward within a line inc dl mov ah, 0x2 int 0x10 inc di inc bl ret .nextln: mov ah, 0x2 inc dh mov dl, 0x1 int 0x10 inc di inc bl ;Go to the last input line check call .checkln ret .prevchar: ;Get the cursor position mov ah, 0x3 int 0x10 ;Move from the beginning of a line to the end of the previous one cmp dl, 0x1 je .prevln ;Move backward within a line dec dl mov ah, 0x2 int 0x10 dec di dec bl ret .prevln: mov ah, 0x2 dec dh mov dl, [cpl] int 0x10 dec di dec bl ret .checkln: ;Get the cursor position mov ah, 0x3 int 0x10 ;Check if the current line is the last one of the input cmp dh, [.lastln] jg .markln ret .markln: ;Mark the current line as the last one of the input mov byte [.lastln], dh ret