免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 5436 | 回复: 8
打印 上一主题 下一主题

[C] Linux 下程序启动时命令行参数的个数保存在哪里? [复制链接]

论坛徽章:
11
摩羯座
日期:2013-09-29 17:39:09白羊座
日期:2014-11-13 09:38:14技术图书徽章
日期:2014-01-17 15:07:36狮子座
日期:2013-12-25 14:01:52技术图书徽章
日期:2013-12-17 11:33:22技术图书徽章
日期:2013-12-03 10:27:57天秤座
日期:2013-11-08 15:47:19申猴
日期:2013-10-29 13:16:32未羊
日期:2013-10-12 22:28:56辰龙
日期:2013-10-09 14:39:5515-16赛季CBA联赛之山东
日期:2016-07-25 10:23:00
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-09-11 18:23 |只看该作者 |倒序浏览
如题,请教各位:
《professional assembly language》中讲到,命令行参数的个数保存在ESP指针之后(向高地址方向)的位置,但小弟通过代码并未验证到这一点:
  1. root@c-dev:/cdev# vi memory_layout.c
复制代码
  1. int main (int argc, char *argv[])
  2. {
  3.     return 0;
  4. }
复制代码
  1. root@c-dev:/cdev# gcc -m32 -g memory_layout.c -o memory_layout
复制代码
  1. root@c-dev:/cdev# gdb --args memory_layout a bc def
  2. GNU gdb (GDB) 7.0.1-debian
  3. Copyright (C) 2009 Free Software Foundation, Inc.
  4. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
  5. This is free software: you are free to change and redistribute it.
  6. There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
  7. and "show warranty" for details.
  8. This GDB was configured as "x86_64-linux-gnu".
  9. For bug reporting instructions, please see:
  10. <http://www.gnu.org/software/gdb/bugs/>...
  11. Reading symbols from /cdev/memory_layout...done.
  12. (gdb) break main
  13. Breakpoint 1 at 0x8048397: file memory_layout.c, line 3.
  14. (gdb) run
  15. Starting program: /cdev/memory_layout a bc def

  16. Breakpoint 1, main (argc=4, argv=0xffffdd54) at memory_layout.c:3
  17. 3                return 0;
  18. (gdb) x/x 0xffffdd54
  19. 0xffffdd54:        0xffffde70
  20. (gdb) x/s 0xffffde70
  21. 0xffffde70:         "/cdev/memory_layout"
  22. (gdb) print argv[0]
  23. $1 = 0xffffde70 "/cdev/memory_layout"
  24. (gdb) print argv[1]
  25. $2 = 0xffffde84 "a"
  26. (gdb) print argv[2]
  27. $3 = 0xffffde86 "bc"
复制代码
自argv的内存地址开始向高地址方向,依次为各个命令行参数和环境变量,但通过怎样的方法才能找到保存命令行参数个数的内存地址呢?

请各位大神指点一下,小弟菜鸟,不甚感谢。


stack.png (37.65 KB, 下载次数: 43)

stack.png

论坛徽章:
4
白羊座
日期:2013-09-17 21:59:30技术图书徽章
日期:2013-10-12 22:16:03白羊座
日期:2013-10-14 11:01:40双子座
日期:2013-12-17 18:26:39
2 [报告]
发表于 2013-09-11 21:48 |只看该作者
回复 1# superwujc
  1. x /d $ebp+8
复制代码

论坛徽章:
11
摩羯座
日期:2013-09-29 17:39:09白羊座
日期:2014-11-13 09:38:14技术图书徽章
日期:2014-01-17 15:07:36狮子座
日期:2013-12-25 14:01:52技术图书徽章
日期:2013-12-17 11:33:22技术图书徽章
日期:2013-12-03 10:27:57天秤座
日期:2013-11-08 15:47:19申猴
日期:2013-10-29 13:16:32未羊
日期:2013-10-12 22:28:56辰龙
日期:2013-10-09 14:39:5515-16赛季CBA联赛之山东
日期:2016-07-25 10:23:00
3 [报告]
发表于 2013-09-11 21:59 |只看该作者
回复 2# 井蛙夏虫
可以得到结果,但请教为什么是$ebp+8呢?


   

论坛徽章:
11
摩羯座
日期:2013-09-29 17:39:09白羊座
日期:2014-11-13 09:38:14技术图书徽章
日期:2014-01-17 15:07:36狮子座
日期:2013-12-25 14:01:52技术图书徽章
日期:2013-12-17 11:33:22技术图书徽章
日期:2013-12-03 10:27:57天秤座
日期:2013-11-08 15:47:19申猴
日期:2013-10-29 13:16:32未羊
日期:2013-10-12 22:28:56辰龙
日期:2013-10-09 14:39:5515-16赛季CBA联赛之山东
日期:2016-07-25 10:23:00
4 [报告]
发表于 2013-09-11 23:16 |只看该作者
回复 2# 井蛙夏虫
已明了,多谢!

附上小弟的解释,请各位不吝拍砖
在C风格的函数调用中,stack首先保存被调函数的输入参数,然后是返回到主程序的地址
而为避免函数另包含其他压栈操作而改变esp的值(如嵌套调用函数),导致无法通过原来的esp间接寻址访问输入参数
因此在函数被调动时会将ebp压栈并将此时的esp值赋予ebp,使得ebp保存函数调用时的返回地址,之后esp指针可以随意向栈底移动,而不影响函数返回时执行清栈

由于32位系统上的地址为4 byte,因此
ebp保存的是函数被调用时的stack顶地址,ebp+4为被调函数的返回地址,ebp+8为被调函数的第一个参数
而对于main()函数,其输入参数有0或2个(int argc, char *argv[]),所以在gdb中,x/d $ebp+8命令将得到argc的值,即程序命令行参数的个数
完毕

   

论坛徽章:
0
5 [报告]
发表于 2013-09-12 00:05 |只看该作者
这个明显是体系架构相关的,看Linux内核中do_fork()的实现吧

论坛徽章:
12
巳蛇
日期:2013-09-16 15:32:242015年辞旧岁徽章
日期:2015-03-03 16:54:152015年亚洲杯之约旦
日期:2015-02-11 14:38:37双鱼座
日期:2015-01-05 11:05:47戌狗
日期:2014-12-08 09:41:18戌狗
日期:2014-08-15 09:29:29双子座
日期:2014-08-05 09:17:17卯兔
日期:2014-06-08 15:32:18巳蛇
日期:2014-01-27 08:47:08白羊座
日期:2013-11-28 21:04:15巨蟹座
日期:2013-11-13 21:58:012015年亚洲杯之科威特
日期:2015-04-17 16:51:51
6 [报告]
发表于 2013-09-12 09:18 |只看该作者
由于main函数也是被别的函数调用,所以这个问题就变成了函数的参数放在哪里。这就由体系结构的ABI来决定了。

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
7 [报告]
发表于 2013-09-12 13:20 |只看该作者
superwujc 发表于 2013-09-11 18:23
如题,请教各位:
《professional assembly language》中讲到,命令行参数的个数保存在ESP指针之后(向高地 ...

那,argc是什么呢?

论坛徽章:
17
处女座
日期:2013-08-27 09:59:352015亚冠之柏太阳神
日期:2015-07-30 10:16:402015亚冠之萨济拖拉机
日期:2015-07-29 18:58:182015年亚洲杯之巴勒斯坦
日期:2015-03-06 17:38:17摩羯座
日期:2014-12-11 21:31:34戌狗
日期:2014-07-20 20:57:32子鼠
日期:2014-05-15 16:25:21亥猪
日期:2014-02-11 17:32:05丑牛
日期:2014-01-20 15:45:51丑牛
日期:2013-10-22 11:12:56双子座
日期:2013-10-18 16:28:17白羊座
日期:2013-10-18 10:50:45
8 [报告]
发表于 2013-09-12 15:24 |只看该作者
回复 4# superwujc


    你说的这部分内容实际上就是为函数调用生成堆栈框架,而现代的编译器基本上都提供不生产函数调用堆栈框架的优化功能。这个时候不存在ebp保存esp并使用esp的问题。这个优化使得ebp寄存器可以用于其它目的也加速的函数调用的性能。gcc用-fomit-frame-pointer,VC++用/Oy (Frame-Pointer Omission)。

论坛徽章:
11
摩羯座
日期:2013-09-29 17:39:09白羊座
日期:2014-11-13 09:38:14技术图书徽章
日期:2014-01-17 15:07:36狮子座
日期:2013-12-25 14:01:52技术图书徽章
日期:2013-12-17 11:33:22技术图书徽章
日期:2013-12-03 10:27:57天秤座
日期:2013-11-08 15:47:19申猴
日期:2013-10-29 13:16:32未羊
日期:2013-10-12 22:28:56辰龙
日期:2013-10-09 14:39:5515-16赛季CBA联赛之山东
日期:2016-07-25 10:23:00
9 [报告]
发表于 2013-09-12 15:49 |只看该作者
回复 8# myworkstation
太高深,不懂,小弟只是觉得用堆栈的观点可以解释这个问题,也便于自己理解
请教楼上几位该如何理解?

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

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP