您的位置:首页 > 其它

INTEL汇编的函数调用过程

2010-10-30 11:15 585 查看
汇编调用函数的过程



push arg2 func: push %ebp 保存caller的栈顶

push arg1 mov %esp,%ebp ebp保存callee的新栈顶

push arg0 保存用到的寄存器值

eip-->call func 递减esp创建局部变量

递增esp销毁局部变量

恢复用到的寄存器值

mov %ebp,%esp 恢复callee的栈顶

pop %ebp 从callee的栈顶弹出caller的栈顶

ret n 弹出函数的返回地址(n可以用来销毁传递参数所占用的字节)



函数调用后栈中的内容



高地址 arg2

arg1

arg0

函数的返回地址【call后面的指令地址】

低地址 ebp--->caller的栈基地地址





















1) EBP是栈基址的指针,永远指向栈底(高地址),ESP是栈指针,永远指向栈顶(低地址)。

2) CALL指令用来调用一个函数或过程,此时,下一条指令地址会被压入堆栈,以备返回时能恢复执行下条指令。

3) RET指令用来从一个函数或过程返回,之前CALL保存的下条指令地址会从栈内弹出到EIP寄存器中,程序转到CALL之前下条指令处执行

4) ENTER是建立当前函数的栈框架,即相当于以下两条指令:
pushl %ebp
movl %esp,%ebp



5) LE***E是释放当前函数或者过程的栈框架,即相当于以下两条指令:
movl %ebp,%esp
popl %ebp

关于WINDOWS的C函数调用



__cdecl 最大好处在于由于是调用者清理栈【清理压入栈中的函数参数】,它可以处理可变参数,缺点则在于它增加了程序的大小,因为在每个调用返回的时候,需要多执行一条清理栈的指令。
  

__stdcall 是在windows程序设计中出现的最多的调用规则,所有的不可变参数的API调用都使用这个规则【由callee清除压入栈中的函数参数】。
  



__fastcall 在windows内核设计中被广泛的使用,由于两个参数由寄存器直接传递,采用这种规则的函数效率要比以上两种规则高【由callee清除压入栈中的函数参数】。

Int __cdecl func(void* p);

Push p
Call func
Add esp,4 //注意这里,由于是cdecl调用,需要调用者清栈。

Int __stdcall func(void* p);

Push p
Call func    //由被调用者清除栈



linux系统调用



Linux会有6个寄存器使用来传递这些参数:eax (存放系统调用号)、 ebx、ecx、edx、esi及edi来存放这些额外的参数
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: