免费注册 查看新帖 |

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
31 [报告]
发表于 2013-01-28 17:05 |只看该作者
本帖最后由 zylthinking 于 2013-01-28 17:09 编辑
zhaohongjian000 发表于 2013-01-28 16:56
我以为我们讨论的是64位的情况。如果是32位,gcc遵循的调用约定不是我给出的那个,而是你们说的cdecl。 ...


对, 调用约定是没有打破, 但就我的反汇编代码, 不打破约定不意味着 C 代码可以预测他所看到的参数地址的大小关系, 这让人很窝火;
cdecl 似乎也不意味着不允许寄存器传参, 我算是知道了

论坛徽章:
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
32 [报告]
发表于 2013-01-28 17:16 |只看该作者
zylthinking 发表于 2013-01-28 17:05
对, 调用约定是没有打破, 但就我的反汇编代码, 不打破约定不意味着 C 代码可以预测他所看到的参数地 ...


cdecl是通过栈传递参数的,我用-m32看到的汇编也是这样,但x86-64下gcc的调用约定不是cdecl,而是AMD制定的单独的规范。

论坛徽章:
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
33 [报告]
发表于 2013-01-28 17:33 |只看该作者
本帖最后由 zylthinking 于 2013-01-28 17:36 编辑
zhaohongjian000 发表于 2013-01-28 17:16
cdecl是通过栈传递参数的,我用-m32看到的汇编也是这样,但x86-64下gcc的调用约定不是cdecl,而是AMD制 ...


考虑考虑 arm 上的 cdecl
因此. cdecl 不是 ABI, 但你不能说 arm 上的 c 就不是 cdecl 了

论坛徽章:
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
34 [报告]
发表于 2013-01-28 17:42 |只看该作者
本帖最后由 zhaohongjian000 于 2013-01-28 17:44 编辑
zylthinking 发表于 2013-01-28 17:33
考虑考虑 arm 上的 cdecl
因此. cdecl 不是 ABI, 但你不能说 arm 上的 c 就不是 cdecl 了


哦,原来你认为调用约定就是cdecl啊,cdecl只是一种调用约定而已,ARM上的调用是遵循官方的AAPCS文档,显然不是cdecl。

重新表述一下:
1.调用约定是ABI规范的一部分。
2.cdecl是一种调用约定,用于IA32
3.x86-64遵循AMD制定的System V AMD64 ABI
4.ARM上的eabi定义在AAPCS文档中,oabi淘汰掉了,我没了解过。

论坛徽章:
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
35 [报告]
发表于 2013-01-28 17:44 |只看该作者
查了查, 至少 c standard 里面没有 cdecl 或者 stdcall 这些字眼, 因此这些应该是编译器概念;
那么, 很显然, 编译器只能在遵循 ABI 的基础上做自己的 cdecl 或者 stdcall, fastcall, xxxxcall 语意;

所以, 问题应该明确了,  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
36 [报告]
发表于 2013-01-28 17:46 |只看该作者
zhaohongjian000 发表于 2013-01-28 17:42
哦,原来你认为调用约定就是cdecl啊,cdecl只是一种调用约定而已,ARM上的调用是遵循官方的AAPCS文档, ...


那你解释解释
static void __cdecl mp4_parse(char* mp4, int len)
{
    static int n = 0;
    ++n;
    char file2[524];
    sprintf(file2, "%s%d.snap", file, n);

    printf("%d bytes in %s\n", len, file2);
    FILE* f = fopen(file2, "wb");
    fwrite(mp4, 1, len, f);
    fclose(f);
}
这个算什么, arm 上的代码, 通过编译无警告, 你说他就是一个 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
37 [报告]
发表于 2013-01-28 17:47 |只看该作者
zylthinking 发表于 2013-01-28 17:44
查了查, 至少 c standard 里面没有 cdecl 或者 stdcall 这些字眼, 因此这些应该是编译器概念;
那么, 很 ...


你理解错cdecl了,cdecl只是一种调用约定,并不是C的调用约定就是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
38 [报告]
发表于 2013-01-28 17:54 |只看该作者
本帖最后由 zylthinking 于 2013-01-28 17:57 编辑
zhaohongjian000 发表于 2013-01-28 17:47
你理解错cdecl了,cdecl只是一种调用约定,并不是C的调用约定就是cdecl。不解释,你自己查查看吧,吃饭 ...


我不知道它是一种??? 至少看到上面列出 stdcall 之类的字眼时, 你也该动动脑子。
如果 arm eabi 和 cdecl 是地位相同的实体, 那么, 上面列出的代码则:
1, 要么支持 cdecl, 不理 eabi 规定前四个参数通过 r0-r3, 所有参数通过栈传递
2, 要么报错, 表明不支持 cdecl, 好吧, 说荒唐些, cdecl ABI, 是你认为他们地位相同的, 那么我叫他 cdecl ABI 可以吗?

你让通过编译的那段代码如何自处?

论坛徽章:
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
39 [报告]
发表于 2013-01-28 18:35 |只看该作者
zylthinking 发表于 2013-01-28 17:54
我不知道它是一种??? 至少看到上面列出 stdcall 之类的字眼时, 你也该动动脑子。
如果 arm eabi 和 ...


该动脑子的是你。

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

cdecl
On the Intel 386, the cdecl attribute causes the compiler to assume that the calling function will pop off the stack space used to pass arguments. This is useful to override the effects of the -mrtd switch.

如果这样:
  1. static void  __attribute__((cdecl)) mp4_parse(char* mp4, int len)
  2. {
  3. }
复制代码
用linaro gcc for arm编译,会有一个警告:
  1. cdecl.c:2:1: 警告:‘cdecl’属性指定被忽略 [-Wattributes]
复制代码
直接在函数前面加__cdecl是会报错的。我假定你用的编译器是gcc,可是armcc我也试过也无法通过。唯一的解释就是,__cdecl是个宏,你应该检查一下。

论坛徽章:
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
40 [报告]
发表于 2013-01-28 18:55 |只看该作者
大体看了看gcc的实现,attribute的处理通过一个attribute_spec的结构体来进行,这个结构中会定义attribute的信息,并有一个回调函数。

各个gcc支持的体系结构会定义一个attribute_spec的数组,包含了该体系结构支持的特定的attribute。

和我想的一样,arm的attribute_spec定义在gcc/config/arm/arm.c约280行左右,其中并没有对cdecl的处理;
相应的,i386的定义在gcc/config/i386/i386.c约35389,包含了对cdecl的处理。

实际上,grep源代码就可以发现,基本上只有i386对这个属性进行了处理。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP