Search code examples
assemblyx86att

Segfault moving (%eax), %ebx on the second iteration of this loop?


I'm new in assembly and am trying to print one character of a string at a time, and currently have this so far.

    .equ  STDOUT,1
    .equ  WRITE,4
    .equ  EXIT,1

char_string:
    .asciz "hello, world"
    
.text
    .globl _start

_start:
    movl $char_string, %eax
    call print_str
    movl $EXIT, %eax
    int $0X80
    
print_str:
        mov (%eax), %ebx
        movl $WRITE, %eax
        movl $STDOUT, %ebx
        movl $char_string, %ecx
        movl $1, %edx
        int $0x80
        inc %eax
        cmpl $0, %ebx
        jne print_str
        je out_of_loop
out_of_loop:
    ret

However, when I try to compile I'm getting a segmentation fault at the line move (%eax), %ebx What's the problem with this? And how do I fix it? I'm trying to get the pointed char of the string to be moved to %ebx for the print and then later on I increment eax to move on to the next char in the string.


Solution

  • The direct cause of the crash is that eax is used as the return value of the system call. Your code is wrong in other ways too, however. I have commented your code:

    print_str:
            mov (%eax), %ebx           # loads 4 bytes not 1
            movl $WRITE, %eax
            movl $STDOUT, %ebx         # overwrites ebx you loaded
            movl $char_string, %ecx    # uses the starting address instead of iterating
            movl $1, %edx
            int $0x80
            inc %eax                   # eax is return value of system call by now
            cmpl $0, %ebx              # ebx is $STDOUT, see above
            jne print_str
            je out_of_loop             # makes no sense to jump to next instruction
    out_of_loop:
        ret
    

    A possible solution could be:

    print_str:
            mov %eax, %ecx             # address of char to print
            movl $STDOUT, %ebx
            movl $1, %edx
    print_str_loop:
            cmpb $0, (%ecx)            # test for terminating zero byte
            je out_of_loop
            movl $WRITE, %eax          # reload eax as it is return value from a previous iteration
            int $0x80
            inc %ecx                   # point to next character
            jmp print_str_loop
    out_of_loop:
            ret