Search code examples
linuxassemblyx86x86-64gnu-assembler

How to get the first command-line argument and put it into static buffer in memory?


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.


Solution

  • 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:

    • Parameters go into %rdi, %rsi, %rdx, %rcx, %r8, and %r9 in that order
    • Syscall # goes into %rax
    • Then perform a syscall instruction
    • The return value is in %rax
    • %rcx and %r11 are clobbered, the rest of the registers are preserved

    The reference of syscalls is here.