在一些旧的汇编中,它使用push来传递参数,例如
push eax
push ebx
call xxx
所以我知道原点函数有两个参数。
但有些汇编程序使用寄存器传递参数,例如在ollydbg中
MOV QWORD PTR [RSP+90],RBP
MOV RAX,QWORD PTR [RCX]
MOV R8,RDX
MOVSXD RBP,EDI
JBE SHORT 61B646C0
MOV R9,RSI
CALL QWORD PTR [RAX+10]
我知道如果电话有两个参数,它应该是RCX,RDX,但我不知道有多少。
我试着用一些简单的函数编写一些C++代码,但在读了函数的前一行汇编后,如果不知道源代码,我仍然找不到逻辑。
1条答案
按热度按时间3ks5zfa01#
在调用之前运行
mov r9, rsi
指令来设置R9是一个参数的可靠标志,因此如果是Windows x64,则至少需要4个参数,如果是x86-64 System V,则至少需要6个整数/指针参数。您提到了RCX和RDX,Ollydbg是一个Windows调试器,因此可能是Windows x64。这与RCX中的结构体/类指针一致,作为成员函数的this
参数。(在本例中为虚拟,即通过vtable的间接寻址)。**R9在两种主流x86-64调用约定中都被调用重编码,因此没有理由在以
call
结尾的基本块中存在mov r9, rsi
。(除非这是经过模糊处理的代码。)**在Windows x64中,RSI是调用保留的,因此很可能mov r9, rsi
将某个局部变量作为函数arg传递,而RSI中的副本在整个呼叫中继续存在。但是正如Jester所说,你不能总是确定堆栈上的东西是函数参数还是只是保存起来供以后使用,所以你不能确定是否有
[rsp+32]
(又名[rsp+0x20]
)的存储,是否 * 只有 * 4个参数。查看被调用方是一个更好的标志,但是有些函数可能会忽略它们的一些参数。一个虚函数可能有一些参数,但并不是所有的示例都需要。但是如果你在被调用者中看到代码读取寄存器或内存位置而没有先写它,那要么是代码中的bug,要么是这是一个输入的信号。如果它是传递参数的寄存器之一,或者就在返回地址的上面,那么它就是一个函数参数。