Problems with Accessing Command Line Arguments in Linux from X86 Asm

Trouble getting command line arguments in x86 assembly

There are two issues with your code.

First, you use lea 8(%rsi), %rdi to retrieve the second argument. Note that rsi points to an array of pointers to command line arguments, so to retrieve the pointer to the second argument, you have to dereference 8(%rsi) using something like mov 8(%rsi), %rdi.

Second, you forgot the dollar sign in front of 0 in cmp $0, %rax. This causes an absolute address mode for address 0 to be selected, effectively dereferencing a null pointer. To fix this, add the missing dollar sign to select an immediate addressing mode.

When I fix both issues, your code as far as you posted it seems to work just fine.

Getting command line parameters from an assembly program

With the help from @Michael, I was able to track down the problem.

Using %ebp as argv as @Michael suggested (he used %eax though). Another problem was that I needed to compare the value of (%ebp) with 0 (the null terminator) and end the program at that point.

Code:

    movl 8(%esp), %ebp  /* Get argv.  */

pr_arg:
cmpl $0, (%ebp)
je endit

pushl %ecx
pushl (%ebp)
pushl $output2
call printf
addl $8, %esp /* remove output2 and current argument. */
addl $4, %ebp

popl %ecx
loop pr_arg

ret

Linux getting terminal arguments from _start not working with inline assembly in C

This looks correct for a minimal _start: but you put it inside a non-naked C function. Compiler-generated code will run, e.g. push %rbp / mov %rsp, %rbp, before execution enters before the asm statement. To see this, look at gcc -S output, or single-step in a debugger such as GDB.

Put your asm statement at global scope (like in How Get arguments value using inline assembly in C without Glibc?) or use __attribute__((naked)) on your _start(). Note that _start isn't really a function

As a rule, never use GNU C Basic asm statements in a non-naked function. Although you might get this to work with -O3 because that would imply -fomit-frame-pointer so the stack would still be pointing at argc and argv when your code ran.

A dynamically linked executable on GNU/Linux will run libc startup code from dynamic linker hooks, so you actually can use printf from _start without manually calling those init functions. Unlike if this was statically linked.

However, your main tries to return to your _start, but you don't show _start calling exit. You should call exit instead of making an _exit system call directly, to make sure stdio buffers get flushed even if output is redirected to a file (making stdout full buffered). Falling off the end of _start would be bad, crashing or getting into an infinite loop depending on what execution falls in to.

Linux 64 command line parameters in Assembly

It looks like section 3.4 Process Initialization, and specifically figure 3.9, in the already mentioned System V AMD64 ABI describes precisely what you want to know.

NASM x86_64 having trouble writing command line arguments, returning -14 in rax

I'm still running 32-bit hardware, so this is a wild asmed guess! As you probably know, 64-bit system call numbers are completely different, and "syscall" is used instead of int 80h. However int 80h and 32-bit system call numbers can still be used, with 64-bit registers truncated to 32-bit. Your tests indicate that this works with addresses in .data, but with a "stack address", it returns -14 (-EFAULT - bad address). The only thing I can think of is that truncating rcx to ecx results in a "bad address" if it's on the stack. I don't know where the stack is in 64-bit code. Does this make sense?

I'd try it with "proper" 64-bit system call numbers and registers and "syscall", and see if that helps.

Best,
Frank

Function arguments in x86-64 asm

The 64 bit calling convention passes first 6 function arguments in registers, so argc is in rdi and argv is in rsi. The first command line argument is argv[1] so to access that you need to load 8(%rsi):

.globl main
main:
subq $8, %rsp # align stack
movq 8(%rsi), %rsi # fetch argv[1]
leaq fmt(%rip), %rdi # format string
xorl %eax, %eax # no xmm used
call printf # print
xorl %eax, %eax # zero return value
addq $8, %rsp # restore stack
ret # done

.data
fmt: .string "First argument is %s\n"

$ ./a.out foo bar
First argument is foo

Of course you should check argc to see if you received enough arguments.

Printing Commandline Arguments x86 Assembly

On POSIX systems if you start a program from a shell the shell will perform so-called globbing, expanding the * and replacing it with the matching files; the result will then be used as the arguments for the invocation of your program.

You cannot do anything to prevent it from your program, the arguments you see are indeed those it got from the shell (IOW, they are the arguments that have been passed to exec).

If you want to pass a literal * to your program when starting it from a shell, you'll have to quote it.

./asm5 me you them us "*"

Of course none of this will happen if some other program launches your program passing the arguments straight to exec, without the shell getting in the way.


Replaced:

; the loop
cmp ecx, eax ; if ecx not equal to eax
jne begin_for_loop ; jmp to loop, else exit

With:

; the loop
cmp ecx, eax ; if ecx not equal to eax
jmp begin_for_loop ; jmp to loop, else exit

And I found a bigger issue where the program prints ENV variables to the screen.

This comes from the fact that you are ignoring the NULL that terminates the argv arguments list, and you are going on reading what's next; this in your case happens to be the environment memory block.

Assembly PE64 Console Can't Find Command-line Arguments Count and Array (argc) + (argv)

Command-line arguments, including the name of executable itself, are parsed by OS and put on stack in Linux
but things are very different in Windows. You need to invoke kernel function GetCommandLineA() and parse the returned string by yourself.

Invoking ExitProcess never returns to the exited program, so your instruction hlt will not execute and should be omitted.



Related Topics



Leave a reply



Submit