如何通过.hex与.map文件确认Cortex-M4中BL指令的函数调用正确性
Great question—this is a common scenario when validating code changes on Cortex-M devices, and combining .map and .hex files is totally the right approach. Let’s break this down into actionable steps tailored to your STM32L4 (ARMv7-M) and IAR setup.
一、确认函数已被正确替换为Bar/Bla
Step 1: Extract critical addresses from the .map file
IAR’s .map file is your roadmap here. Open it and look for these sections:
- Function addresses: Locate the absolute addresses of
Foo,Bar, andBla(e.g.,Foo: 0x08001234,Bar: 0x08001456). These are listed under sections likeSymbol TableorFunction Addresses. - Call site references: Find where
Foowas originally called. Check theCross Referencessection—look for lines likeReferences to Foo: 0x08000ABC(this is the address of theBL Fooinstruction in your code).
Step 2: Convert .hex to raw binary for easy address inspection
Intel Hex is a text-based format, which isn’t great for direct address lookups. Use IAR’s built-in ielftool to convert your .hex (or better yet, your .out executable) to a binary file:
ielftool --bin your_project.out your_project.bin
This gives you a raw byte-for-byte copy of your firmware in Flash.
Step 3: Verify the call site machine code matches the target function
Now, cross-check the call site address (from Step 1) in the binary:
- Calculate the offset from your Flash base address (STM32L4 uses
0x08000000as the default Flash start). For a call site at0x08000ABC, the offset is0x08000ABC - 0x08000000 = 0xABC. - Open the
.binfile in a hex editor (like HxD or IAR’s built-in editor) and jump to offset0xABC. - Before replacement: This location should hold the machine code for
BL Foo. After replacement: It should hold the machine code forBL BarorBL Bla.
To confirm the machine code is correct, calculate the expected BL instruction for your target function (see Section II below) and compare it to the bytes in the .bin file.
Bonus: Cross-check with .map reference changes
Quick sanity check: Compare the .map files before and after replacement. The References to section should now list Bar or Bla at the same call site address where Foo was referenced before. If this is the case, it’s a strong indicator the replacement worked.
二、Convert .map addresses to machine code
There are two common scenarios here: converting a function’s address to the BL instruction that calls it, or extracting the raw machine code at a given address from the .hex file.
Scenario 1: Calculate the BL instruction machine code for a function address
Cortex-M4 uses Thumb-2 instruction set, and BL (branch and link) is a 4-byte instruction. The encoding depends on the relative offset between the call site and the target function. Here’s how to compute it:
Define variables:
PC: The address of theBLinstruction plus 4 (since ARM uses a "delayed" PC value).TargetAddr: The function address from the.mapfile (e.g.,0x08001456).
Compute the relative offset:
Offset = TargetAddr - PCSince Thumb instructions are 2-byte aligned,
Offsetmust be even.Encode the offset into the 4-byte
BLinstruction:
The Thumb-2BLinstruction splits the signed offset into two parts:- High 16 bits:
0xF000 | ((Offset >> 12) & 0x07FF) << 4 | ((Offset >> 11) & 0x01) - Low 16 bits:
0x8000 | ((Offset >> 1) & 0x03FF)
If manual calculation feels tedious, use IAR’s disasm tool to generate the instruction automatically:
ielftool --disasm your_project.out > disassembly.txtOpen the disassembly and look for the call site—you’ll see the
BL Barinstruction alongside its machine code.- High 16 bits:
Scenario 2: Extract raw machine code from a .map address
To get the actual machine code bytes at a function’s address (from .map) from your .hex file:
- Convert the
.hexto.bin(as in Step 2 of Section I). - Subtract the Flash base address (
0x08000000) from the function’s address to get the offset in the.binfile. - Jump to that offset in the hex editor—those bytes are the raw machine code for the function’s start.
Quick Tips
- Ignore the green CRC regions in your hex diffs—code changes will always trigger CRC updates, which is expected.
- If you have access to IAR’s debugger, you can set a breakpoint at the call site and inspect the instruction directly to confirm the replacement.
内容的提问来源于stack exchange,提问作者Guillaume D

