汇编之函数调用(CALL)分析
2012-02-20 10:46
218 查看
问题来源:
stdcall类型函数调用,参数倒序入栈,第一个参数最后入栈,函数内部访问第一个参数时经常看到用[ebp + $08]表示,ebp通常来自esp,即函数首部经常看到的push ebp, mov ebp, esp,为什么栈顶偏移$08才是第一个参数呢?按道理说第一个参数最后入栈,栈顶不应该就是第一个参数么?事实并非如此...
问题探索与解答:
函数1:
调用该函数,观察汇编代码:(注意EIP寄存器变化)
函数2:
调用该函数,观察汇编代码:(注意EIP寄存器变化及栈内栈顶到第一参数间的数值)
问题解答:
因此,在调用函数的时候,程序会偷偷的将执行CALL之后的下一条语句的地址压入栈中,同时呢,一般带有参数的程序,进入程序内部后会首先保存当时的EBP,这就造成了栈内多出两个数值,而这两个又都是在参数入栈之后发生的,因此第一个参数的地址就变成了[EBP+$08]。
明眼人也发现了,函数1返回时用的是ret直接返回,而函数2返回时是ret $0004, 这又是何意呢?原来ret时就自动把CALL之后的下一条语句的地址出栈了,后面的$0004意味着出栈后ESP这个栈顶指针要进行的偏移,因为你传进的这些参数在函数返回后它们就没必要存在栈里面了,所以移动下栈顶指针就可以。
ret $0004= ESP + $0004
stdcall类型函数调用,参数倒序入栈,第一个参数最后入栈,函数内部访问第一个参数时经常看到用[ebp + $08]表示,ebp通常来自esp,即函数首部经常看到的push ebp, mov ebp, esp,为什么栈顶偏移$08才是第一个参数呢?按道理说第一个参数最后入栈,栈顶不应该就是第一个参数么?事实并非如此...
问题探索与解答:
函数1:
function add:Integer;stdcall; begin Result :=10; end;
调用该函数,观察汇编代码:(注意EIP寄存器变化)
0044D944 E8F3FFFFFF call add ;此时EIP=0044D944 0044D949 C3 ret 跟进函数CALL Unit1.pas.27: Result :=10; 0044D93C B80A000000 mov eax,$0000000a 0044D941 C3 ret 此函数无参,跟进发现栈顶为 0044D949,这正是执行完CALL之后的下一句要执行的代码
函数2:
function add(a: Integer):Integer;stdcall; begin Result := a + 10; end;
调用该函数,观察汇编代码:(注意EIP寄存器变化及栈内栈顶到第一参数间的数值)
Unit1.pas.45: s := add(12); 0044D94C 6A0C push $0c 0044D94E E8E9FFFFFF call add ;此时EIP=0044D94E,跟进 0044D953 C3 ret 跟进CALL Unit1.pas.31: begin 0044D93C 55 push ebp 0044D93D 8BEC mov ebp,esp Unit1.pas.32: Result := a + 10; 0044D93F 8B4508 mov eax,[ebp+$08];执行到此行,观察 0044D942 83C00A add eax,$0a Unit1.pas.33: end; 0044D945 5D pop ebp 0044D946 C20400 ret $0004 栈顶是push ebp保存进EBP当时的值,结束前恢复现场用 [ebp+$08]是访问的第一个参数 那[ebp+$04]是何作用呢,又是何时进到栈里的呢? 观察发现[ebp+$04]= 0044D953,是CALL返回后要执行的下一句
问题解答:
因此,在调用函数的时候,程序会偷偷的将执行CALL之后的下一条语句的地址压入栈中,同时呢,一般带有参数的程序,进入程序内部后会首先保存当时的EBP,这就造成了栈内多出两个数值,而这两个又都是在参数入栈之后发生的,因此第一个参数的地址就变成了[EBP+$08]。
明眼人也发现了,函数1返回时用的是ret直接返回,而函数2返回时是ret $0004, 这又是何意呢?原来ret时就自动把CALL之后的下一条语句的地址出栈了,后面的$0004意味着出栈后ESP这个栈顶指针要进行的偏移,因为你传进的这些参数在函数返回后它们就没必要存在栈里面了,所以移动下栈顶指针就可以。
ret $0004= ESP + $0004
相关文章推荐
- 反汇编及函数调用堆栈分析
- 一段C语言和汇编的对应分析,揭示函数调用的本质
- 从汇编的角度分析函数调用过程(2)
- 汇编中的函数调用:call
- 献给汇编初学者-函数调用堆栈变化分析
- 献给汇编初学者-函数调用堆栈变化分析(转)
- 函数调用-汇编分析
- VC环境下对函数调用的汇编分析
- 一段C语言和汇编的对应分析,揭示函数调用的本质
- c语言内部(汇编代码分析)函数调用过程探究
- C++中的虚函数调用原理的反汇编实例分析(1)
- 关于 接口与对象指针对成员函数的调用时的汇编执行行为分析
- 分析函数调用关系图(call graph)的几种方法
- 汇编代码分析----函数的调用堆栈过程(进程内核栈的切换过程)
- 分析函数调用关系图(call graph)的几种方法
- C++中的虚函数调用原理的反汇编实例分析(2)
- 汇编学习笔记:函数调用过程中的堆栈分析
- 献给汇编初学者-函数调用堆栈变化分析
- 献给汇编初学者-函数调用堆栈变化分析
- (此文精辟)[汇编学习]献给汇编初学者-函数调用堆栈变化分析(转自黑客风云)