 |
Cheat Engine The Official Site of Cheat Engine
|
View previous topic :: View next topic |
Author |
Message |
Gear2ndGandalf Cheater
Reputation: 0
Joined: 22 Jan 2018 Posts: 36 Location: USA
|
Posted: Tue Feb 06, 2024 9:10 pm Post subject: Assembler: How Can I Divide Directly From r8d Register? |
|
|
This address executes when an enemy hits player, and the damage output varies by enemy type and action. Instead of mov r8d,#1, where all enemies do 1 damage to the player, I want to divide the general damgae done by 2 as to keep in line with the variable damage output from a variety of enemies and attacks.
Google searched up and down just to find examples regarding eax, ah, bl, ebx, ax, bx. Though I fail to implement the code properly and keep crashing the game as an enemy attack lands.
Please view photo for code.
Code: | push eax
push ebx
mov ebx,2
movsx r8d,word ptr [r10+000019A2]
div ebx
mov r8d,eax
pop ebx
pop eax |
Clearly what I'm doing doesn't make sense.
Description: |
movsx r8d,word ptr [r10+000019A2] |
|
Filesize: |
55.63 KB |
Viewed: |
13471 Time(s) |

|
Last edited by Gear2ndGandalf on Sat Feb 17, 2024 8:12 am; edited 1 time in total |
|
Back to top |
|
 |
ParkourPenguin I post too much
Reputation: 150
Joined: 06 Jul 2014 Posts: 4641
|
Posted: Tue Feb 06, 2024 11:35 pm Post subject: |
|
|
https://www.felixcloutier.com/x86/div
The numerator is always rdx:rax (rdx is the more significant half; edx:eax for 32-bit div). The denominator is some generic register or memory location- you're free to use whatever you want (probably not edx / eax obviously).
If you're dividing by 2, just shift the bits to the right by 1:
Code: | newmem:
code:
movsx r8d,word ptr[r10+19A2]
sar r8d,1
jmp return |
Some generic divisor:
Code: | alloc(damageDiv,4)
newmem:
code:
// no need to backup rax: game overwrites it immediately after this
push rdx
movsx eax,word ptr[r10+19A2] // eax b/c `idiv` uses edx:eax
cdq // sign-extend to edx:eax
idiv dword ptr[damageDiv] // divide edx:eax by the specified 4-byte value
mov r8d,eax
pop rdx
jmp return
damageDiv:
dd 7 |
If you want some user-configurable divisor, I'd really recommend using floating point arithmetic. This allows you to use divisors like 1.5 for example if 2 is too much.
Code: | alloc(damageDiv,8)
newmem:
code:
movsx r8d,word ptr[r10+19A2]
cvtsi2sd xmm0,r8d // convert int to double
divsd xmm0,[damageDiv]
cvttsd2si r8d,xmm0 // convert double to int (truncation)
jmp return
damageDiv:
dq (double)1.5 | xmm0 probably isn't in use, so no need to back it up
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
 |
Dark Byte Site Admin
Reputation: 467
Joined: 09 May 2003 Posts: 25700 Location: The netherlands
|
Posted: Wed Feb 07, 2024 12:54 am Post subject: |
|
|
you don't need to use floats if you don't want to use floats
you can also multiply the value by 10 and then divide by 15 (divisor * 10) to get a divide by 1.5 with decent accuracy
(10 is just for accuracy. you can also multiply by 2 and then divide by 3(divisor * 2) depending on how accurate the input is)
_________________
Do not ask me about online cheats. I don't know any and wont help finding them.
Like my help? Join me on Patreon so i can keep helping |
|
Back to top |
|
 |
Gear2ndGandalf Cheater
Reputation: 0
Joined: 22 Jan 2018 Posts: 36 Location: USA
|
Posted: Wed Feb 07, 2024 1:00 pm Post subject: |
|
|
Thanks that code actually works! And thanks for the explanation as well.
|
|
Back to top |
|
 |
Gear2ndGandalf Cheater
Reputation: 0
Joined: 22 Jan 2018 Posts: 36 Location: USA
|
Posted: Sat Feb 17, 2024 8:11 am Post subject: |
|
|
@ParkourPenguin
I have another one I'm struggling with.
Dante only goes into Majin Form devil trigger when his base HP is below 350. Starting max HP is 5000; Upgradable to 20000. I want to write a script that will allow us to set a percentage of Max HP needed to trigger the Majin Form.
Original code is: Code: | mov eax,0000015E // (350) |
My code is: Code: | aobscanmodule(majinDT,dmc2.exe,B8 5E 01 00 00 66 39 83)
alloc(newmem,$1000,majinDT)
alloc(percent,$1000)
label(code)
label(exit)
label(return)
percent:
dd (float)100
newmem:
push rdx
push ecx
mov edx,64 // 100 int
mov eax,[rdi+144] // 5000 int (Is Max HP Address)
mov ecx,[percent] // 100 float
div ecx
mov eax,edx
pop ecx
pop rdx
code:
// mov eax,0000015E // Original Code!
exit:
jmp return
majinDT:
jmp newmem
return:
registersymbol(majinDT)
registersymbol(percent)
|
Please see attachment for total code in disassembler. I keep getting improper results as changing my variable [percent] to 1 does not output 1% of 5000 to eax!
If [percent = 1] eax should = 50. If [percent = 100] eax should = 5000
Description: |
|
Filesize: |
155.46 KB |
Viewed: |
13129 Time(s) |

|
|
|
Back to top |
|
 |
ParkourPenguin I post too much
Reputation: 150
Joined: 06 Jul 2014 Posts: 4641
|
Posted: Sat Feb 17, 2024 12:31 pm Post subject: |
|
|
`div` is for integers. If you want floating point arithmetic, use SSE instructions.
Push `rcx`, not `ecx`. There might be something important in the upper 32 bits (e.g. a 64-bit pointer).
You don't need to allocate a full page (4096 bytes) of memory for a single variable.
There's no good reason to use floats instead of doubles.
Why move 100 into edx before the `div`? edx is the upper 32 bits of the numerator.
After `div`, eax is the result and edx is the remainder (i.e. modulus operation). You want eax and not edx.
I'm guessing the user input should be a number between 0 and 100. Floating point arithmetic:
Code: | aobscanmodule(majinDT,dmc2.exe,B8 5E 01 00 00 66 39 83)
alloc(newmem,1024,majinDT)
alloc(percent,8,majinDT)
alloc(hundred,8,majinDT)
label(return)
percent:
dq (double)100
hundred:
dq (double)100
newmem:
cvtsi2sd xmm0,[rdi+144] // max hp
mulsd xmm0,[percent]
divsd xmm0,[hundred]
cvttsd2si eax,xmm0
jmp return
majinDT:
jmp newmem
return:
registersymbol(majinDT)
registersymbol(percent) |
I'd prefer floating point arithmetic, but if you want integer arithmetic, use integers instead of floats. Multiply by the percentage first, then divide by 100 to avoid loss of precision.
Code: | ...
percent:
dd (int)100
newmem:
push rdx
push rcx
mov eax,[rdi+144] // max HP
imul [percent] // edx:eax = maxHP * percent
mov ecx,(int)100
idiv ecx // eax = edx:eax / ecx
pop rcx
pop rdx
jmp return
...
|
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
 |
Gear2ndGandalf Cheater
Reputation: 0
Joined: 22 Jan 2018 Posts: 36 Location: USA
|
Posted: Tue Feb 20, 2024 11:14 pm Post subject: |
|
|
Really appreciate it! Thanks for all your help ParkourPenguin and Dark Byte! Now I'm going to open another topic with a CE question regarding how to make a pop up warning happen when enabling a script.
|
|
Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You can download files in this forum
|
|