通过汇编程序看函数调用过程中的原理

本文通过C++源代码和汇编指令,深入解析函数调用过程中的参数传递、局部变量销毁和返回值返回机制。重点讨论了lea、call、ret等指令的作用,并展示了函数调用的五个关键环节:传参、保存上下文、向返回值空间写值、恢复上下文和从临时空间拷贝数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、C++ 源代码,本文所有汇编、函数堆栈数据情况都是根据以下源代码得到的

int Add(int x,int y)
{
	int sum;
	sum = x+y;
	return sum;
}

int main(int argc, char * argv[])
{
	int z;

	z = Add(1,2);
}



二、需要知道的基础知识:


1、X86 寄存器基础


    (1)ESP:栈顶指针,X86中的栈是向下增长,所以入站push时 esp--,出栈pop时,esp++

    (2)EBP:函数的参数和局部变量都是存储在程序栈中,所以当一个函数想要获取它自己的参数或者局部变量时,想到的第一个方案就是使用(ESP寄存器的值+栈偏移量)推算出参数和局部变量的地址。但是栈顶指针的值会随着程序入栈和出栈操作不断变化。所以为了计算方便,可以将该值保存到另一个寄存器---EBP(extended base pointer,扩展基址寄存器)。这样获取参数可以用:EBP+偏移量,获取局部变量就可以用  EBP-偏移量了。(下图中的数据是根据第一部分的代码得到的)

            

    (3)EBX ,基址寄存器,在内存中寻址时使用。

    (4)ESI/EDI,源/目的地址寄存器,暂时不清楚有什么用

    (5)ECX,(extended counter )计数器寄存器,和rep和loop指令搭配使用。主要用来进行循环计数

2、汇编指令基础

        (1)lea指令,格式:lea + 目的寄存器+源操作数,作用:将源操作数的地址偏移量保存到目的寄存器中。学习lea指令可以和mov指令一起来记,他们格式相同,但mov指令是将操作数指向的内存中的数据保存到目的寄存器。

       (2)call 指令,格式 :call + 目标地址,作用:将程序调转到目标地址处执行。

                 call 指令使用的是相对寻址,所谓的相对寻址就是:基址+偏移量 = 最终地址。在call指令中,基址就是call指令的下一条指令的起始地址。偏移量就是call指令中后4字节的内容。

                 call指令返回地址会在指令执行过程中被压到程序栈中。

                 等价指令:push EIP+5 ,jmp 目标地址

       (3)ret指令,作用:将栈顶保存的地址弹入EIP指令寄存器,这个过程ESP要增大(因为执行了一次出栈操作)

       (4)rep 指令,格式 rep+其他指令,作用:重复rep后面的其他指令,重复次数记录在ECX寄存器中,每次循环ECX寄存器执行减减操作。

       (5)stos指令,格式 stos+目的地址,将寄存器EAX中的内容保存到目的地址处。目的地址格式 ES:[EDI] ,ES保存了段选择符,EDI保存了段偏移量。如果设置了direction flag, 那么EDI会在该指令执行后减小, 如果没有设置direction flag, 那么EDI的值会增加, 为下一次的存储做准备

三、正文,使用汇编分析函数调用并返回过程中的原理


        1、main函数反汇编:

int main(int argc, char * argv[])
{
001D1A70 55               push        ebp  
001D1A71 8B EC            mov         ebp,esp 
001D1A73 81 EC CC 00 00 00 sub         esp,0CCh 
001D1A79 53               push        ebx  
001D1A7A 56               push        esi  
001D1A7B 57               push        edi  
001D1A7C 8D BD 34 FF FF FF lea         edi,[ebp+FFFFFF34h] 
001D1A82 B9 33 00 00 00   mov         ecx,33h 
001D1A87 B8 CC CC CC CC   mov         eax,0CCCCCCCCh 
001D1A8C F3
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值