Difference between revisions of "Tutorial:CodeInjection Floats"
(→Working with the FPU registry) |
|||
Line 220: | Line 220: | ||
<br> | <br> | ||
== Working with the FPU registry == | == Working with the FPU registry == | ||
− | Some times you'll find some opcode that uses the FPU registry. These include [[Assembler:Commands:FLD|FLD]], [[Assembler:Commands:FMUL|FMUL]], [[Assembler:Commands:FADD|FADD]], [[Assembler:Commands:FSUB|FSUB]], [[Assembler:Commands:FST|FST]], [[Assembler:Commands:FSTP|FSTP]]. | + | Some times you'll find some opcode that uses the [https://en.wikibooks.org/wiki/X86_Assembly/Floating_Point FPU] registry. These include [[Assembler:Commands:FLD|FLD]], [[Assembler:Commands:FMUL|FMUL]], [[Assembler:Commands:FADD|FADD]], [[Assembler:Commands:FSUB|FSUB]], [[Assembler:Commands:FST|FST]], [[Assembler:Commands:FSTP|FSTP]]. |
So with singles it might look like this. | So with singles it might look like this. | ||
Line 270: | Line 270: | ||
<br> | <br> | ||
+ | |||
== See Also == | == See Also == | ||
{{TutorialsAA}} | {{TutorialsAA}} |
Revision as of 03:05, 12 May 2018
This tutorial builds on the topic of Code Injection:
- Code Injection - Basic injection
- Code Injection - Full injection
- Code Injection - Adding Editable Values
- Code Injection - Working with Integers
- Code Injection - Working with Floats
Let's say you have a float and some code that increases the value.
addss [eax+10],xmm0
- Note: SS is for singles and SD is for doubles.
What if what writes to the value is only a MOVSS. Try to find a spot above the write instruction that has an ADDSS (or a SUBSS depending on what you want to do).
addss xmm0,xmm1 //... movss [eax+10],xmm0
Contents
Editable value
We could use a label, giving it some memory. And optionally register it so the label can be used on the table as an address.
//... alloc(someMem, 0x400) //... label(someSymbol) registerSymbol(someSymbol) //... someMem: //... movss xmm0,[someSymbol] addss [eax+10],xmm0 //... jmp return //... someSymbol: dd (float)100 //...
Adding a Multiplier
We could add an editable value like above but use MULSS to add a multiplier to the script.
//... alloc(someMem, 0x400) //... label(someSymbol) registerSymbol(someSymbol) //... someMem: //... mulss xmm0,[someSymbol] addss [eax+10],xmm0 //... jmp return //... someSymbol: dd (float)100 //...
Calculate a value for a Multiplier
Let's say we just can't find an ADDSS or a SUBSS, and all we have is a MOVSS.
movss [eax+10],xmm0
We can just do some math in the script, to calculate a value for a multiplier.
//... alloc(someMem, 0x400) //... label(someSymbol) registerSymbol(someSymbol) //... someMem: //... subss xmm0,[eax+10] mulss xmm0,[someSymbol] addss xmm0,[eax+10] movss [eax+10],xmm0 //... jmp return //... someSymbol: dd (float)10 //...
Working with doubles
Let's say the game use doubles, we can use ADDSD, SUBSD, MULSD, and MOVSD instead. We just need to also make our scripts value a double.
movsd [eax+10],xmm0
So to calculate a value for a multiplier.
//... alloc(someMem, 0x400) //... label(someSymbol) registerSymbol(someSymbol) //... someMem: //... subsd xmm0,[eax+10] mulsd xmm0,[someSymbol] addsd xmm0,[eax+10] movsd [eax+10],xmm0 //... jmp return //... someSymbol: dq (double)10 //...
Working with packed instructions
Some times (especially with vectors) you'll see packed instructions, like MOVAPS, MOVUPS, ADDPS, SUBPS, MULPS. These type of instructions work on 16 bytes at a time.
So let's say you have some code accessing the player coordinate deltas, and it's using packed instructions.
addps [eax+10],xmm0
So let's add a multiplier for this.
//... alloc(someMem, 0x400) //... label(someSymbol) registerSymbol(someSymbol) //... someMem: //... mulps xmm0,[someSymbol] addps [eax+10],xmm0 //... jmp return //... someSymbol: dd (float)1.75 dd (float)1.75 dd (float)1.25 dd (float)1 //...
Calculate a value for packed instruction
Let's say we just can't find an ADDPS or a SUBPS, and all we have is a MOVUPS or a MOVAPS.
movups [eax+10],xmm0
We can just do some math in the script, to calculate a value for a multiplier.
//... alloc(someMem, 0x400) //... label(someSymbol) registerSymbol(someSymbol) //... someMem: //... subps xmm0,[eax+10] mulps xmm0,[someSymbol] addps xmm0,[eax+10] movups [eax+10],xmm0 //... jmp return //... someSymbol: dd (float)1.75 dd (float)1.75 dd (float)1.25 dd (float)1 //...
We could use the align command and then be able to use aligned instructions. So if the injection point looks like this.
movups [eax+10],xmm0
Then we could make a script like this.
//... alloc(someMem, 0x400) //... label(someSymbol) registerSymbol(someSymbol) //... someMem: //... subps xmm0,[eax+10] mulps xmm0,[someSymbol] addps xmm0,[eax+10] movaps [eax+10],xmm0 //... jmp return //... align 10 CC someSymbol: dd (float)1.75 dd (float)1.75 dd (float)1.25 dd (float)1 //...
Working with the FPU registry
Some times you'll find some opcode that uses the FPU registry. These include FLD, FMUL, FADD, FSUB, FST, FSTP.
So with singles it might look like this.
fld dword ptr [ebp+20] fmul dword ptr [ebp+40] fadd dword ptr [eax+10] fstp dword ptr [eax+10]
And if it was with doubles it might look like this.
fld qword ptr [ebp+20] fmul qword ptr [ebp+40] fadd qword ptr [eax+10] fstp qword ptr [eax+10]
So say we have some opcode that decreases health that looks like this.
fld dword ptr [eax+10] fsub dword ptr [ebp+20] fstp dword ptr [eax+10]
So the add a multiplier to this we could make a script like this.
//... alloc(someMem, 0x400) //... label(someSymbol) registerSymbol(someSymbol) //... someMem: //... fld dword ptr [ebp+20] fmul dword ptr [someSymbol] fld dword ptr [eax+10] fsub st(0),st(1) fstp dword ptr [eax+10] fstp st(0) //... jmp return //... someSymbol: dd (float)0.25 //...