我有一些代码(我假设是 Delphi),它只使用 EAX 和 EDX 寄存器来传递参数(如果需要更多,当然还有堆栈)。我查看了哪些调用约定会匹配,但我还没有找到仅使用 EAX 和 EDX 的调用约定。AFAIK Borland fastcall/register 使用 EAX 和 EDX,但也使用 ECX,这里不是这种情况。
我能以某种方式告诉 IDA 关于这个调用约定吗?我该怎么做?
我有一些代码(我假设是 Delphi),它只使用 EAX 和 EDX 寄存器来传递参数(如果需要更多,当然还有堆栈)。我查看了哪些调用约定会匹配,但我还没有找到仅使用 EAX 和 EDX 的调用约定。AFAIK Borland fastcall/register 使用 EAX 和 EDX,但也使用 ECX,这里不是这种情况。
我能以某种方式告诉 IDA 关于这个调用约定吗?我该怎么做?
您可以通过编辑(键 Y)并添加名称来添加功能类型。
我写了一个页面来提醒我在 ASM 级别调用约定。
原来的电话是myfunc(0,1,2,3,4)
。
注意:堆栈在垂直方向上看起来像调用顺序。
push 4
push 3
push 2
push 1
push 0
call myfunc
xor eax,eax
retn 10
这实际上是微软的fastcall。
push 4
push 3
push 2
mov edx,1
xor ecx,ecx
call myfunc
xor eax,eax
retn 10
push 4
push 3
push 2
push 1
push 0
call myfunc
add esp,014
xor eax,eax
retn 10
push ebx
push 0
push 1
push 2
push 3
push 4
call myfunc
xor eax,eax
pop ebx
retn 10
显然,fortran 调用约定是什么并不是很清楚,这个甚至与 raymond 的帖子不同,__fortran
调用约定不是 FORTRAN 使用的调用约定。
push ebx
push 4
mov ecx,3
mov ebx,2
mov edx,1
xor eax,eax
call myfunc
xor eax,eax
pop ebx
retn 10
使用eax
, ecx
,edx
作为前 3 个参数。其他参数以相反的顺序压入堆栈。
push 3
push 4
mov ecx, 2
mov edx, 1
xor eax,eax
call myfunc
xor eax,eax
retn 10
如果您遇到任何标准调用约定未涵盖的调用约定,您可以使用__usercall 或 __userpurge 调用约定,它允许您指定将哪些参数传递到何处。语法是
return_type __usercall function_name< registers >(arg0_type arg0< registers >, arg1_type arg1< registers >, ...)
其中寄存器可以是寄存器中的一个分组分离由“:”字符如果参数占据多于一个的寄存器。
如果你在一个非常糟糕的地方调用约定明智你可以使用这里描述的完整语法。您可以在其中描述在寄存器或堆栈元素的部分中传递的参数,而不是简单地键入保存参数的寄存器名称。语法如上,只是将寄存器替换为
<argoff:register^regoff.size>
或者如果参数在堆栈上传递
<argoff:^stkoff.size>
Delphi 和 Borland C++ Builder 使用EAX
,EDX
和ECX
作为其__fastcall
调用约定变体中的前三个参数。因此,如果您在 Options-Compiler 中选择“Delphi”或“C++ Builder”,则只需__fastcall
在函数原型中使用即可- 无需求助于__usercall
.