免费注册 查看新帖 |

Chinaunix

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

[C] printf参数入栈顺序和编译器相关,还是都是从右至左? [复制链接]

论坛徽章:
0
71 [报告]
发表于 2007-11-02 13:33 |只看该作者
原帖由 zx_wing 于 2007-11-2 13:22 发表

对于变参函数的解析,都要通过一个参数解析出后面参数的个数才能正常取参,无法凭压栈的顺序或和栈有关的方法判断出一共传入了的多少参数。


不对的,而且根本不必理会一共传入了的多少参数。

如果入栈顺序设计正确,

1/ 就不必知道个数,得到第一个参数的位置就够了。
2/ 就不必考虑入栈顺序,stdarg的实现就能够用宏简单解决。

论坛徽章:
0
72 [报告]
发表于 2007-11-02 13:44 |只看该作者
第一个参数问题,编译随便做点暗处的小动作就可以了。

要保证后面参数ARGN的地址比ARG1高,目的是使LIB库什么也不用改动就可以直接使用(STDARG。H等)。

论坛徽章:
0
73 [报告]
发表于 2007-11-02 13:55 |只看该作者
原帖由 ccpaishi 于 2007-11-1 08:13 发表
__cdecl __stdcall __pascal __fastcall
这些类型的函数的参数是从左至右吗?

没看到是pascal调用方式么
pascal的经典标志就是从左到右
C的标志就是从右到左
但是既然这个声明是pascal调用方式了
那么就是从左到右的了

论坛徽章:
0
74 [报告]
发表于 2007-11-02 17:06 |只看该作者
原帖由 JohnBull 于 2007-11-2 13:33 发表


不对的,而且根本不必理会一共传入了的多少参数。

如果入栈顺序设计正确,

1/ 就不必知道个数,得到第一个参数的位置就够了。
2/ 就不必考虑入栈顺序,stdarg的实现就能够用宏简单解决。

所以说到底,还是要靠一个参数来解析其它参数,这就是版主这里说的第一个参数,而这个参数在printf里面就是fmt字符串。
前面那么多讨论都是在说基于x86的存参、取参方式,对于不同的入栈顺序,如何定位第一个参数(或者说就是那个关键的参数)。
问题绕了个圈又回到原点。

论坛徽章:
0
75 [报告]
发表于 2007-11-02 17:28 |只看该作者
持续关注~~~

论坛徽章:
0
76 [报告]
发表于 2007-11-02 17:32 |只看该作者
一个方法(真实的不一定如此)。
CALLER:
push arg1, 2, ...argN, push &arg1.
CALLEE:
pop(get) address arg1.

这种trick在X86的GCC中也有。比如函数返回了一个结构。

具体是怎么搞的,你找一个正方向STACK机器看一下就知道了。

论坛徽章:
0
77 [报告]
发表于 2007-11-02 17:38 |只看该作者
原帖由 思一克 于 2007-11-2 17:32 发表
一个方法(真实的不一定如此)。
CALLER:
push arg1, 2, ...argN, push &arg1.
CALLEE:
pop(get) address arg1.

这种trick在X86的GCC中也有。比如函数返回了一个结构。

具体是怎么搞的,你找一个正方 ...

没有意义的。我现在的机器就可以配成栈向上增长。
但有什么意义呢?前面的讨论基于x86的存参、取参方式,平台换了,参数传递方式不一样了,那就没什么讨论的意义了。
就像前面的的powerpc样,第一参数放在寄存器中,程序肯定能拿到,和我们讨论的就没有什么关系了。
实际我觉得这个问题讨论到这里已经差不多了,我想我明白你们的意思。

论坛徽章:
59
2015年亚洲杯之约旦
日期:2015-01-27 21:27:392015年亚洲杯之日本
日期:2015-02-06 22:09:41拜羊年徽章
日期:2015-03-03 16:15:432015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:50:282015元宵节徽章
日期:2015-03-06 15:50:392015年亚洲杯之阿联酋
日期:2015-03-19 17:39:302015年亚洲杯之中国
日期:2015-03-23 18:52:23巳蛇
日期:2014-12-14 22:44:03双子座
日期:2014-12-10 21:39:16处女座
日期:2014-12-02 08:03:17天蝎座
日期:2014-07-21 19:08:47
78 [报告]
发表于 2007-11-02 20:44 |只看该作者
这个问题大家也能讨论这么久,真是服了。

看一下《编译原理》吧。
BSP[1]为第一个参数,
BSP[2]为第二个参数(intel,下增长栈).

BSP[-1]为第一参数,
BSP[-2]为第二参数。
脑袋
为什么要这样实现,因为:


如果你的系统同时使用了ASM和C,那你就会知道,以上的设计会给你提供多少的方便。

同时,对于编译器的设计者来说,这样的设计也更加简单和有效!此外,这样的设计使得C语言能很好地支持可变参数。



不使用这样的设计,那么,脑袋一定... 如果你想结合ASM和支持可变参数的话。

论坛徽章:
0
79 [报告]
发表于 2007-11-02 21:09 |只看该作者
原帖由 folklore 于 2007-11-2 20:44 发表
这个问题大家也能讨论这么久,真是服了。

看一下《编译原理》吧。
BSP[1]为第一个参数,
BSP[2]为第二个参数(intel,下增长栈).

BSP[-1]为第一参数,
BSP[-2]为第二参数。
脑袋
为什么要这样实现,因 ...

呵呵,我倒认为上面的探讨非常有意义。
不要因为有了这样的实现就不去思考为什么没有其它的实现方式,通过对比思考,很多东西就可以了然于胸。
我反而认为这样的讨论还少了点。目前为止就看到三个,一是内核版从前的《linux中中断能不能睡眠》、一是这里的printf,一是最近内核版的《ISA中断能不能共享》。这些都是基于当前实现去讨论其它实现方式的帖子,我觉得从这样的讨论中受益良多。
个人意见,得罪勿怪

论坛徽章:
0
80 [报告]
发表于 2007-11-03 01:18 |只看该作者
原帖由 zx_wing 于 2007-10-31 22:10 发表

俺也想知道哪个编译器从左至右。
PS:并非printf是这个顺序,函数调用参数入栈都是这个顺序



是看你的调用方式,函数有几种调用方式啦..
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP