函数的调用

本文详细介绍了栈在计算机科学中的作用,特别是其在函数调用中的应用。栈遵循后进先出(LIFO)原则,其顶部用于元素的插入和删除。栈帧,即过程活动记录,是编译器用于管理函数调用的数据结构,包括局部变量、参数和返回地址。在函数调用过程中,EBP和ESP寄存器用于划定栈帧范围。同时,文章提到了不同的调用约定,如cdecl、stdcall、fastcall等,它们规定了参数传递和返回方式。
摘要由CSDN通过智能技术生成

Coception:
栈:堆栈(stack)又称为栈或堆叠,是计算机科学里最重要且最基础的数据结构之一,它按照FILO(First In Last Out,后进先出)的原则存储数据。
栈顶:元素插入(压栈PUSH,减4或8)和删除(出栈POP,加4或8)的地方。栈底:另一端。
从技术上说,栈就是CPU寄存器里的某个指针所指向的一片内存区域。这里所说的“某个指针”通常位于x86/x64平台的ESP寄存器/RSP寄存器,以及ARM平台的SP寄存器。作用如下, 暂时保存函数内的局部变量。调用函数时传递参数。保存函数返回的地址。
栈帧也叫过程活动记录,是编译器用来实现过程/函数调用的一种数据结构。简言之,栈帧就是利用EBP(栈帧指针,请注意不是ESP)寄存器访问局部变量、参数、函数返回地址等的手段。

;栈帧结构
PUSH EBP			;函数开始(使用EBP前先把已有值保存到栈中)
MOV EBP, ESP		;保存当前ESP到EBP中

...					;函数体
					;无论ESP值如何变化,EBP都保持不变,可以安全访问函数的局部变量、参数
					
MOV ESP, EBP		;将函数的起始地址返回到ESP中
POP EBP				;函数返回前弹出保存在栈中的值
RETN				;函数终止

每一次函数的调用,都会在调用栈(call stack)上维护一个独立的栈帧(stack frame)。每个独立的栈帧一般包括:

  • 函数的返回地址和参数
  • 临时变量:包括函数的非静态局部变量以及编译器自动生成的其他临时变量
  • 函数调用的上下文

栈是从高地址向低地址延伸,一个函数的栈帧用EBP和ESP这两个寄存器来划定范围。EBP指向当前栈帧的底部,ESP始终指向栈帧的顶部。

EBP寄存器又被称为帧指针(Frame Pointer)

ESP寄存器又被称为栈指针(Stack Pointer)

经典代码如下:

#include <stdio.h>

int foo(int x, int y)
{
        int z;
        z = x + y;
        return z;
}

int main(int argc, char* argv[])
{
        int a;
        a = foo(5, 6);
        printf("a = %d", a);
}

main函数调用了foo函数,所以main函数又称调用函数(caller),foo函数又被称为被调用函数(callee)。C使用的调用惯例是cdec1。

Tips: 常用调用惯例

调用惯例出栈方参数传递名字修饰
cdecl函数调用方从右至左的顺序压参数入栈下划线+函数名
stdcall函数本身从右至左的顺序压参数入栈下划线+函数名+@+参数的字节数,如函数int func(int a,double b)的修饰名是_func@12
fastcall函数本身头两个DWORD(4字节)类型或者占更少字节的参数被放入寄存器,其他剩下的参数按从右到左的顺序压入栈@+函数名+@+参数的字节数
pascal函数本身从左至右的顺序压参数入栈较为复杂,参加pascal文档

先y后z,push eip(保存返回地址)
=>保存调用函数的ebp(也就是caller的基地址),然后将ebp寄存器的值更新为当前的栈顶的地址(也就是ebp被更新为callee的基地址)。接下来通过sub指令来抬高栈顶,为了保存寄存器和局部变量。然后通过ebp+偏移的方式将参数保存到寄存器中,然后进行相加,将结果保存到eax寄存器中,在32位程序中,返回值是放在eax寄存器里的。

最后ret,第一步pop 返回地址,第二步jmp 返回地址。

函数具体的调用过程就是利用栈帧保存临时变量(保存返回地址)和返回地址(跳转函数)。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值