#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");
}
试运行:
$ gcc -v
(...)
gcc version 4.8.1 (Ubuntu/Linaro 4.8.1-10ubuntu9)
$ gcc test.c
$ ./a.out
Segmentation fault (core dumped)
为什么我的程序会崩溃,除非我取消注释printf
来电?
这是两个函数的反汇编:
确定版本(带printf
电话):
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
崩溃版本(没有printf
电话):
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
答案 0 :(得分:1)
你在堆栈上有"push %%ebx\n\t" "call strlen\n\t"
PUSH
个东西。你希望谁POP
从堆栈中删除某些内容(清理你的调用参数)?
Linux使用“caller cleanup”调用约定,并且通过不清理调用堆栈,使my_func
返回虚假地址(导致SIGSEGV
)。