ff 15 调用函数与e8调用函数的区别 call的两种二进制命令

ff 15 和e8都是用来调用函数的机器码,看一个例子:
218 f9ebc53a 6a00                  push    0
218 f9ebc53c ff1500c9ebf9    call    dword ptr [APC!PspExitThread_Addr (f9ebc900)]
219 f9ebc542 a100c9ebf9      mov     eax,dword ptr [APC!PspExitThread_Addr (f9ebc900)]
219 f9ebc547 50                      push    eax
219 f9ebc548 68f0c4ebf9     push    offset APC!GetPspExitThreadAddr+0xee (f9ebc4f0)
219 f9ebc54d e872020000     call    APC!DbgPrint (f9ebc7c4)
219 f9ebc552 83c408              add     esp,8
220 f9ebc555 e870020000     call    APC!KeGetCurrentThread (f9ebc7ca)
220 f9ebc55a 8945fc               mov     dword ptr [ebp-4],eax
221 f9ebc55d 8b4dfc               mov     ecx,dword ptr [ebp-4]
221 f9ebc560 51                      push    ecx
221 f9ebc561 680cc5ebf9      push    offset APC!GetPspExitThreadAddr+0x10a (f9ebc50c)
221 f9ebc566 e859020000    call    APC!DbgPrint (f9ebc7c4)
221 f9ebc56b 83c408             add     esp,8

222 f9ebc56e 6a00                 push    0
222 f9ebc570 8b5508             mov     edx,dword ptr [ebp+8]
222 f9ebc573 52                     push    edx
222 f9ebc574 ff1508c8ebf9   call    dword ptr [APC!_imp__ExFreePoolWithTag (f9ebc808)]

APC!KillThreadRoutine+0x4d [f:/dvs/apc/apc.c @ 224]:
224 f9ebc57a 8be5                mov     esp,ebp
224 f9ebc57c 5d                     pop     ebp
224 f9ebc57d c21400            ret     14h
看上面的代码得到的结果是:
ff 15 调用时后面直接跟的是函数地址,并且不需要主调函数来平衡堆栈(即不需要在主调函数中使用add esp,xxh)
e8调用时后面跟的是函数地址相对于当前地址的偏移量,并且需要主调函数来实现堆栈平衡(即需要在主调函数中添加add esp,xxh),这个xxh当然是等于调用函数前push了多少字节的参数)
但是不知道还有没有其他的区别了...

 

 

 

PS:

call 一个near过程,只把偏移地址压入堆栈,过程返回时用retn返回
call一个far过程,把偏移地址和段地址入栈,过程返回时用retf返回

在过程中的ret指令根据near和far的不同,分别编译成retn和 retf
retn和retf的机器码是不同的,你也可以不定义过程,直接用retn和retf

你可能感兴趣的:(c)