C++: How is the process of function calling in C++

Following images are from http://www.xuebuyuan.com/528715.html

In general, the process of calling function is put the parameters into the stack, move the EBP and ESP (jump into another function), protect the information of father function, restore the information of father function. (参数入栈、函数跳转、保护现场、回复现场)

There are three special pointer in compiler: EIP(Instruction pointer)是指令指针,point to the address of next instrction (即指向下一条即将执行的指令的地址);EBP (bottom pointer) 为基址指针,point to the bottom of stack 常用来指向栈底;ESP (stack pointer) 为栈指针,point to the top of stack 常用来指向栈顶.

For example, here is the code:

First, we are at the main function. Every function has its EBX (basic register),ESI,EDI (destination register)分别为基址寄存器,源变址寄存器,目的变址寄存器. They are some important information of a particular function. When we call the g_func, we firstly need to transport the
parameters into it. As I mentioned in my C++ note, when we are using the transportation of value, we will create copies of the parameters for the function. Therefore, here is the first step: put the parameters into the function stack.

三条push指令,分别将三个参数压入栈中,可以发现参数的压栈顺序是从右向左的。这时我们可以查看栈中的数据验证一下。如图3所示,从右边的实时寄存器表中我们可以看到ESP(栈顶指针)值为0x0012FEF0,然后从中间的内存表中找到内存地址0x0012FEF0处,我们可以看到内存中依次存储了0x00000001(即参数1),0x00000002(即参数2),0x00000003(即参数3),即此时栈顶存储的是三个参数值,说明压栈成功。

If we translate the code into instructions, we will get:

We firstly push three parameters into stack. Then we call a instruction at the address of  00401005. Following this address, we can see this:

We can see this is a jump instruction at the instruction address of 00401005. It jumps to 00401030. That is the begin instruction address of g_func.

Until now, we see how the instructions like before entering the instructions of function. Firstly push the parameters into stack, then use a call instruction to a jump instruction to jump to the actual instruction address of the function. So, until now,
the stack is like above. It has three parameters in it now.

Now, we turn to protect information before really entering function.

This step consists of three actual movement:

1)第一步的隐含的,并没有显式的指令去指挥其完成。就是将之前的call 指令之后EIP地址(main 函数的下一个指令的地址)压进去栈中。在这个例子中,call之后则为add。地址是00401093.

2) ebp is the original bottom pointer of the main function. 变了函数的话,栈底都是要变化的。我们要保存之前的函数的栈底地址,作为保护现场的第一步. 所以第二步就是将之前的函数的EBP压进栈中。

下一条mov ebp, esp 将此时的栈顶地址作为该函数的栈基址,确定g_func函数的栈区域(ebp为栈底,esp为栈顶)。再往下的指令是sub esp, 48h,指令的字面意思是将栈顶指针往上移动48h Byte。那为什么要移动呢?这中间的内存区域用来做什么呢?这个区域为间隔空间,将两个函数的栈区域隔开一段距离,如图7所示。而该间隔区域的大小固定为40h,即64Byte,然后还要预留出存储局部变量的内存区域。g_func函数有两个局部变量x和y,所以esp需移动的长度为40h+8=48h。

注意,存放局部变量的区域是64Bytes另外移出来的。并不会占用64Byte的空间。确保至少函数的栈空间之间至少有64Bytes的间隔。

移动之后的栈空间分布如图:

3) 将之前提到的EBX (basic register),ESI,EDI (destination register)分别为基址寄存器,源变址寄存器,目的变址寄存器压进去当前ESP的上面的地址。作为保存现场的第三步。

此时我们可以知道,栈内存是这样的:

The following content is talking about how to restore the information, I just directly copied form http://www.xuebuyuan.com/528715.html

时间: 2024-10-06 01:37:01

C++: How is the process of function calling in C++的相关文章

PatentTips – Java native function calling

BACKGROUND OF INVENTION This invention relates to a system and method for providing a native function call facility. In particular it relates to a system and method for providing a native function call facility in a Java Virtual Machine (JVM) for pla

function calling convention

这是2013年写的一篇旧文,放在gegahost.net上面 http://raison.gegahost.net/?p=31 February 19, 2013 function calling convention Filed under: c++ — Tags: C convention, C optimization, multi-thread — Raison @ 4:29 am (original works by Peixu Zhu) Function calling conven

Java JVM、JNI、Native Function Interface、Create New Process Native Function API Analysis

目录 1. JAVA JVM 2. Java JNI: Java Native Interface 3. Java Create New Process Native Function API Analysis In Linux 4. Java Create New Process Native Function API Analysis In Windows 1. JAVA JVM 0x1: JVM架构简介 JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种

UNIX高级环境编程(9)进程控制(Process Control)- fork,vfork,僵尸进程,wait和waitpid

本章包含内容有: 创建新进程 程序执行(program execution) 进程终止(process termination) 进程的各种ID ? 1 进程标识符(Process Identifiers) 每个进程都有一个唯一的标识符,进程ID(process ID). 进程的ID是可重用的,如果一个进程被终止,那么它的进程ID会被系统回收,但是会延迟使用,防止该进程ID标识的新进程被误认为是以前的进程. 三个特殊ID的进程: Process ID 0:调度者进程,内核进程. Process

NodeJS入门(五)—— process对象

process对象用于处理与当前进程相关的事情,它是一个全局对象,可以在任何地方直接访问到它而无需引入额外模块. 它是 EventEmitter 的一个实例. 本章的示例可以从我的Github上下载到(敏感时期GFW发大招,git暂时传不了,等多几天风头过了再试着上传). 事件'exit' 当进程将要退出时触发.这是一个在固定时间检查模块状态(如单元测试)的好时机.需要注意的是 'exit' 的回调结束后,主事件循环将不再运行,所以计时器也会失效: process.on('exit', func

Node.js 使用process.nextTick

今天发现Node.js文档很好地解释了如何使用process.nextTick. Node.js文档链接 http://nodejs.org/api/process.html#process_process_nexttick_callback process.nextTick(function callback(){ }); Node.js确保callback会在处理下一个事件前被调用. 下面是Node.js文档的翻译: process.nextTick(callback) 在下一个事件循环中调

Node.js学习笔记:setImmediate与process.nextTick

通过process.nextTick注册的函数在当前这个事件循环中执行的函数执行完毕后立即执行,相当于把当前的同步代码执行完毕之后,立刻执行所有的通过process.nextTick注册的函数,如果注册的是多个,那么注册的函数会依次按顺序执行完毕:通过setImmediate注册的函数在下一个事件循环中执行,如果有多个,那么回依次执行. 1 'use strict'; 2 const process=require('process'); 3 4 process.nextTick(functio

Node.js API —— process(进程)

// 说明 Node API 版本为 v0.10.31.    中文参考:http://nodeapi.ucdok.com/#/api/,http://blog.sina.com.cn/oleoneoy 本段为博主注解. 目录 ● 进程    ○ Event: 'exit'    ○ Event: 'uncaughtException'    ○ Signal Events    ○ process.stdout    ○ process.stderr ○ process.stdin ○ pro

比较setImmediate(func),setTimeout(func),process.nextTick(func)

node中的事件优先级机制: console.log('第一笔!'); process.nextTick(function() { console.log('吃个饭吧!'); setImmediata(function() { console.log('洗个头发1!'); }); }); setImmediata(function() { console.log('洗个头发2!'); }); console.log('第二笔!'); console.log('第三笔!'); 那么执行的步骤就是