C语言主函数中如何调用栈,C语言中函数调用过程(如何管理栈空间)

ps:先做草稿,以后有时间再整理并贴图,:)

主要是利用栈底寄存器(ebp)、栈顶寄存器(esp)跟eax寄存器(存储返回值)来实现。

假设P调用Q:

P()

{

Q(1,2);

}

1.调用前准备,将Q的参数放到栈中(非push)

mov $1, (%esp)

mov $2, 4(%esp)

2.调用call 0x12345678 (Q的地址)

首先将函数的返回地址(call语句后的那条指令的地址)进栈,

然后跳到0x12345678执行Q的代码。

3.将旧的ebp进栈(用于退出Q时还原)

push %ebp

4.设置新的栈底

mov %esp, %ebp

5.为Q分配栈空间(栈是向下生长的)

sub $24, %esp    (16 * k + 8,用于对齐)

6.执行Q的相关代码。局部变量/参数是根据esp、ebp跟偏移量来进行存取的。

7.函数离开前将返回值赋值给%eax。

8.调用leave,相当于:

mov %ebp, %esp (还原栈顶)

pop %ebp (还原栈底)

9.处理返回值并接着P接着的代码继续执行。

原文:http://www.cnblogs.com/runnyu/p/5894009.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言主函数(main函数)可以通过调用子函数来实现特定的功能。调用子函数的过程包括以下几个步骤: 1. 声明子函数的原型:在主函数的前面声明子函数的原型,以便主函数能够正确调用子函数。原型包括子函数的返回类型、函数名和参数列表。例如,如果子函数的原型为 `int add(int a, int b);`,则在主函数开始的地方加上 `int add(int, int);`。 2. 编写子函数:在主函数的后面编写子函数的定义。子函数的定义包括函数的返回类型、函数名和参数列表,以及具体的函数体。例如,定义一个加法函数 `int add(int a, int b) { return a + b; }`。 3. 在主函数调用子函数:在主函数调用子函数时,使用子函数的函数名加上实际的参数列表。例如,调用上述定义的加法函数可以写为 `int result = add(3, 4);`,该语句将返回加法函数的结果并赋值给变量 `result`。 4. 处理子函数的返回值:根据子函数的返回类型来确定如何处理返回值。如果子函数的返回类型是 `void`,则不需要对返回值进行处理;如果子函数的返回类型是其他类型,则可以将返回值赋给变量或者直接使用。 总之,通过在主函数声明子函数的原型,编写子函数的定义,然后在主函数调用子函数,我们可以实现主函数对子函数的调用。这样可以将程序的功能模块化,并更好地组织和管理代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值