In some old assemble, it use push to pass parameter,for example
push eax
push ebx
call xxx
so I know the origin function has two parameters.
But some assemble use register to pass parameter,for example in 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]
I know if the call has two parameters, it should be RCX,RDX,but i don't know how many.
I try write some C++ code with some simple function,but after read the previous line of assemble of the function,I still can't find the logic if not knowing the origin code.
Running a mov r9, rsi
instruction to set R9 right before a call is a sure sign that it's an arg, so at least 4 total args if that's Windows x64, or at least 6 integer/pointer args if that's x86-64 System V. You mention RCX and RDX, and Ollydbg is a Windows debugger, so presumably Windows x64. That's consistent with having a struct / class pointer in RCX, as the this
argument for a member function. (In this case virtual, indirection through the vtable).
R9 is call-clobbered in both mainstream x86-64 calling conventions, so there'd be no reason for a mov r9, rsi
to exist in a basic block ended by a call
otherwise. (Unless this is obfuscated code.) In Windows x64, RSI is call-preserved, so it's very likely mov r9, rsi
is passing some local variable as a function arg, with the copy in RSI surviving across the call.
But as Jester said, you can't always be sure whether things on the stack are function args or just saving for later. So you can't be sure there are only 4 args, if there are any stores to [rsp+32]
(aka [rsp+0x20]
).
Looking at the callee is a better sign, but some functions might ignore some of their args. Especially in this case where call [RAX+0x10]
is probably indexing the vtable; a virtual function might have args that not all instances of it need. But if you do see code in a callee that would read a register or memory location without having written it first, that's either a bug in the code or a sign that this is an input. If it's one of the arg-passing registers or just above the return address, then it's a function arg.