You can write push '/bin' in NASM to get the bytes into memory in that order. (Padded with 4 bytes of zeros, for a total width of qword; dword pushes are impossible in 64-bit mode.) No need to mess around with manually encoding ASCII characters; unlike some assemblers NASM doesn't suck at multi-character literals and can make your life easier.
You could use use mov dword [rsp+4], '//ls' to store the high half. (Or make it a qword store to write another 4 bytes of zeroes past that, with a mov r/m64, sign_extended_imm32.) Or just zero-terminate it with an earlier push before doing mov rsi, '/bin//ls' / push rsi if you want to store exactly 8 bytes.
Or mov eax, '//ls' ; shr eax, 8 to get EAX="/ls\0" in a register ready to store to make an 8-byte 0-terminated string.
Or use the same trick of shifting out a byte after mov r64, imm64 (like in @prl's answer) instead of separate push / mov. Or NOT your literal data so you do mov rax, imm64 / not rax / push rax, producing zeros in your register without zeros in the machine code. For example:
mov rsi, ~`/bin/ls\0` ; mov rsi, 0xff8c93d091969dd0
not rsi
push rsi ; RSP points to "/bin/ls", 0
If you want to leave the trailing byte implicit, instead of an explicit \0, you can write mov rsi, ~'/bin/ls' which assembles to the same mov rsi, 0xff8c93d091969dd0. Backticks in NASM syntax process C-style escape sequences, unlike single or double quotes. I'd recommend using \0 to remind yourself why you're going to the trouble of using this NOT, and the ~ bitwise-negation assemble-time operator. (In NASM, multi-character literals work as integer constants.)
I believe that to set up the first one, it suffices doing
push 0x736c2f2f ;sl//
push 0x6e69622f ;nib/
mov rdi, rsp
No, push 0x736c2f2f is an 8-byte push, of that value sign-extended to 64-bit. So you've pushed '/bin\0\0\0\0//ls\0\0\0\0'.
Probably you copied that from 32-bit code where push 0x736c2f2f is a 4-byte push, but 64-bit code is different.
x86-64 can't encode a 4-byte push, only 2 or 8 byte operand-size. The standard technique is to push 8 bytes at a time:
mov rdi, '/bin//ls' ; 10-byte mov r64, imm64
push rdi
mov rdi, rsp
If you have an odd number of 4-byte chunks, the first one can be push imm32, then use 8-byte pairs. If it's not a multiple of 4, and you can't pad with redundant characters like /, mov dword [mem], imm32 that partially overlaps might help, or put a value in a register and shift to introduce a zero byte.
See
push imm32still pushes 8 bytes so the string won't be correct, it will be/bin<0><0><0><0>//lspushinstruction with an 8 byte immediate. You have to move into a register and then push.0bytes (i.e. shellcode)? Then it's trivial and you should just put the strings in memory with their terminating0bytes, and use RIP-relative LEA to get pointers to them. Does it even have to be position-independent? If not, the arrays of pointers can be static as well instead of writing instructions to get addresses and store them to the stack. i.e. you can basically just use compiler output. Why would you waste your time pushing strings if you aren't aiming for code-injection (shellcode)?