Linux nasm command line args as integers

I've been banging my head for days trying to figure this out, finally posting some help here. This exercise is purely academic for me, but it got to the point where I just need to figure out why this isn't working or what I'm doing wrong.

section .text
    global _start

    pop eax
    pop ebx
    pop ecx

    mov eax, 1
    mov ebx, 0
    int 0x80


Compiling / linking with:

$ nasm -f elf -o test.o test.asm
$ gcc -o test test.o


Run in gdb with argument "5":

$ gdb test
(gdb) b _exit
Breakpoint 1 at 0x8048063
(gdb) r 5
Starting program: /home/rich/asm/test 5

Breakpoint 1, 0x08048063 in _exit ()
(gdb) i r
eax            0x2      2
ebx            0xbffff8b0       -1073743696
ecx            0xbffff8c8       -1073743672
edx            0x0      0
esp            0xbffff78c       0xbffff78c
ebp            0x0      0x0


So, eax

it makes sense here - is it 0x2 or 2, argc. My question is, how do I get the value "5" (or 0x5) into a register? As I understand it ecx

is a pointer to my value 5, since I can "dereference" it into a usable digit, i.e. What can I do arithmetic?


source to share

2 answers

What do you want to do about it? Your understanding is correct: the kernel pushes the argc counter to the top of the stack, under which argv [0] ... argv [argc-1] is in reverse order (ie, the top of the stack / low address contains the first argument). You can check this with gdb on any binary on the system:

$ echo "int main(){return 0;}" > test.c
$ gcc test.c
$ gdb ./a.out
(gdb) b _start
(gdb) r A B C D E
(gdb) p ((void**)$rsp)[0]
$2 = (void *) 0x6
(gdb) p (char*)((void**)$rsp)[1]
$4 = 0x7fffffffeab7 "/home/andy/a.out"
(gdb) p (char*)((void**)$rsp)[2]
$5 = 0x7fffffffeac8 "A"
(gdb) p (char*)((void**)$rsp)[3]
$6 = 0x7fffffffeaca "B"
(gdb) p (char*)((void**)$rsp)[4]
$7 = 0x7fffffffeacc "C"
(gdb) p (char*)((void**)$rsp)[5]
$8 = 0x7fffffffeace "D"
(gdb) p (char*)((void**)$rsp)[6]
$9 = 0x7fffffffead0 "E"


You might be asking how to parse strings? This is a more difficult question.



I realize this may be a little overdue and you may have already been working on this or moving on to something else, but I ran into this question when I was looking for something related to this and decided I could help to someone else who comes across this.

The problem I think you are running into is that the "5" you pass into your program is then not stored as an integer 5, as you might expect. The argument is passed to your program as a char, and as Andy pointed out, you would point to a pointer to a byte containing 0x35, which is an integer value that represents the ASCII character 5, not a pointer to an integer value 5.

To use the argument as an integer, you need to convert the byte to its integer equivalent, as defined in the ASCII table - otherwise, you will find that you are passing into char 5, but any math you try with this will use 53 ( 0x35) because it's 5 in ASCII.

You can find an example of how to perform this conversion in the rsi_to_bin function of the sample asm program here . Once you convert the ascii code to its actual integer equivalent, you will get the correct number you passed in and be able to do whatever arithmetic you wanted with it. An extremely simple example is to simply subtract 48 from the input - this will work if you only pass in one integer 0-9.



All Articles