ldstr loads the address of the string ldstr stack. According to the calling convention used in IL, clean up the stack, i.e. deleting function arguments from it is performed by the called function. WriteLine expects to receive one parameter and removes one value from the stack. You put 2 values on the stack, so at the time of the ret execution, you have one extra thing left on the stack.
At the time of the call of any function on the top of the stack is the return address where ret should return control when the function ends. At the time of execution, ret takes the return address from the top of the stack and navigates to that address. If at the moment of execution of ret there is an extra value in the stack (which you put there and no one took it from there) then ret will not know where to return and the program will crash.