SoC
  • Home
  • Arm
  • Arm Cortex M0/M0+
  • Arm Cortex M4
  • Arm Cortex M3
  • Contact
Reading: Understanding Indirect Branches on Arm with BX and BLX
SUBSCRIBE
SoCSoC
Font ResizerAa
  • Home
  • Arm
  • Arm Cortex M0/M0+
  • Arm Cortex M4
Search
  • Home
  • Arm
  • Arm Cortex M0/M0+
  • Arm Cortex M4
Have an existing account? Sign In
Follow US
  • Looking for Something?
  • Privacy Policy
  • About Us
  • Sitemap
  • Contact Us
© S-O-C.ORG, All Rights Reserved.
Arm

Understanding Indirect Branches on Arm with BX and BLX

Graham Kruk
Last updated: September 28, 2023 1:22 pm
Graham Kruk 7 Min Read
Share
SHARE

Indirect branching allows jumping to an address stored in a register, providing flexibility in control flow. The Arm instruction set includes two main indirect branch instructions – BX and BLX. This article will explain how they work and when to use each one.

Contents
What is an Indirect Branch?BX – Branch and Exchange Instruction SetUses of BXFunction ReturnsPosition IndependenceSwitching Instruction SetsJump TablesBLX – Branch Link ExchangeUses of BLXIndirect CallsInterworking CallsFunction PointersPosition IndependenceBX vs BLXGuidelines for Indirect BranchesConclusion

What is an Indirect Branch?

An indirect branch occurs when the destination address for a jump or call instruction is computed at runtime rather than encoded directly in the instruction. For example: MOV R0, #0x100 BX R0

Here BX jumps to the address contained in R0, which could be set to any value at runtime. This contrasts with a direct branch like: B 0x100

Which always jumps to the fixed address 0x100.

BX – Branch and Exchange Instruction Set

The BX instruction performs an indirect branch to the address in a register, and can optionally switch between Arm and Thumb state. Its syntax is: BX Rn

BX jumps to the address in Rn. If bit 0 of Rn is 0, the processor remains in the current state (Arm or Thumb). If bit 0 is 1, the processor switches state.

For example: // Remain in Arm state MOV R0, #0x100 BX R0 // Switch to Thumb state MOV R0, #0x101 BX R0

This ability to conditionally change instruction set state is useful for interfacing between Arm and Thumb code.

Uses of BX

Some common uses of the BX instruction include:

  • Returning from a function call
  • Jumping to an address in a register for position-independent code
  • Switching between Arm and Thumb states
  • Implementing a primitive form of switch/case by jumping through a jump table

Function Returns

BX makes returning from a function easy: the return address was stored in LR during the BL call, so BX LR will jump back to the caller. This even works across changes in instruction set state thanks to the conditional switch ability of BX.

Position Independence

Code that computes jump targets at runtime can use BX to jump to those locations in a position independent way. For example: ADR R0, Function1 // R0 now contains address of Function1 BX R0 // Jump to address in R0

This allows the code to work regardless of where it is located in memory.

Switching Instruction Sets

BX provides a simple way to transfer control between Arm and Thumb code. For example: // Start in Arm state MOV R0, #1 // Set bit 0 BX R0 // Switch to Thumb // Now in Thumb state

Jump Tables

BX can be used to implement jump tables for primitive switch/case constructs. The table contains addresses to jump to indexed by case value: JUMPTABLE: DCD CASE1 DCD CASE2 DCD CASE3 // Load case value into R0 LDR R1, =JUMPTABLE LDR R0, [R1, R0, LSL #2] // Get address for case from table BX R0 // Jump

BLX – Branch Link Exchange

BLX performs similarly to BX but also stores the return address in LR, making it suitable for calling functions and subroutines. Its syntax is: BLX Rn

BLX branches to the address in Rn, switching instruction set state if bit 0 of Rn is 1. It also stores the address of the next instruction in the link register LR.

Uses of BLX

BLX is commonly used for:

  • Calling functions indirectly
  • Calling Thumb functions from Arm code and vice versa
  • Calling code via function pointers
  • Position independent calls

Indirect Calls

BLX allows computed destinations for calls: // R0 contains function address BLX R0 // Call through pointer MOV R0, pFunction BLX R0

This is useful any time the target of a call is not known at compile time.

Interworking Calls

BLX can call between Arm and Thumb thanks to its state switch ability: // Start in Arm state MOV R0, #1 // Set bit 0 BLX R0 // Switch to Thumb and call // Function is Thumb code

This facilitates interaction between the two instruction sets.

Function Pointers

BLX enables calling functions via C-style function pointers in Arm assembly: // R0 contains a function pointer BLX R0

Function pointers are useful for implementing callbacks, virtual functions, and more.

Position Independence

Like BX, BLX supports position independent calls: ADR R0, Function BLX R0

So the code works regardless of where it is located.

BX vs BLX

While BX and BLX are similar, there are some key differences:

  • BLX stores a return address in LR, BX does not
  • Use BX for jumps, BLX for calls
  • BLX takes an extra cycle compared to BX
  • BX can conditionally switch instruction sets, BLX always does

In general, use BX for simple jumps and BLX when you need to call a subroutine and be able to return.

Guidelines for Indirect Branches

Here are some guidelines for working with indirect branches on Arm:

  • Use BX for position independent jumps and returns
  • Use BLX for position independent calls
  • Take care that register alignment requirements are met
  • Beware of switching CPU states accidentally with BX
  • Use BLX to call between Arm and Thumb code
  • Indirect branches can make code harder to follow – use judiciously

Conclusion

BX and BLX provide flexible control flow on Arm using computed jump targets. BX performs simple indirect jumps, while BLX adds call abilities. Both can optionally switch instruction set state. Indirect branches enable position independence, call virtul functions, implement jump tables, and interact cleanly between Arm and Thumb. Used properly, they are powerful tools for advanced control flow.

This article has covered the key aspects of indirect branch instructions on Arm. BX and BLX provide a useful addition to direct branches, enabling flexible runtime-driven code execution.

Newsletter Form (#3)

More ARM insights right in your inbox

 


Share This Article
Facebook Twitter Email Copy Link Print
Previous Article Demystifying Arm’s Branch and Link Instructions (BL and BLX)
Next Article Arm’s Compare and Branch Instructions (CBZ and CBNZ) Explained
Leave a comment Leave a comment

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

2k Followers Like
3k Followers Follow
10.1k Followers Pin
- Sponsored-
Ad image

You Might Also Like

Use of Address of Unaligned Structure Member

Accessing members of a structure that is not aligned to…

7 Min Read

Common Vivado Issues on Windows for ARM Developers

Developing applications for ARM-based systems using Xilinx's Vivado Design Suite…

8 Min Read

Configuring Endianness in ARM Cortex-M3: Options and Limitations

The ARM Cortex-M3 processor supports both little endian and big…

9 Min Read

What is bare metal embedded programming?

Bare metal embedded programming refers to developing firmware directly on…

9 Min Read
SoCSoC
  • Looking for Something?
  • Privacy Policy
  • About Us
  • Sitemap
  • Contact Us
Welcome Back!

Sign in to your account