x86 Assembly Command Line Arguments

Whether you're a newbie or an experienced programmer, any questions, help, or just talk of any language will be welcomed here.

Moderator: Coders of Rage

Post Reply
ajtgarber
Chaos Rift Cool Newbie
Chaos Rift Cool Newbie
Posts: 97
Joined: Wed Jun 10, 2009 8:56 am

x86 Assembly Command Line Arguments

Post by ajtgarber »

Hello, I've written a few assembly programs recently trying to print out all of the command line arguments given to the program but I've come across a few issues. First way I tried (just to get the first argument) was to pop off the char* and try to print it with the system call write:

Code: Select all

section .text
    global _start
_start:
    pop ecx
    pop ecx ; something along the lines of ./a.out
    mov eax, 4
    mov ebx, 1
    mov edx, 20
    int 0x80
    ...
But the problem with it was that I didn't know how long each of the argument strings were, and the write system call doesn't stop writing after hitting zero, and I'm not sure that the arguments are zero terminated.

So now I've tried this:

Code: Select all

section .text
	global _start

_start:
	pop eax
	call printargv

	mov eax, 1
	mov ebx, 0
	int 0x80

printargv:
	pop esi
	pop esi
	mov eax, 4
	mov ebx, 1
	mov ecx, msg
	mov edx, msglen
	int 0x80
.start
	lodsb
	or al, al
	jz .done
	mov ebx, 1
	mov ecx, eax
	mov eax, 4
	;mov byte [buffer], al
	;mov ecx, [buffer]
	mov edx, 1
	int 0x80
	jmp .start
.done
	ret

section .bss
	buffer resb 1
section .data
	msg db 'Entering printargv...', 13, 10, 0
	msglen equ $-msg
Where I take the first 'real' command line argument (doesn't really matter which one I guess) and go through it character by character until I hit zero. The code I have above always fails with a segmentation fault in printargv between .start and .done.
The way I'm doing this probably looks weird, but thats because I'm adapting some code that talks to the BIOS to write code out character by character. How can I go through a string character by character in 32-bit code? Is there a better way to print out the command line arguments using assembly?
Just in case it's useful to anyone this is using the nasm assember.
N64vSNES
Chaos Rift Devotee
Chaos Rift Devotee
Posts: 632
Joined: Thu Aug 12, 2010 11:25 am

Re: x86 Assembly Command Line Arguments

Post by N64vSNES »

I'm not 100% if this will work, as I'm fuzzy on whether passing arguments was just something the C library did. I'll look into that and get back to you.

I'm pretty surprised that your example assembled, I'm not entirely sure (about anything in this post), but I didn't think it would be valid to call pop without a call to push..... :S

But this should work for you:

Code: Select all

global main
extern printf


section .text
main:
        ; Gets number of arguments (int argc)
	push dword[esp + 4]
	push argc
	call printf

	add esp, 8
	
	mov eax, dword [esp + 8]

        ; Gets first byte of args (char *args[])
	mov edx, dword [eax]
	push dword [edx]
	push arg
	call printf
	add esp, 8



section .data
argc db 'argc: %i', 0
arg db 'argv[0][0]: %c', 0
It just gets the parameters by pushing values onto the stack from their address.
This will only take the first byte of the first argument, however I think the arguments are null terminated '\0', so you shouldn't have too much trouble with strings.

Let me know how you get on, sorry if I'm vague I'm still terrible with my assembly.

PS: Whenever need to know how something would be done in assembly, I usually like to write a basic C program to do it, and then pass it to GCC with

Code: Select all

gcc -O0 -S Main.c
This will give the assembly output of the file, which can be very useful! ;)
Post Reply