想了解浅谈C语言函数调用参数压栈的相关问题的相关内容吗,在本文为您仔细讲解函数调用压栈的相关知识和一些Code实例,欢迎阅读和指正,我们先划重点:函数调用压栈,下面大家一起来学习吧。

参数入栈的顺序

以前在面试中被人问到这样的问题,函数调用的时候,参数入栈的顺序是从左向右,还是从右向左。参数的入栈顺序主要看调用方式,一般来说,__cdecl 和__stdcall 都是参数从右到左入栈。

看下面的代码:

#include

int test(int a, int b)

{

printf("address of a %x.\n", &a);

printf("address of b %x.\n", &b);

return 0;

}

int main()

{

test(1, 2);

return 0;

}

在64位Ubuntu的系统下的运行结果是:

address of a 1ec62c.

address of b 1ec628.

32位Ubuntu的结果是:

address of a bfd03290.

address of b bfd03294.

可以看出,首先,不同的体系结构,栈增长的方向也不同,有的是从低地址向高地址方向增长,有的是从高地址向低地址方向增长。

可以用以下的代码来判断栈的增长方向:

typedef enum {

LOW_TO_HIGH,

HIGH_TO_LOW,

LEFT_TO_RIGHT,

RIGHT_TO_LEFT,

}stack_direc_t;

int stack_grow_direc()

{

static char *p = NULL;

char c;

if (p == NULL) {

p = &c;

stack_grow_direc();

}

else {

printf("First in stack address is %x.\n", p);

printf("Second in stack address is %x.\n", &c);

if (&c > p) {

printf("Stack grows from low address to high address!\n");

return LOW_TO_HIGH;

}

else {

printf("Stack grows from high address to low address!\n");

return HIGH_TO_LOW;

}

}

}

函数调用时栈里都有什么

以参数从左到右入栈为例:

push arg0 -- High Address

push arg1

...

push argn

push eip

push ebp -- Low address

32位系统和64位系统函数调用时,参数入栈方式有不同么?

这个问题在不久之前被人问题,当时傻了,我一直以来只关注过32位系统的参数入栈方式,一直以为64位系统也是一样,没有什么不同,现在归纳起来有两点:

64位系统先把传入参数放在寄存器里面,在被调函数的具体实现中把寄存器的值入栈,然后再去栈中取参数

64位系统栈中参数存放的顺序是从左至右的(因为先经历了寄存器传值)

看下面的反汇编:

C代码同上面一样

Ubuntu 32位反汇编:

int main()

{

804846d: 55 push %ebp

804846e: 89 e5 mov %esp,%ebp

8048470: 83 e4 f0 and $0xfffffff0,%esp

8048473: 83 ec 10 sub $0x10,%esp

test(1, 2);

8048476: c7 44 24 04 02 00 00 movl $0x2,0x4(%esp)

804847d: 00

804847e: c7 04 24 01 00 00 00 movl $0x1,(%esp)

8048485: e8 8a ff ff ff call 8048414

return 0;

804848a: b8 00 00 00 00 mov $0x0,%eax

}

int test(int a, int b)

{

8048414: 55 push %ebp

8048415: 89 e5 mov %esp,%ebp

8048417: 83 ec 18 sub $0x18,%esp

printf("address of a %x.\n", &a);

804841a: b8 60 85 04 08 mov $0x8048560,%eax

804841f: 8d 55 08 lea 0x8(%ebp),%edx

8048422: 89 54 24 04 mov %edx,0x4(%esp)

8048426: 89 04 24 mov %eax,(%esp)

8048429: e8 12 ff ff ff call 8048340

return 0;

8048466: b8 00 00 00 00 mov $0x0,%eax

}

Ubuntu 64位反汇编:

int main()

{

40056e: 55 push %rbp

40056f: 48 89 e5 mov %rsp,%rbp

test(1, 2);

400572: be 02 00 00 00 mov $0x2,%esi

400577: bf 01 00 00 00 mov $0x1,%edi

40057c: e8 ac ff ff ff callq 40052d

return 0;

400581: b8 00 00 00 00 mov $0x0,%eax

}

int test(int a, int b)

{

40052d: 55 push %rbp

40052e: 48 89 e5 mov %rsp,%rbp

400531: 48 83 ec 10 sub $0x10,%rsp

400535: 89 7d fc mov %edi,-0x4(%rbp)

400538: 89 75 f8 mov %esi,-0x8(%rbp)

printf("address of a %x.\n", &a);

40053b: 48 8d 45 fc lea -0x4(%rbp),%rax

40053f: 48 89 c6 mov %rax,%rsi

400542: bf 14 06 40 00 mov $0x400614,%edi

400547: b8 00 00 00 00 mov $0x0,%eax

40054c: e8 bf fe ff ff callq 400410

return 0;

400567: b8 00 00 00 00 mov $0x0,%eax

}

看32位的ubuntu操作系统, 8048476: 的确是把参数直接入栈,2先入栈,1后入栈。

8048476: c7 44 24 04 02 00 00 movl $0x2,0x4(%esp)

804847d: 00

804847e: c7 04 24 01 00 00 00 movl $0x1,(%esp)

8048485: e8 8a ff ff ff call 8048414

再来看64位的ubuntu操作系统,2 和1根本就没有放入到栈中,而是放到了寄存器esi和edi中。

40056f: 48 89 e5 mov %rsp,%rbp

test(1, 2);

400572: be 02 00 00 00 mov $0x2,%esi

400577: bf 01 00 00 00 mov $0x1,%edi

40057c: e8 ac ff ff ff callq 40052d

再来看64位系统test的实现,先把edi入栈,再把esi入栈,这就是为什么函数看起来像是从左到右入栈的原因了。

40052d: 55 push %rbp

40052e: 48 89 e5 mov %rsp,%rbp

400531: 48 83 ec 10 sub $0x10,%rsp

400535: 89 7d fc mov %edi,-0x4(%rbp)

400538: 89 75 f8 mov %esi,-0x8(%rbp)

以上就是小编为大家带来的浅谈C语言函数调用参数压栈的相关问题的全部内容了,希望对大家有所帮助,多多支持~

相关文章

c语言函数参数压栈,函数调用压栈 浅谈C语言函数调用参数压栈的相关问题相关推荐

  1. c语言乐学编程作业答案,信息乐学|浅谈C语言

    原标题:信息乐学|浅谈C语言 一大波C语言的干货正在靠近 刚刚成为大学生的小萌新们,经过两个多月的学习,你们对大学的多彩生活是否还满意?全新的学习方式你们是否还适应?然而,新鲜劲还没过,第一件让你们头 ...

  2. c语言如何求一个数学表达式的值,浅谈C语言中表达式的求值

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 C语言研究性学习的路线 现行的多数C语言教材有太多的误区,不仅不能给读者提供有效的学习线索,还常常"误导"读者,于是,"死记 ...

  3. 自学c语言后的感受,一路走来,浅谈c语言的学习感想

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 #include #include #define PI 3.1415926 int main() { int a,b,c; float x1,x2,d, ...

  4. 分三种情况C语言编程,浅谈C语言教学的现状及几点建议.doc

    浅谈C语言教学的现状及几点建议 浅谈C语言教学的现状及几点建议 摘 要 针对C语言教学中存在的问题提出建议,以期对C语言教学有一定帮助. 关键词 C语言:课程设置:创新能力 中图分类号:G642 文献 ...

  5. c语言函数调用参数调用的太少,浅谈C语言函数调用参数压栈的相关问题

    参数入栈的顺序 以前在面试中被人问到这样的问题,函数调用的时候,参数入栈的顺序是从左向右,还是从右向左.参数的入栈顺序主要看调用方式,一般来说,__cdecl 和__stdcall 都是参数从右到左入 ...

  6. 浅谈C语言内存(栈)

    浅谈C语言内存 文章目录 浅谈C语言内存 内存分配 栈 斐波纳契数列 内存分配 在C语言中内存分别分为栈区(stack).堆区(heap).未初始化全局数据区.已初始化全局数据区.静态常量区(stat ...

  7. c语言弱符号与函数指针,浅谈C语言中的强符号、弱符号、强引用和弱引用【转】...

    首先我表示很悲剧,在看<程序员的自我修养--链接.装载与库>之前我竟不知道C有强符号.弱符号.强引用和弱引用.在看到3.5.5节弱符号和强符号时,我感觉有些困惑,所以写下此篇,希望能和同样 ...

  8. 基于c语言的递归算法分析论文,浅谈C语言递归算法.docx

    浅谈C语言递归算法 浅析C语言递归算法王浏江盐城师范学院 信息工程学院 计算机161班 摘要:递归算法,结构清晰,代码简练,函数调用灵活方便,比较容易理解和阅读.因此,递归算法一般用于多个相似小问题组 ...

  9. c语言 去掉双引号_技术分享|浅谈C语言陷阱和缺陷

    良好的软件架构.清晰的代码结构.掌握硬件.深入理解C语言是防错的要点,人的思维和经验积累对软件可靠性有很大影响.C语言诡异且有种种陷阱和缺陷,需要程序员多年历练才能达到较为完善的地步.软件的质量是由程 ...

最新文章

  1. web架构设计经验分享
  2. ubuntu使用root权限登录的设置方法
  3. 【POJ - 1751】Highways (最小生成树)
  4. 代码写成这样,老板把我开除了| IT 巨能唠
  5. python调用远程js_python和js交互调用的方法
  6. quick-cocos2d-x 游戏开发——StateMachine 状态机
  7. java中的saturn_Saturn分布式调度平台系列:高屋建瓴之设计原理简析
  8. Ruby on Rails -跑起来吧hello World!
  9. .NET中利用XML来自动生成代码策略
  10. 革新—决定磁带未来的最大挑战
  11. Android LeakCanary的使用和原理
  12. Linux字体库ttc还是ttf,几种操作系统字体格式:otf/ttf/ttc格式字体的区别
  13. mysql语句监控工具
  14. ASP.NET_各个币种之间的汇率转换(实时)使用Yahoo汇率。
  15. Linux常用命令英文全称与中文解释 (pwd、su、df、du等)
  16. C/C++ 延时函数 (标准库)
  17. JAVA程序员常用网址
  18. 基于Python和R的多元线性回归分析实例
  19. 实验十四 团队项目评审课程学习总结
  20. 苹果4s忘记id密码怎么办_iPhone忘记ID密码怎么办?不花钱,这波操作帮你轻松解决...

热门文章

  1. 河北正定县2010年政府工作报告(1)
  2. 今年的中秋(好惨啊)
  3. 第70课:Spark SQL内置函数解密与实战 每天晚上20:00YY频道现场授课频道68917580
  4. Python-音频补齐(即对不同长度的音频用数据零对齐补位)
  5. 数据科学家应该掌握的12种机器学习算法
  6. QTCN注册之一个小问题
  7. 红外海洋目标检测实践,基于目标检测模型识别红外海洋目标
  8. 微信小程序-生成保存图文海报-canvas生成图片、二维码、自定义文字样式
  9. m227只有一台计算机,惠普m227fdw单面打印如何设置_惠普m227fdw怎么设置单面打印-硬件之家...
  10. Word处理控件Aspose.Words功能演示:在 C# 中的 Word 文档 (DOCX/DOC) 中添加或删除水印