免费注册 查看新帖 |

Chinaunix

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

[C] Linux下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
41 [报告]
发表于 2013-01-28 19:07 |只看该作者
zhaohongjian000 发表于 2013-01-28 18:35
该动脑子的是你。

首先,gcc的手册中说的很清楚:


Ok, 没什么可争的了, 现在其实都明白是怎么回事, 你不过是想让 cdecl 更加重要化, 所有 cdecl 的都必须是某个特定的行为; 而我认为 cdecl 是编译器随意玩弄的花样, 不同的编译器可以赋给 cdecl 不同的语意; 虽然在更多些编译器可能是按照你的来的, 但不是说所有的都是, 我用的是 llv, __cdecl 不是宏, 只是一个应该被编译器忽略的 token, 但也未必不能说 llvm 就是修改了cdecl 的经典语意。

要争下去, 除非你能证明 llvm 处理 cdecl 就是一个 bug, 否则无论你怎么说, 只要我找到一个反例, 你就不占理, 而我找到了这么一个例子

论坛徽章:
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
42 [报告]
发表于 2013-01-28 19:34 |只看该作者
zylthinking 发表于 2013-01-28 19:07
Ok, 没什么可争的了, 现在其实都明白是怎么回事, 你不过是想让 cdecl 更加重要化, 所有 cdecl 的都必 ...


你当然可以认为cdecl是你想的那个样子,本来也没有什么标准,但就约定俗成的说法,cdecl就意味着通过stack传参。

你说你举出反例就ok了?呵呵,那只不过能说明某个编译器的cdecl不是通常所说的cdecl,只是名字相同而已。

另外,我尝试了一下x86-64的clang,指定__cdecl之后确实参数都是通过栈传递的。手头没有llvm/clang的代码,懒得找了。你动脑子想想,如果clang在ARM支持cdecl,有什么理由修改cdecl的语义?

论坛徽章:
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
43 [报告]
发表于 2013-01-28 19:48 |只看该作者
对, 我认为找到一个反例就足够了。 原来是名字相同的不一样的东西, 你的理由找的够无敌的。 约定俗成是你在同意说cdecl 语意可变吗? clang x64 的例子是在帮我反驳名字相同不一样东西论吗? 你很友好嘛。

论坛徽章:
24
金牛座
日期:2013-10-18 21:35:56综合交流区版块每日发帖之星
日期:2015-08-15 06:20:00综合交流区版块每日发帖之星
日期:2015-09-30 06:20:00综合交流区版块每日发帖之星
日期:2015-10-16 06:20:03每日论坛发贴之星
日期:2015-10-16 06:20:03综合交流区版块每日发帖之星
日期:2015-10-24 06:20:00IT运维版块每日发帖之星
日期:2016-01-06 06:20:0015-16赛季CBA联赛之天津
日期:2016-02-25 16:28:04综合交流区版块每日发帖之星
日期:2016-06-12 06:20:00每日论坛发贴之星
日期:2016-06-12 06:20:00综合交流区版块每日发帖之星
日期:2016-06-13 06:20:00综合交流区版块每日发帖之星
日期:2015-06-22 22:20:00
44 [报告]
发表于 2013-01-28 20:42 |只看该作者
这么简单的问题都能扯那么远,真服了你们!
01.a = 0x7fff743ce50c
02.b = 0x7fff743ce500
03.c = 0x7fff743ce4f8

很好解释吧?
E4F8~E4FF=c
E500~E507=b
E508~E50B=无用
E50C~E50F=a
LZ是64位机,字长64,简单类型的变量在栈中的长度都是8字节。
a是int,占4字节,所以前4字节空闲不用。
明白了?

论坛徽章:
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
45 [报告]
发表于 2013-01-28 22:00 |只看该作者
zylthinking 发表于 2013-01-28 19:48
对, 我认为找到一个反例就足够了。 原来是名字相同的不一样的东西, 你的理由找的够无敌的。 约定俗成是你 ...

噗,你是故意曲解还是理解不了呢?

什么是cdecl?就是通过栈传递参数的调用约定。clang/llvm在x86-64上生成的代码违反这个了吗?没有,汇编显示加了cdecl之后就改用栈传递了。虽然不知道llvm支持x86-64能够生成cdecl调用的代码是处于什么考虑,但在x86-64下显然很少用到这个。

我再重复一遍,防止你理解不了:cdecl的特点就是参数通过栈传递,无论是wiki上写的,手册上写的,以及gcc实现的都是如此。如果你愿意把一个通过寄存器传递参数的调用约定称为cdecl,那谁也拦不住你。但如果你觉得只要有一个编译器实现了一个用寄存器传递参数的调用约定并称之为cdecl,就认为cdecl得重新定义,那未免太可笑了。

论坛徽章:
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
46 [报告]
发表于 2013-01-28 22:32 |只看该作者
回复 44# 一介村夫

楼上的意思是,C在寻址时采取了内存对齐,64位系统的默认对齐模数是8,也就是以8字节为边界,对吗?
如果是这样的话,楼上怎么又说a存储空间的前4个字节不用呢?另外b的地址与a的地址之间的空隙是12字节,而不是以8字节为边界
还有,楼上是怎样确定存储空间之间的空隙在存储对象之前或之后呢,也就是前n或后n个字节不用?

可能是我理解有误,请指教,谢谢!
   

论坛徽章:
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
47 [报告]
发表于 2013-01-28 22:54 来自手机 |只看该作者
你当然是对的, cdecl 必须通过栈传递, 通过寄存器传的, 就算叫cdecl 也不是cdecl, 我还有什么话说。 手册, wiki? 你必须首先找出一个标准化定义而不是几个编译器互相兼容的支持, 然后找到一个编译器声明自己遵守这个权威定义的条款, 然后才能数cdecl 是申请了商标权的, 才能对别人提供cdecl 认证。 要说互相支持的情况, c++ 函数名修饰方案记得哪个语言也同样遵守来的, 倒也没听说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
48 [报告]
发表于 2013-01-28 23:25 来自手机 |只看该作者
关键问题不在哪个行为是名门正派哪个是邪教, 而是编译器在满足自己声明的各种约束的基础上, 能不能自由的定义一些调用约定, 以及cdecl 是不是编译器官方声明支持的标准问题, 如果存在标准条文规定什么是cdecl 那有编译器 实现不一致语意当然是他的bug, 但若没有, 没错, 各个cdecl 都是叫cdecl 而实际上不一样的东西, 而不仅仅是不合群的cdecl 才是不一样的东西, 拉帮结派的就是一样的东西了。 很显然, thiscall 就是微软自由加到自己编译器里面的调用约定, 既然能够自由定义新的约定, 为何不能修改已有的约定, 在该约定没有权威定义情况下, 等什么时候 gcc 也弄出一个不同与微软的但也叫thiscall 的出来, 微软是不是也该声称 gcc 的是 bug?

论坛徽章:
24
金牛座
日期:2013-10-18 21:35:56综合交流区版块每日发帖之星
日期:2015-08-15 06:20:00综合交流区版块每日发帖之星
日期:2015-09-30 06:20:00综合交流区版块每日发帖之星
日期:2015-10-16 06:20:03每日论坛发贴之星
日期:2015-10-16 06:20:03综合交流区版块每日发帖之星
日期:2015-10-24 06:20:00IT运维版块每日发帖之星
日期:2016-01-06 06:20:0015-16赛季CBA联赛之天津
日期:2016-02-25 16:28:04综合交流区版块每日发帖之星
日期:2016-06-12 06:20:00每日论坛发贴之星
日期:2016-06-12 06:20:00综合交流区版块每日发帖之星
日期:2016-06-13 06:20:00综合交流区版块每日发帖之星
日期:2015-06-22 22:20:00
49 [报告]
发表于 2013-01-29 07:19 |只看该作者
superwujc 发表于 2013-01-28 22:32
回复 44# 一介村夫

楼上的意思是,C在寻址时采取了内存对齐,64位系统的默认对齐模数是8,也就是以8字节 ...

LZ这是语文不好还是算数不好?
我觉得我写得够明白的了,数据也列得够充分了,语文不好的,可以用算数加加减减,算数不好的可以仔细理解字面意思,两样都不好的我实在没招。

论坛徽章:
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
50 [报告]
发表于 2013-01-29 09:11 |只看该作者
zylthinking 发表于 2013-01-28 22:54
你当然是对的, cdecl 必须通过栈传递, 通过寄存器传的, 就算叫cdecl 也不是cdecl, 我还有什么话说。 手册 ...


既然讨论到耍赖的地步,也就没必要再讨论了。你可以前后看看你的发言,动动脑子(你在前面都没弄清什么是cdecl)。

ARM上clang的情况,无非3种:
1.clang在ARM上接受cdecl属性,生成了使用栈传参的代码。这一点无需多说,但ARM上通行的abi仍然是eabi,调用约定也是eabi规定的,只能说有个编译器在ARM上实现了cdecl。
eabi的调用约定和cdecl是不同的两种调用约定。
2.cdecl被忽略,生成了和以前一样的代码。
3.cdecl被接受,生成了既非eabi,也非cdecl的东西,但是在clang中仍然叫做cdecl。
你认为这样的话就能证明cdecl不是一定通过栈传参的,我只能笑而不语。
另外,这种情况下我会认为clang/llvm的设计明显有毛病,好像是故意要配合你跟我抬杠似的。

基本上说清楚了,理解不了或者还要耍赖是你自己的事了,不陪你玩了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP