LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
12
返回列表 发新帖
楼主: rickxbx

play with C

[复制链接]
 楼主| 发表于 2005-9-11 18:47:00 | 显示全部楼层
Post by chairman
不懂,大侠给解释一下.*(&a+2) = &g;是什么意思?

局部变量a的地址加2事实上就是这个函数的返回地址所在的地址,在这里填上函数g的地址,那么当函数返回时,就会返回到g函数那了

栈里面是这样的:
[eip]
[ebp]
[a]

再次强调:编译器相关,体系结构相关
回复 支持 反对

使用道具 举报

发表于 2005-9-12 11:23:02 | 显示全部楼层
和缓冲区溢出的原理一样,都是利用stack中保存的函数返回地址作文章。
有些RISC体系结构的计算机是在寄存器中专门指定一个寄存器保存函数返回地址,这种作法肯定是不能直接照搬的。
回复 支持 反对

使用道具 举报

发表于 2005-9-13 21:09:03 | 显示全部楼层
__asm__("pushl $n;");
是把n那个地方的地址压栈.在g()返回的时候可以弹出.那么g()返回的时候是弹出栈顶的
数据,还是会弹出一个固定的地址.
我把main里的f();屏蔽后,为什么在main结束的时候不能弹出n的地址呢?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-9-13 21:55:58 | 显示全部楼层
Post by chairman
__asm__("pushl $n;");
是把n那个地方的地址压栈.在g()返回的时候可以弹出.那么g()返回的时候是弹出栈顶的
数据,还是会弹出一个固定的地址.
我把main里的f();屏蔽后,为什么在main结束的时候不能弹出n的地址呢?

因为main函数最后的汇编是这样的:

  1. leave
  2. ret
复制代码

而leave=

  1. movl %ebp,%esp
  2. popl %ebp
复制代码

那我们发现,最后的esp是由当前的ebp决定的,而ebp在一个函数内部可以认为是不变的,不会因为压入了一些数据而改变.所以,在ret之前,esp已经指向main函数应该返回的地方.
回复 支持 反对

使用道具 举报

发表于 2005-9-17 17:29:13 | 显示全部楼层
Post by rickxbx
局部变量a的地址加2事实上就是这个函数的返回地址所在的地址,在这里填上函数g的地址,那么当函数返回时,就会返回到g函数那了

栈里面是这样的:
[eip]
[ebp]
[a]

再次强调:编译器相关,体系结构相关

还跟优化参数相关
[PHP][leo@leo test]$ gcc t.c -O
t.c: In function 'f':
t.c:18: warning: assignment makes integer from pointer without a cast
[leo@leo test]$ ./a.out
entering main ...
f is calling...
back to main
[/PHP]
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表