Modding Android games or apps using IDA Pro can be challenging, especially for beginners, as the structure and code can look very confusing if you don’t understand what it does. With IDA Pro, you can modify any kind of software programs, including PC games, showing the power of this single tool.
I have been using IDA Pro to reverse engineer for many years now and can understand a function on what it does by looking at it. This guide lists common ARM opcodes you might encounter while modding games, with simple explanations for each.
Data Processing Instructions
MOV (Move)
Syntax: MOV <Rd>, <Op2>
Description: Moves a value into a register.
Example: MOV R0, R1 – Copies the value in R1 into R0.
MVN (Move Not)
Syntax: MVN <Rd>, <Op2>
Description: Moves the bitwise NOT of a value into a register.
Example: MVN R0, R1 – Moves the bitwise NOT of R1 into R0.
ADD (Add)
Syntax: ADD <Rd>, <Rn>, <Op2>
Description: Adds two values.
Example: ADD R0, R1, R2 – Adds R1 and R2, stores the result in R0.
ADC (Add with Carry)
Syntax: ADC <Rd>, <Rn>, <Op2>
Description: Adds two values and the carry flag.
Example: ADC R0, R1, R2 – Adds R1, R2, and the carry flag, stores the result in R0.
SUB (Subtract)
Syntax: SUB <Rd>, <Rn>, <Op2>
Description: Subtracts one value from another.
Example: SUB R0, R1, R2 – Subtracts R2 from R1, stores the result in R0.
SBC (Subtract with Carry)
Syntax: SBC <Rd>, <Rn>, <Op2>
Description: Subtracts one value and the carry flag from another.
Example: SBC R0, R1, R2 – Subtracts R2 and the carry flag from R1, stores the result in R0.
RSB (Reverse Subtract)
Syntax: RSB <Rd>, <Rn>, <Op2>
Description: Subtracts a value from another in reverse order.
Example: RSB R0, R1, R2 – Subtracts R1 from R2, stores the result in R0.
CMP (Compare)
Syntax: CMP <Rn>, <Op2>
Description: Compares two values by subtracting one from the other and setting flags based on the result.
Example: CMP R0, R1 – Compares R0 and R1.
CMN (Compare Negative)
Syntax: CMN <Rn>, <Op2>
Description: Compares two values by adding them and setting flags based on the result.
Example: CMN R0, R1 – Compares R0 and the negation of R1.
Memory Access Instructions
LDR (Load Register)
Syntax: LDR <Rd>, [<Rn>, <offset>]
Description: Loads a value from memory into a register.
Example: LDR R0, [R1, #0x10] – Loads the value from the address (R1 + 0x10) into R0.
STR (Store Register)
Syntax: STR <Rd>, [<Rn>, <offset>]
Description: Stores a value from a register into memory.
Example: STR R0, [R1, #0x10] – Stores the value in R0 into the address (R1 + 0x10).
Branch Instructions
B (Branch)
Syntax: B <label>
Description: Unconditionally branches to a label.
Example: B loop_start – Jumps to the label loop_start.
BL (Branch with Link)
Syntax: BL <label>
Description: Branches to a label and stores the return address in the link register (LR).
Example: BL function_call – Calls the subroutine at function_call.
BX (Branch and Exchange)
Syntax: BX <Rn>
Description: Branches to the address in a register and optionally switches instruction sets.
Example: BX R0 – Branches to the address in R0.
Practical Examples
Modifying Health to Infinite
Original Instruction: LDR R0, [R1, #0x10]
Modified Instruction: MOV R0, #0xFFFFFFFF
Description: Loads a very high value into the health register, effectively giving infinite health.
Increasing Ammo Count
Original Instruction: LDR R2, [R3, #0x20]
Modified Instruction: ADD R2, R2, #10
Description: Adds 10 to the current ammo count, increasing the total ammo.
Increasing Currency
Original Instruction: SUB R4, R5, #100
Modified Instruction: ADD R4, R5, #100
Description: Instead of subtracting 100 from the currency, this change adds 100, increasing the total currency.
Setting Maximum Ammo
Original Instruction: LDR R2, [R3, #0x20]
Modified Instruction: MOV R2, #999
Description: Directly sets the ammo count to 999.
Setting Maximum Health
Original Instruction: LDR R0, [R1, #0x10]
Modified Instruction: MOV R0, #1000
Description: Directly sets the health value to 1000.
Preventing Health Decrease
Original Instruction: SUB R0, R0, #1
Modified Instruction: ADD R0, R0, #0
Description: Prevents the health from decreasing by adding 0 instead of subtracting 1.
Doubling Currency Collection
Original Instruction: ADD R4, R4, #100
Modified Instruction: ADD R4, R4, #200
Description: Doubles the amount of currency added when collected.
Instantly Refilling Ammo
Original Instruction: LDR R2, [R3, #0x20]
Modified Instruction: MOV R2, #500
Description: Instantly refills ammo to 500.
Increasing Health Pickup Amount
Original Instruction: ADD R0, R0, #10
Modified Instruction: ADD R0, R0, #50
Description: Increases the health gained from pickups from 10 to 50.
More Examples with Use Cases
MOV (Move)
Syntax: MOV <Rd>, <Op2>
Description: Moves a value into a register.
Example: MOV R0, R1 – Copies the value in R1 into R0.
Use Case 1: Setting health to a high value.
Example: MOV R0, #0xFFFFFFFF – Sets the health value in R0 to a very high number, effectively making health infinite.
Use Case 2: Setting ammo to a high value.
Example: MOV R2, #999 – Sets the ammo count in R2 to 999.
ADD (Add)
Syntax: ADD <Rd>, <Rn>, <Op2>
Description: Adds two values.
Example: ADD R0, R1, R2 – Adds R1 and R2, stores the result in R0.
Use Case 1: Increasing health.
Example: ADD R0, R0, #100 – Increases the health value in R0 by 100.
Use Case 2: Increasing ammo.
Example: ADD R2, R2, #10 – Adds 10 to the current ammo count in R2.
Use Case 3: Increasing currency.
Example: ADD R4, R4, #1000 – Adds 1000 to the current currency in R4.
SUB (Subtract)
Syntax: SUB <Rd>, <Rn>, <Op2>
Description: Subtracts one value from another.
Example: SUB R0, R1, R2 – Subtracts R2 from R1, stores the result in R0.
Use Case 1: Decreasing health.
Example: SUB R0, R0, #1 – Decreases the health value in R0 by 1.
Use Case 2: Decreasing ammo.
Example: SUB R2, R2, #5 – Subtracts 5 from the current ammo count in R2.
Use Case 3: Decreasing currency.
Example: SUB R4, R4, #500 – Subtracts 500 from the current currency in R4.
STR (Store Register)
Syntax: STR <Rd>, [<Rn>, <offset>]
Description: Stores a value from a register into memory.
Example: STR R0, [R1, #0x10] – Stores the value in R0 into the address (R1 + 0x10).
Use Case 1: Storing a high health value.
Example: STR R0, [R1, #0x10] – After setting R0 to a high value, this instruction stores that high value into the health address.
Use Case 2: Storing a high ammo value.
Example: STR R2, [R3, #0x20] – After setting R2 to a high value, this instruction stores that high value into the ammo address.
LDR (Load Register)
Syntax: LDR <Rd>, [<Rn>, <offset>]
Description: Loads a value from memory into a register.
Example: LDR R0, [R1, #0x10] – Loads the value from the address (R1 + 0x10) into R0.
Use Case 1: Loading the current health value.
Example: LDR R0, [R1, #0x10] – Loads the current health value into R0 from the address (R1 + 0x10).
Use Case 2: Loading the current ammo count.
Example: LDR R2, [R3, #0x20] – Loads the current ammo count into R2 from the address (R3 + 0x20).
Conclusion
The knowledge of these ARM opcodes is very important in effectively modding games with IDA Pro. By changing these instructions, you can change the way a game works: say, infinite health, much ammo, or much in-game money. Always remember to back up your original game files before making any changes. Happy modding!
If you have any questions, then let me know in the comments section below.