Reputation: 121
int CachedTag_NoCache_GetTagPos( CEntity* centity, int tag, Vector* worldpos )
{
void* funccall = (void*)0x7D5BD0;
__asm {
mov edi, worldpos
mov esi, centity
push tag
call funccall
add esp, 4
}
}
Function crashes at add esp, 4....
I know its crashing from the clean up of this inline assembly. I just don't know how to fix it.
This is what is inside ida pro:
int __usercall sub_7A7D20<eax>(int a1<ecx>, int a2<edi>, int a3<esi>, int a4)
{
int v4; // eax@2
int result; // eax@2
char *v6; // eax@3
char v7; // al@5
int v8; // [sp+0h] [bp-4h]@1
v8 = a1;
if ( *(_WORD *)(a3 + 678) == 1 )
{
LOBYTE(v8) = sub_5BB6F0(*(_BYTE *)(a3 + 4), *(_DWORD *)(a3 + 0x1E8));
v4 = sub_7A7C40();
result = sub_4DA2F0(a3, a2, a4, v4, v8);
}
else
{
v6 = sub_615EA0(*(_DWORD *)(a3 + 0x1E8), *(_BYTE *)(a3 + 4));
result = sub_4B2F50(a3, v6, a2, a4);
}
if ( !result )
{
v7 = sub_624C70(a2, 0);
result = sub_627380(1, "AimTarget_GetTagPos: Cannot find tag [%s] on entity\n", v7);
}
return result;
}
The assembly for this function from ida pro in text:
.text:007D5BD0 sub_7D5BD0 proc near ; CODE XREF: sub_4DA2F0+76p
.text:007D5BD0 ; sub_62AE20+18p
.text:007D5BD0
.text:007D5BD0 arg_0 = dword ptr 4
.text:007D5BD0
.text:007D5BD0 movzx eax, byte ptr [esi+4]
.text:007D5BD4 mov ecx, [esi+1E8h]
.text:007D5BDA push ebx
.text:007D5BDB mov ebx, [esp+4+arg_0]
.text:007D5BDF push eax
.text:007D5BE0 push ecx
.text:007D5BE1 call sub_615EA0
.text:007D5BE6 add esp, 8
.text:007D5BE9 test eax, eax
.text:007D5BEB jnz short loc_7D5C00
.text:007D5BED fld dword ptr [esi+30h]
.text:007D5BF0 pop ebx
.text:007D5BF1 fstp dword ptr [edi]
.text:007D5BF3 fld dword ptr [esi+34h]
.text:007D5BF6 fstp dword ptr [edi+4]
.text:007D5BF9 fld dword ptr [esi+38h]
.text:007D5BFC fstp dword ptr [edi+8]
.text:007D5BFF retn
.text:007D5C00 ; ---------------------------------------------------------------------------
.text:007D5C00
.text:007D5C00 loc_7D5C00: ; CODE XREF: sub_7D5BD0+1Bj
.text:007D5C00 push edi
.text:007D5C01 push ebx
.text:007D5C02 push eax
.text:007D5C03 push esi
.text:007D5C04 call sub_4B2F50
.text:007D5C09 add esp, 10h
.text:007D5C0C test eax, eax
.text:007D5C0E jnz short loc_7D5C2B
.text:007D5C10 push eax
.text:007D5C11 push ebx
.text:007D5C12 call sub_624C70
.text:007D5C17 push eax ; char
.text:007D5C18 push offset aCachedtag_noca ; "CachedTag_NoCache_GetTagPos: Cannot fin"...
.text:007D5C1D push 1 ; int
.text:007D5C1F call sub_627380
.text:007D5C24 add esp, 14h
.text:007D5C27 xor eax, eax
.text:007D5C29 pop ebx
.text:007D5C2A retn
.text:007D5C2B ; ---------------------------------------------------------------------------
.text:007D5C2B
.text:007D5C2B loc_7D5C2B: ; CODE XREF: sub_7D5BD0+3Ej
.text:007D5C2B mov edx, dword_D4F178
.text:007D5C31 mov eax, [edx+40688h]
.text:007D5C37 pop ebx
.text:007D5C38 retn
.text:007D5C38 sub_7D5BD0 endp
.text:007D5C38
.text:007D5C38 ; ---------------------------------------------------------------------------
.text:007D5C39 align 10h
.text:007D5C40
The assembly that I have is working. I enter into the game and it shows me what I want for about 3 minutes. Then it crashes. While having visual studio attached to the process it always says crashed on my function above at add esp, 4.
Now on a usercall that uses edi and esi do I have to pop them off after calling my function and/or do I have to retn something too?
Its obviously not fine the way I have it because it only works for about 3 minutes. The longest I had the code working for was about 3 games. Which were about 10 minutes in length.
Then after those 3 games it just started to fatal error on me.
Thanks for anyone who has the knowledge to answer this question.
I know its something stupid with the clean up after that function call in the inline assembly.
Upvotes: 1
Views: 3319
Reputation: 26181
you need to save and restore EDI
and ESI
(the x86 ABI defines them as non-volatile registers, which means you cannot trash them), it also likely the prologue and epilogue generated by MSVC that is causing issues, IMO, it would be better to write this a a pure naked function, this gives you better control over the assembly generated, and ensures you can properly emulated non-standard (optimized) calling conventions:
__declspec(naked) int __fastcall CachedTag_NoCache_GetTagPos(CEntity* centity, int tag, Vector* worldpos)
{
__asm {
push edi
push esi
mov edi,worldpos
mov esi,centity
push tag
mov eax,0x7D5BD0
call eax
add esp,4
pop esi
pop edi
retn 4
}
}
In terms of the exception you are getting, it sounds like you aren't getting the correct line, an assembly level debugger like ollydbg would help you pin-point the exact cause and the correct location.
Also, as a word of caution, never use a fixed address, use a relocation safe variant, ie: a base address + RVA; in my above code, you need only alter two lines to achieve that:
mov eax,[base_address]
add eax,rva
where base_address
is along the lines of:
UINT_PTR base_address = (UINT_PTR)GetModuleHandle("some_module");
and is globally accessible.
Upvotes: 1
Reputation: 5607
The code you provided is correct. The target function itself is stack neutral and you clean your pushed parameter after calling.
Are you sure that this is the correct line the code is crashing at? What exception do you get? I don't think that adding a constant to a register can even cause an exception.
The crash intervals you report seem random. This could be a threading issue that you for example pass an invalid CEntity and the called function crashes. You can prevent this by hooking the thread that usually calls this function and call it within that thread.
Upvotes: 0