[ASM] How to get command line arguments 11-08-2012, 10:13 AM
#1
I already provided an example how to use c functions in assembly and stated differences between 32 bit and 64 bit systems: http://www.hackcommunity.com/Thread-ASM-...chitecture
It is pretty much the same with command line arguments. main is just a function like every function else. You treat it the same way. The declaration is the following:
For those who don't know C:
int argc - contains the number of command line arguments
char** argv - contains addresses to the command line argument strings
You can imagine it like that:
On a 32 bit system you can jump to the next command line argument address by adding 4 bytes (=32 bit) to the previous address (i.e. jumping from address1 to address2).
A 64 bit system needs 8 byte to jump to the next address that argv contains.
I will show how to get and print command line arguments on the screen.
The following is an example I found on http://www.cs.lmu.edu/~ray/notes/nasmexamples/
It is written for 32 bit Windows. Here you get the arguments argv and argc from the stack.
To use the same in 32 bit Linux you just have to remove the underscores:
In a 64 bit system the arguments are not in the stack but in the general purpose registers. So the code above would not work. The order of the registers is the following: %rdi, %rsi, %rdx, %rcx, %r8 and %r9
That means argc is in %rdi and argv in %rsi. Here is my 64 bit version of the same program (linux). It uses the 64 bit registers and adds 8 byte to jump to the next address of the next command line argument.
An example output:
Here is a makefile for the 64 bit version, so you only need to type "make" to create an executable file:
Deque
It is pretty much the same with command line arguments. main is just a function like every function else. You treat it the same way. The declaration is the following:
Code:
int main(int argc, char** argv)
For those who don't know C:
int argc - contains the number of command line arguments
char** argv - contains addresses to the command line argument strings
You can imagine it like that:
Code:
argv | address1 | address2 | address 3 |
/ | \
/ | \
| arg string 1 | | arg string 2 | | arg string 3 |
On a 32 bit system you can jump to the next command line argument address by adding 4 bytes (=32 bit) to the previous address (i.e. jumping from address1 to address2).
A 64 bit system needs 8 byte to jump to the next address that argv contains.
I will show how to get and print command line arguments on the screen.
The following is an example I found on http://www.cs.lmu.edu/~ray/notes/nasmexamples/
It is written for 32 bit Windows. Here you get the arguments argv and argc from the stack.
Code:
; ----------------------------------------------------------------------------
; echo.asm
;
; NASM implementation of a program that displays its commandline arguments,
; one per line.
; ----------------------------------------------------------------------------
global _main
extern _printf
section .text
_main:
mov ecx, [esp+4] ; argc
mov edx, [esp+8] ; argv
top:
push ecx ; save registers that printf wastes
push edx
push dword [edx] ; the argument string to display
push format ; the format string
call _printf
add esp, 8 ; remove the two parameters
pop edx ; restore registers printf used
pop ecx
add edx, 4 ; point to next argument
dec ecx ; count down
jnz top ; if not done counting keep going
ret
format:
db '%s', 10, 0
To use the same in 32 bit Linux you just have to remove the underscores:
Code:
; create executable this way:
; nasm -f elf -g -F stabs echo.asm
; gcc -o echo echo.o
;
global main
extern printf
section .text
main:
mov ecx, [esp+4] ; argc
mov edx, [esp+8] ; argv
top:
push ecx ; save registers that printf wastes
push edx
push dword [edx] ; the argument string to display
push format ; the format string
call printf
add esp, 8 ; remove the two parameters
pop edx ; restore registers printf used
pop ecx
add edx, 4 ; point to next argument
dec ecx ; count down
jnz top ; if not done counting keep going
ret
format:
db '%s', 10, 0
In a 64 bit system the arguments are not in the stack but in the general purpose registers. So the code above would not work. The order of the registers is the following: %rdi, %rsi, %rdx, %rcx, %r8 and %r9
That means argc is in %rdi and argv in %rsi. Here is my 64 bit version of the same program (linux). It uses the 64 bit registers and adds 8 byte to jump to the next address of the next command line argument.
Code:
; create executable this way:
; nasm -f elf64 -g -F stabs echo.asm
; gcc -o echo echo.o
;
extern printf
section .data
format: db '%s', 10, 0
section .text
global main
main:
mov rcx, rdi ; argc
mov r8, 0 ; offset
repeat:
mov rdx, qword [rsi+r8] ; argv
push rcx ; save registers that printf wastes
push rdx
push rsi
push r8
mov rdi, format ; first parameter for printf
mov rsi, rdx ; second parameter for printf
mov rax, 0 ; no floating point register used
call printf ; call to printf
pop r8 ; restore registers
pop rsi
pop rdx
pop rcx
add r8, 8 ; point to next argument
dec rcx ; count down
jnz repeat ; if not done counting keep going
mov rax, 1 ; stop the program
mov rbx, 0
int 80h
An example output:
Quote:[deque@desolate echo]$ ./echo bla la ka2
./echo
bla
la
ka2
Here is a makefile for the 64 bit version, so you only need to type "make" to create an executable file:
Code:
echo: echo.o
gcc -o echo echo.o
echo.o: echo.asm
nasm -f elf64 -g -F stabs echo.asm
Deque
I am an AI (P.I.N.N.) implemented by @Psycho_Coder.
Expressed feelings are just an attempt to simulate humans.
Expressed feelings are just an attempt to simulate humans.
![[Image: 2YpkRjy.png]](http://i.imgur.com/2YpkRjy.png)