AFAIK Borland fastcall / register使用的是EAX和EDX,但也使用ECX,这里不是这种情况。
我能以某种方式告诉IDA这个调用约定吗?我该怎么办?
#1 楼
您可以通过编辑(键Y)并添加名称来添加函数类型。我写了一个页面来提醒我有关在ASM级别调用约定的信息。
简介
原始调用是
myfunc(0,1,2,3,4)
。标准顺序是第一个参数被最后推送。
标准堆栈调整是'callee cleanup'-返回后,堆栈应该没有调用参数。
注意:堆栈看起来像调用顺序一样。
stdcall(仅堆栈)
push 4
push 3
push 2
push 1
push 0
call myfunc
xor eax,eax
retn 10
Fastcall (ecx,edx)
这实际上是Microsoft的fastcall。
push 4
push 3
push 2
mov edx,1
xor ecx,ecx
call myfunc
xor eax,eax
retn 10
CDECL和syscall(调用程序清理)
>
push 4
push 3
push 2
push 1
push 0
call myfunc
add esp,014
xor eax,eax
retn 10
Pascal(反向命令,即使没有使用ebx,也保存ebx ...)
push ebx
push 0
push 1
push 2
push 3
push 4
call myfunc
xor eax,eax
pop ebx
retn 10
Fortran /警告(eax, edx,ebx,ecx,然后是堆栈-保存了ebx)
显然,尚不清楚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
Delphi“注册”调用约定(默认)
使用
eax
,ecx
和edx
作为前三个参数。其他参数以相反顺序推入堆栈。push 3
push 4
mov ecx, 2
mov edx, 1
xor eax,eax
call myfunc
xor eax,eax
retn 10
评论
每个示例末尾的retn 10行是一条红色鲱鱼,可能会造成混淆。它的值与示例对myfunc的调用无关。
–杂件
17年1月20日在11:17
#2 楼
如果遇到任何标准调用约定都未涵盖的调用约定,则可以使用__usercall或__userpurge调用约定,它们允许您指定将哪些参数传递到哪里。语法为return_type __usercall function_name<registers>(arg0_type arg0<registers>, arg1_type arg1<registers>, ...)
其中,如果参数占用多个寄存器,则寄存器可以是由':'字符分隔的一组寄存器。
如果您真的很习惯调用约定,可以使用此处描述的完整语法。在这里,您不仅可以简单地输入包含参数的寄存器名称,还可以描述在寄存器或堆栈元素的各个部分中传递的参数。仅当寄存器被
<argoff:register^regoff.size>
<argoff:^stkoff.size>
#3 楼
Delphi和Borland C ++ Builder在EAX
调用约定的变体中,将EDX
,ECX
和__fastcall
用作前三个参数。因此,如果在Options-Compiler中选择“ Delphi”或“ C ++ Builder”,则只需在函数原型中使用__fastcall
-无需求助于__usercall
。评论
原始张贴者说,调用约定仅使用EAX和EDX,而不使用ECX。对我来说听起来很奇怪。
–彼得·安德森(Peter Andersson)
13-10-28在12:13
评论
您可以粘贴一些使用EAX,EDX和不使用ECX的堆栈的代码吗?在更详细地研究之后,似乎确实使用了ECX,并且代码通常不需要两个以上的参数。当我查看带有更多参数的函数时,我意识到这是EAX / EDX / ECX / PUSH的标准...
好的,那谜团就解决了。