# Offset Calculation for a Branch Instruction Thumb [closed]

I did find this link: Offset calculation for branch instruction in ARM

Which was quite helpful but also confusing for me. I tried few ways to get it working with my offsets but failed.

What I wanted to do, was create a BL instruction from 0x52F4D6 to 0x5BF368.

At 0x52F4D6 I wanted to write BL sub_5BF368 but how do I get the correct hex code (thumb) for it?

Thank you!

• Example of manipulating ARM conditional branch instruction to patch an Android Shared LIB Android lib patching – Hilogic Apr 20 '16 at 17:09

You can get this from the ARM manual; for example from the version linked at the link you found, https://ece.uwaterloo.ca/~ece222/ARM/ARM7-TDMI-manual-pt3.pdf.

First, a quick calculation 5BF358-52F4D6 yields 8FE82, so you see you have more than 12 bits, and need to use the long branch format in 5.19, which splits your BL into two instructions. The section says "The branch offset must take account of the prefetch operation, which causes the PC to be 1 word (4 bytes) ahead of the current instruction", so the offset you need is from 4 bytes behind 52F4D6 - 52F4DA, which means the offset for the instructions - the value you want to add to PC is 8FE7E.

The first part of the instruction shifts its partial offset left by 12 bits, and adds this to PC. The instruction format is 1111HXXXXXXXXXXX in binary, with H=0, so F000+XXXX in hex. What you want to add to PC in this step is 8F000, so the opcode for this instruction is F0 8F.

The second part shifts its partial offset left by one bit (remember thumb instructions are aligned to 16 bit, so the last bit of an offset is always 0, so it doesn't have to be represented in the hex opcode), and it has H=1, so the opcode is F800+XXXX. What you want to add in this step is E7E. Shift that right by one bit to get 73f, and add to your opcode to get FF 3F.

So, your BL instruction is F08F FF3F.

To confirm this, create an assembly program, assemble it, and check the result:

.thumb
.arch armv7a
.syntax unified
.align 2
.org    0x52F4D6
bl  sub_5BF368
.org    0x5BF368
sub_5BF368:


arm-linux-gnueabi-as -o y.o y.s
arm-linux-gnueabi-objdump -s y.o | grep -v "00000000 00000000 00000000 00000000"
.....
52f4d0 00000000 00008ff0 3fff0000 00000000  ........?.......
....


Remember words are byte-swapped due to little-endianness, and you'll find your F08F FF3F opcode there.

EDIT: I just fixed the address of the second .org since it seemed miss-typed just to avoid confusion. Now it looks consistent I think :)

• Awesome! Thank you! I also wanted to ask if I can use BGT, BEQ, BNE, BLE, BGE, BLT inside the assembly program and then disassemble it? – Anthony Apr 20 '16 at 15:16
• Yes, this works for all instructions. Just remember that the offset part of the conditional branches is just 8 bit, so the target needs to be closer to the branch instruction than in the bl example above. – Guntram Blohm supports Monica Apr 20 '16 at 15:31
• Sorry, I answered my own question. But another question, why can't I branch backwards a few offsets? Always get this error: attempt to move .org backwards – Anthony Apr 21 '16 at 14:06
• That because, well, you can't move .org backwards. For a back jump, you need to put the .org/sub declaration in front of the .org/branch. – Guntram Blohm supports Monica Apr 21 '16 at 17:30
• Awesome! Would you happen to have the parts to add to the start of the program so we can get the x64 offset? :) – Anthony Apr 22 '16 at 23:05