Course contentsShow
← Rust
Lesson 1505 of 1,91012. Unsafe Rust and Low-Level AccessFree lesson

Addressing Mode Optimization

You will utilize platform-specific memory addressing modes to reduce instruction counts.

In this lesson, you will learn how to leverage complex CPU addressing modes to consolidate multi-instruction sequences into a single operation, reducing your binary's instruction count.

The Cost of Address Calculation

In high-level Rust, we often treat memory access as a single step: ptr[index]. However, at the machine level, calculating base + (index * scale) + offset often requires multiple instructions—loading the base, shifting the index, and adding the components. On architectures like x86_64, the hardware provides "Complex Addressing Modes" (also known as SIB—Scale, Index, Base) that perform this entire calculation in a single instruction cycle.

Utilizing SIB Addressing

When writing high-performance code, especially in no-std or kernel contexts, you can guide the compiler—or manually optimize via asm!—to utilize these modes. Instead of calculating an address in a general-purpose register, you can embed the computation directly into the instruction's ModR/M byte.

Consider a scenario where you are traversing an array of structs where each element is 16 bytes:

// Instead of manually calculating: let target = base + (index << 4);
// We can use Rust's asm! macro to force the SIB mode:
unsafe {
    core::arch::asm!(
        "mov rax, [{base} + {index}*16 + 8]",
        base = in(reg) base_ptr,
        index = in(reg) idx,
        out("rax") val,
    );
}

By offloading the scaling (*16) and the offset (+8) to the hardware's addressing unit, you save two arithmetic instructions per access.

When to Optimize

This optimization is most effective when working with contiguous buffers, such as DMA descriptors or memory-mapped video frames. If your code is frequently performing index-based lookups, checking the generated assembly (via cargo-show-asm) is critical. If you see your compiler emitting shl (shift) and add instructions before a mov, you are missing out on the hardware's ability to handle that offset natively.

However, note that this is highly platform-specific. While x86_64 is rich with SIB modes, RISC architectures like ARM or RISC-V may have different constraints on which offsets can be encoded. Always verify that your target hardware supports the specific scaling factor you intend to use.

Key Takeaway: Use hardware-native SIB (Scale-Index-Base) addressing modes within asm! blocks to fold pointer arithmetic into your load/store instructions, effectively shrinking your instruction footprint.