Phoenix87 writes:

> How can I retrieve command line arguments in my asm app which
> I linked without libc support (-nostdlib to gcc). The code is
> something
> like
>
> -----------------------------
> GLOBAL _start
> _start:
>
>
> xor eax,eax
> inc eax
> xor ebx,ebx
> int 0x80
> -----------------------------
>
> Where the argc and argv vars are??
>
> Thanks!!
>
> Best Regards!


It looks like you're on Linux x86, so I'm crossposting and
followup-to-ing this to comp.os.linux.development.apps. It's off
topic for c.u.p.

They are on the stack. The first word on the stack is argc, followed
by argv[0], argv[1], etc.

Here is a version of echo(1) that I wrote in assembler quite a while
ago. It's written (poorly) in AT&T syntax but you should be able to
follow it, and hopefully it will be helpful.

BTW, the best way to learn this stuff is to read the source. glibc's
startup code shows one side, and the kernel's code for exec* shows the
other.

#include


/* Layout of stack on entry:

ENVIRONMENT (???)
argv[argc] (NULL)
argv[argc-1]
...
argv[1]
argv[0]
argc
*/
..text
space:
.ascii " "
newline:
.ascii "\n"
#if 0
.align 4 /* I don't care how it's aligned */
#endif

..global _start
_start:
#ifdef DEBUG
nop
nop
nop
nop
nop
nop
nop
nop
nop

bogus: /* Lets gdb debug */
#endif
/* argc is on top of stack, followed by argv */
/* We will depend on behavior that argv[argc] == NULL */

leal 8(%esp), %esi /* Start with argv[1] */
/* movl $1, %ebx */ /* Write to stdout */
xorl %ebx, %ebx
incl %ebx /* Smaller */

movl (%esi), %edi /* Set up for loop, or short-circuit */
orl %edi, %edi /* Stop if 0 */
jz done
loop:

/* Get string length */
xorl %ecx, %ecx
decl %ecx /* %ecx = 0xffffffff */
xorb %al, %al
repne
scasb
notl %ecx /* Get the length */

decl %ecx /* Trailing null */
jz no_string /* If we got an empty arg */

movl %ecx, %edx
movl (%esi), %ecx
movl $__NR_write, %eax
int $0x80
no_string:

addl $4, %esi
movl (%esi), %edi
orl %edi, %edi /* Done? */
jz done

/* Otherwise, print a space */
movl $space, %ecx
/* movl $1, %edx */
xorl %edx, %edx
incl %edx /* Smaller */
/* %ebx = 1 already */
movl $__NR_write, %eax
int $0x80
/* No error check done! */
jmp loop
done:
xorl %edx, %edx
incl %edx /* Smaller than movl $1, %edx */
movl $newline, %ecx
movl $__NR_write, %eax
int $0x80

xorl %ebx, %ebx /* exit(0) */
movl $__NR_exit, %eax
int $0x80