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
_start:
pop eax
pop ebx
pop ecx
_exit:
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
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.
source to share
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.
source to share