Search code examples
stringassemblyx86attreversing

Reversing a string and printing it in IA32 assembly


So basically I'm trying to read a string, increase a counter (in this case, %edx) until I read a \n, and then, going backwards to print it reversed.

This is my code:

.section .data
cadsal: 
    .asciz "Por favor ingrese su cadena:\n"

leer:
    .asciz "%s"

salidafinal:
    .asciz "La cadena introducida, invertida es:\n"

imp:
    .asciz "%c\n"

.section .bss .comm cadena,50,1

.section .text

.globl _start

_start:

leal cadsal, %eax
pushl %eax
call printf
addl $4, %esp

leal cadena, %eax
pushl %eax
leal leer, %eax
pushl %eax  
call scanf
addl $8, %esp

xorl %edx, %edx

Contar:

movb cadena(%edx), %al
incl %edx
cmpb $0, %al
jne Contar

leal salidafinal, %ecx
pushl %ecx
call printf
addl $4, %esp

addl $-2, %edx

Invertir:

movb cadena(%edx), %al
pushl %eax
leal imp, %ebx
pushl %ebx
call printf
addl $8, %esp

decl %edx
cmpl $0, %edx
jge Invertir

movl $1, %eax
int $0x80

I'm using the command -nostartfiles when compiling. It works, but when I run it, segmentation fault appears when entering in "Invertir". I need help to detect what's wrong in this code.

Thanks!


Solution

  • Your immediate problem is cmpb '\n', %al which is missing the $ sign required in at&t syntax to make it an immediate. As it is, '\n' is considered an address, and an invalid one at that. You should use cmpb $'\n', %al.

    However scanf will not place '\n' into your buffer at all, because %s stops at whitespace. So you really want to be looking for a terminating zero byte instead, that is use cmpb $0, %al. Or, if you really need to read a whole line, use fgets instead.

    If you fix that, you will run into the next problem which is that you have an incl %edx between your cmp and the jne which will change the flags so you will not be branching on the result of the comparison but the increment. Solution: swap the cmp and the incl.

    Yet another problem is that some registers, including %edx, are caller-saved. As such they can be modified by called functions, and you do call printf. You should push/pop around both of those to preserve the value.

    Even after all of that, you probably won't see any output until you print a final \n manually, due to buffering.

    Note that if you intend to use C library, you should really not use -nostartfiles. Instead, you should use entry point main and assemble and link normally. Also, you should simply return from main (or at most call exit) and not use direct system call because that doesn't allow the C library to clean up properly. Incidentally, that would also flush the I/O buffers, so you would see the output even without an extra newline.

    You should really learn to use a debugger.