Pregunta

#include <stdio.h>

static void my_func(char *text) {
    //printf("hello again\n");
    __asm__(
        "push %%ebp\n\t"
        "mov %0, %%ebx\n\t"
        "push %%ebx\n\t"
        "call strlen\n\t"
        "movb (%%ebx), %%al" 
    : : "r"(text));
}

int main() {
    int i;
    for(i = 0; i < 3; ++i)
        my_func("hello");
}

Test run:

$ gcc -v
(...)
gcc version 4.8.1 (Ubuntu/Linaro 4.8.1-10ubuntu9) 
$ gcc test.c
$ ./a.out 
Segmentation fault (core dumped)

Why does my program crash unless I uncomment the printf call?

Here's the disassembly for the two functions:

OK version (w/ printf call):

0804844d <my_func>:
 804844d:   55                      push   %ebp
 804844e:   89 e5                   mov    %esp,%ebp
 8048450:   83 ec 18                sub    $0x18,%esp
 8048453:   c7 04 24 30 85 04 08    movl   $0x8048530,(%esp)
 804845a:   e8 b1 fe ff ff          call   8048310 <puts@plt>
 804845f:   8b 45 08                mov    0x8(%ebp),%eax
 8048462:   89 c3                   mov    %eax,%ebx
 8048464:   53                      push   %ebx
 8048465:   e8 c6 fe ff ff          call   8048330 <strlen@plt>
 804846a:   8a 03                   mov    (%ebx),%al
 804846c:   c9                      leave  
 804846d:   c3                      ret   

Crashing version (no printf call):

 0804841d <my_func>:
 804841d:   55                      push   %ebp
 804841e:   89 e5                   mov    %esp,%ebp
 8048420:   8b 45 08                mov    0x8(%ebp),%eax
 8048423:   89 c3                   mov    %eax,%ebx
 8048425:   53                      push   %ebx
 8048426:   e8 d5 fe ff ff          call   8048300 <strlen@plt>
 804842b:   8a 03                   mov    (%ebx),%al
 804842d:   5d                      pop    %ebp
 804842e:   c3                      ret    
¿Fue útil?

Solución

"push %%ebx\n\t"
"call strlen\n\t"

You PUSH something on the stack. Who do you expect to POP that something off the stack (clean up your call parameter)?

Linux uses "caller cleanup" calling convention, and by not cleaning up the call stack, you are making my_func return to a bogus address (which causes SIGSEGV).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top