evanjs
evanjs

Reputation: 13

Reading filename from argv via x86 assembly

I'm and trying to read a filename passed to my executable and write to that file using assembly. It compiles without error but fails when executed. What is wrong with my code exactly?

BITS 32
segment .data
text db "text"

segment .text

global main

main:
pop ebx 
pop ebx
pop ebx    ; pop pointer to filename into ebx
mov eax,0x5  ;syscall open
mov ecx,0x2   ;flag read/write
int 0x80   ;call kernel
mov ebx,eax   ;save returned file descriptor
mov eax,0x4 ; write syscall
mov ecx,text ;mov pointer to text into ecx
mov edx,0x4 ;string length
int 0x80  ;exit syscall
mov eax,0x1
int 0x80

Upvotes: 1

Views: 3224

Answers (2)

ninjalj
ninjalj

Reputation: 43688

On entry to main: the stack has the following:

...
*envp[]
*argv[]
argc
return address

When you pop ebx thrice, you end up accesing argv, not argv[1].

argv is a pointer to a NULL-terminated array of char *, so you have to follow the indirection, as @user786653 shows.

Upvotes: 2

user786653
user786653

Reputation: 30460

Since you're being called from libc you also have to recall that you have return address so you could return there. This is unlike what you get if you just have a bare-bones assembly program (like a lot of tutorials!). With that in mind:

pop ebx    ;; pops return address to libc caller (_start usually)
pop ebx    ;; pops argc
pop ebx    ;; pops argv !!WAS!!: ; pop pointer to filename into ebx

Here's how you can print the first argument. You should be able to go from there (beware: I might have made mistakes):

    BITS 32

    section .text
    global main
    extern strlen

main:
    pop ecx ; Return address
    pop ecx ; argc
    pop ecx ; argv 
    mov ecx, [ecx+4] ; argv[1]

    push ecx
    call strlen
    mov edx, eax ; count
    pop ecx ; buf

    mov eax, 4 ; sys_write
    mov ebx, 1 ; stdout
    int 0x80

    mov eax, 1 ; sys_exit
    mov ebx, 0 ; status
    int 0x80

Upvotes: 4

Related Questions