I want to put into the buffer the first command-line argument which has length 4. I can get each char of it by :
.code64
.global _start
.bss
.lcomm mybuf , 4
.text
_start:
mov 16(%rsp) , %rsi # argv[1]
movzx (%rsi) , %ebx # first char of argv[1]
movzx 1(%rsi) , %ebx # second char of argv[1]
movzx 2(%rsi) , %ebx # third char of argv[1]
movzx 3(%rsi) , %ebx # fourth char of argv[1]
xor %rax , %rax
inc %rax
int $0x80
But how to put the whole string with length 4 into my buffer? My system is x64-Linux with GAS.
You don't have to copy the contents of the string itself into a data buffer. Save the value of 16(%rsp)
in a QWORD sized variable and use it with syscalls all you want. In C terms, that would be the difference between
char lcomm[4];
strcpy(lcomm, argv[1]);
open(lcomm, ...);
and
char *plcomm;
plcomm = argv[1];
open(plcomm, ...);
The second one works just as well.
Also, your buffer has a fixed size of 4 bytes. If the command line argument is longer than that, your code will overflow the buffer, and potentially crash.
That said, if you're serious about learning assembly, you should eventually figure out how to write a strcpy
-like loop. :)
EDIT with some assembly code. Last time I checked, the file name goes into the syscall as RDI, not RSI:
mov 16(%rsp), %rdi # File name
mov $0, %rsi # Flags: O_RDONLY, but substitute your own
mov $0, %rdx # Mode: doesn't matter if the file exists
mov $2, %rax # Syscall number for open
syscall
# %rax is the file handle now
For future reference, the x86_64 syscall convention is:
syscall
instructionThe reference of syscalls is here.