1

I want to write a text to a file that i take from argv[1] but for some reason, it returns this Error:

[1] 5590 segmentation fault (core dumped) ./hey hey.txt

Here is my code:

.section .data
        .equ SYS_OPEN, 5
        .equ SYS_CLOSE, 6
        .equ SYS_WRITE, 4
        .equ SYS_READ, 3
        .equ SYS_EXIT, 1

        .equ LINUX_SYSCALL, 0X80
        .equ STDIN, 0
        .equ STDOUT, 1
        .equ STDERR, 2
        .equ O_CREATE_WRITE, 03101
        .equ TEXT_SIZE, 17
text:
                .ascii "hey diddle diddle\0"
.section .text
.globl _start
_start:
        pushl %ebp

        #reserve memory for file descriptor
        subl $4, %esp
        
        #opening file we want to write to
        movl $SYS_OPEN, %eax
        movl 8(%ebp), %ebx #8(%ebp) is the argv[1] that's where we take our filename
        movl $O_CREATE_WRITE, %ecx
        movl $0666, %edx

        int $LINUX_SYSCALL

        movl %eax, -4(%ebp) #store file descriptor

_write_text:
        # making the write syscall
        movl $SYS_WRITE, %eax
        movl -4(%ebp), %ebx #file descriptor in %ebx
        movl $text, %ecx #Addres of text 
        movl $TEXT_SIZE, %edx 

        int $LINUX_SYSCALL
_exit:
        #close the file
        movl $SYS_CLOSE, %eax
        movl -4(%ebp), %ebx #file dexcriptor to close
        int $LINUX_SYSCALL

        #exit
        movl $SYS_EXIT, %eax
        movl $0, %ebx
        int $LINUX_SYSCALL

this is how I assembled and linked:

➜ as --32 hey.s -o hey.o ➜ ld -m elf_i386 hey.o -o hey ➜ ./hey hey.txt

what's the problem here and how can I give the filename to it directly in a string, not in argv?

Awolez
  • 11
  • 4
  • 1
    Note that there is no red zone on i386. `-4(%esp)` refers to storage that may be clobbered. I'm not sure about the offsets you use to find the first command line argument either. Due to a lack of comments, it is hard to say what exactly your intent is, but it doesn't look completely right. – fuz Mar 20 '23 at 12:43
  • `movl %eax, -4(%esp)` will store the value `$SYS_OPEN` to `-4(%esp)`. This looks weird not only because you are using `%esp` instead of `%ebp` but also this move is done *before* invoking a system call. – MikeCAT Mar 20 '23 at 12:45
  • 1
    And you don't even set `ebp` up to point to your frame. – Jester Mar 20 '23 at 12:52
  • I fixed -4(%esp) to -4(%ebp) and made the linux syscall before storing the file descriptor and added some comments but it still returns the same error. – Awolez Mar 20 '23 at 13:28
  • I pushed %ebp so it should point to the frame, I don't see any problem with that. – Awolez Mar 20 '23 at 13:30
  • 4
    Pushing `ebp` is for preserving the prior value. Pushing does not **set** `ebp` to anything, you need a `mov` for that. – ecm Mar 20 '23 at 14:02

1 Answers1

0

the problem was this line

pushl %ebp

I replaced it with this and it worked fine.

movl %esp, %ebp

this refers to the stack frame so we can access file descriptor and file name. and for giving the file name directly instead of argv we could define a symbol in data section using the .ascii directive

filename:
    .ascii "hey.txt\0"
Awolez
  • 11
  • 4
  • Normally you'd use `.asciz "hey.txt"` to get a zero-terminated string, but yes `.ascii` with an explicit zero byte is equivalent. Also, in an actual function (not `_start`) you would need `mov %esp, %ebp` *as well* as `push %ebp`, because you still need to save/restore the caller's value as well as set your own. See any tutorial that uses EBP as a frame pointer for the standard function-prologue sequence, or look at compiler output for a debug build. – Peter Cordes Mar 20 '23 at 19:41