免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: superwujc
打印 上一主题 下一主题

[C] Linux下c函数参数的入栈顺序? [复制链接]

论坛徽章:
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
21 [报告]
发表于 2013-01-28 16:02 |只看该作者
  1. main:
  2. .LFB11:
  3.         .cfi_startproc
  4.         subq    $8, %rsp
  5.         .cfi_def_cfa_offset 16
  6.         movl    $.LC3, %edx
  7.         movl    $99999, %esi
  8.         movl    $18, %edi
  9.         call    func
  10.         xorl    %eax, %eax
  11.         addq    $8, %rsp
  12.         .cfi_def_cfa_offset 8
  13.         ret
  14.         .cfi_endproc
复制代码
这是我看到的汇编,根本就没有什么入栈,3个参数全部通过寄存器传递的。ABI没有被打破,和我之前说的符合,func通过寄存器拿到参数,
但既然已经通过代码取得了参数的地址,所以必须要把这3个参数对应到内存。

论坛徽章:
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
22 [报告]
发表于 2013-01-28 16:10 |只看该作者
回复 19# zylthinking

如此说来,这个问题取决于多方面的原因是吗?“函数参数的入栈顺序是从。。。到。。。”之类的说法都是毫无道理的了?但这些说法总该有个来由吧,比如什么权威教材之类的

只会用头撞南墙而学不得其法的菜鸟看过这么多的帖子之后感到很悲催!!!

哎!

   

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
23 [报告]
发表于 2013-01-28 16:11 |只看该作者
zhaohongjian000 发表于 2013-01-28 16:02
这是我看到的汇编,根本就没有什么入栈,3个参数全部通过寄存器传递的。ABI没有被打破,和我之前说的符合, ...


你的是 x86-64 代码, 我的是 -m32  的代码, 不知道你的 func 反汇编是什么; 但 64 位机器上的 -m32 编译也会通过寄存器传参数??

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
24 [报告]
发表于 2013-01-28 16:13 |只看该作者
superwujc 发表于 2013-01-28 16:10
回复 19# zylthinking

如此说来,这个问题取决于多方面的原因是吗?“函数参数的入栈顺序是从。。。到。 ...


你自己先实验一下 var_list 这些东西在你的编译器下能否正常跑起来吧, 如果只是学学 c 语言, 或者 var_list 这些, 就不用考虑那一坨别的东西了,var_list 能正常跑, 那就是什么事也没有, 否则就是编译器 bug

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
25 [报告]
发表于 2013-01-28 16:16 |只看该作者
superwujc 发表于 2013-01-28 16:10
回复 19# zylthinking

如此说来,这个问题取决于多方面的原因是吗?“函数参数的入栈顺序是从。。。到。 ...

查一下ABI 或者调用约定相关资料吧, 也没什么神秘的了不起的东西, 你我差别, 就是我现在知道大概有这么一回事, 你还不知道, 而你要想知道, 也就是半小时的事情

论坛徽章:
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
26 [报告]
发表于 2013-01-28 16:26 |只看该作者
回复 24# zylthinking

可以运行stdarg,没问题,毕竟gcc要遵从ANSI,ISO,C99等等

之前提问过stdarg在gcc(或者glibc)中的实现,自己在头文件中没找到,网上的都是vc的实现

小弟现在想通过本质来理解现象,而不是通过现象来推断本质

http://wenku.baidu.com/view/78beecaddd3383c4bb4cd2e5.html 这里通过代码来验证参数入栈顺序,用vc实现解释stdarg
[url= http://bbs.chinaunix.net/thread-2005270-1-1.html ] http://bbs.chinaunix.net/thread-2005270-1-1.html [/url]这里用了从右到左的入栈顺序来解释
http://blog.chinaunix.net/uid-26009923-id-3261696.html 这里也把入栈顺序作为定理,来推断结果

还有一个cdecl,明确说明了C的默认函数调用方法

现在看来,一个问题的不确定因素太多,哪怕是最简单的问题,一些貌似说得通的道理其实个问题本身毫无关系。。。

迷茫中。。。

   

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
27 [报告]
发表于 2013-01-28 16:37 |只看该作者
superwujc 发表于 2013-01-28 16:26
回复 24# zylthinking

可以运行stdarg,没问题,毕竟gcc要遵从ANSI,ISO,C99等等


那就没问题了, cdecl 是默认调用约定一说, 大概是说在 x86 下。 因为既然 64 位下就算参数顺序相反也能让 var_list 正常运行, 那就说明 var_list 作者是知道这个情况的, 也就是说这是故意的; 也就是说这是正确的
反正 arm 下函数前四个参数也是通过寄存器来传递的;
刚做了一个试验, 我就算在函数定义前加 __cdecl, 参数还是通过寄存器来的; 那就是说, 其实通过寄存器传递参数, 也叫 __cdecl; 至于对不对, 就要看 __cdecl 是不是有标准定义了; 我不知道

论坛徽章:
2
程序设计版块每日发帖之星
日期:2015-06-17 22:20:00每日论坛发贴之星
日期:2015-06-17 22:20:00
28 [报告]
发表于 2013-01-28 16:42 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
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
29 [报告]
发表于 2013-01-28 16:56 |只看该作者
zylthinking 发表于 2013-01-28 16:11
你的是 x86-64 代码, 我的是 -m32  的代码, 不知道你的 func 反汇编是什么; 但 64 位机器上的 -m32  ...


我以为我们讨论的是64位的情况。如果是32位,gcc遵循的调用约定不是我给出的那个,而是你们说的cdecl。
但原理是一样的:
1.ABI不会被打破
2.假设参数都放到栈上,按从左到右入栈本身就是不对的。从这个假设推导出的结论自然也不对。

不过,我试了下-m32的情况,得到的结果正是楼主预期的,从汇编上看32位下几个参数全部通过寄存器传递的。

32位汇编:
  1.         .file   "abi.c"
  2.         .section        .rodata.str1.1,"aMS",@progbits,1
  3. .LC0:
  4.         .string "a = %p\n"
  5. .LC1:
  6.         .string "b = %p\n"
  7. .LC2:
  8.         .string "c = %p\n"
  9.         .text
  10.         .p2align 4,,15
  11.         .globl  func
  12.         .type   func, @function
  13. func:
  14. .LFB12:
  15.         .cfi_startproc
  16.         subl    $28, %esp
  17.         .cfi_def_cfa_offset 32
  18.         leal    32(%esp), %eax
  19.         movl    %eax, 4(%esp)
  20.         movl    $.LC0, (%esp)
  21.         call    printf
  22.         leal    36(%esp), %eax
  23.         movl    %eax, 4(%esp)
  24.         movl    $.LC1, (%esp)
  25.         call    printf
  26.         leal    40(%esp), %eax
  27.         movl    %eax, 4(%esp)
  28.         movl    $.LC2, (%esp)
  29.         call    printf
  30.         addl    $28, %esp
  31.         .cfi_def_cfa_offset 4
  32.         ret
  33.         .cfi_endproc
  34. .LFE12:
  35.         .size   func, .-func
  36.         .section        .rodata.str1.1
  37. .LC3:
  38.         .string "hello world"
  39.         .section        .text.startup,"ax",@progbits
  40.         .p2align 4,,15
  41.         .globl  main
  42.         .type   main, @function
  43. main:
  44. .LFB11:
  45.         .cfi_startproc
  46.         pushl   %ebp
  47.         .cfi_def_cfa_offset 8
  48.         .cfi_offset 5, -8
  49.         movl    %esp, %ebp
  50.         .cfi_def_cfa_register 5
  51.         andl    $-16, %esp
  52.         subl    $16, %esp
  53.         movl    $.LC3, 8(%esp)
  54.         movl    $99999, 4(%esp)
  55.         movl    $18, (%esp)
  56.         call    func
  57.         xorl    %eax, %eax
  58.         leave
  59.         .cfi_restore 5
  60.         .cfi_def_cfa 4, 4
  61.         ret
  62.         .cfi_endproc
  63. .LFE11:
  64.         .size   main, .-main
  65.         .ident  "GCC: (SUSE Linux) 4.7.1 20120723 [gcc-4_7-branch revision 189773]"
  66.         .section        .comment.SUSE.OPTs,"MS",@progbits,1
  67.         .string "Ospwg"
  68.         .section        .note.GNU-stack,"",@progbits
复制代码

论坛徽章:
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
30 [报告]
发表于 2013-01-28 16:58 |只看该作者
附个链接:wikipedia的页面,最后的列表列出了x86下各个编译器/系统以及32/64位下遵循的ABI规范。
http://en.wikipedia.org/wiki/X86_calling_conventions

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

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP