Here is a better version, it has had a few things done to reduce the instruction count in the typing loop but it probably does not matter as there are API calls in the loop code. Zip file attached.
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
include \masm32\include64\masm64rt.inc
.code
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
msc equ <30> ; milliseconds delay between characters
entry_point proc
invoke type_this,"The time has come, the Walrus said,",msc
invoke type_this,"To talk of many things.",msc
invoke type_this,"Of shoes and ships and sealing-wax,",msc
invoke type_this,"Of cabbages and kings.",msc
invoke type_this,"And why the sea is boiling hot,",msc
invoke type_this,"And whether pigs have wings.",msc
waitkey " "
invoke ExitProcess,0
ret
entry_point endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
type_this proc ptxt:QWORD,msdelay:QWORD
LOCAL .r14 :QWORD
LOCAL .r15 :QWORD
LOCAL pbuf :QWORD
LOCAL buf[8]:BYTE
mov .r14, r14 ; preserve r14 & r15
mov .r15, r15
mov pbuf, ptr$(buf) ; set pointer to "buf"
mov r15, pbuf ; load r15 outside of the loop
mov r14, ptxt ; load text address into r14
sub r14, 1
@@:
add r14, 1
movzx rax, BYTE PTR [r14] ; read each BYTE into AL
test rax, rax ; exit loop on zero terminator
jz bye
mov BYTE PTR [r15], al ; load AL into 1st BYTE of pbuf
invoke StdOut, pbuf ; output single character to console
invoke SleepEx,msdelay,0 ; set delay between characters
jne @B
bye:
invoke StdOut,chr$(13,10) ; append the CRLF at the end of the line
mov r14, .r14 ; restore r14 & r15
mov r15, .r15
ret
type_this endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
end