Why runtime function address is off by 1 w.r.t. elf disassembly?

Hi all.
The runtime address of a sketch function shows up as 00080181 hex while the disassembled adr is 00080180.

  1. I would expect the elf file disassembly to show the exact placement of code in the memory. Please correct me if I am wrong.
  2. Why the cpu prefers dealing with odd addresses for code? What am I missing here?

Here is the sketch, parts of disassembled code and the program output:-

==============================
The sketch_oct05b_funcAdrVerif
==============================

volatile uint32_t   janCount=0;
void janFunc( void)
{
    if( janCount > 20)
        janCount = 0;
}

void (*pFunc)( void) = NULL;

void myTest( void)
{
    printf( " Address of janFunc(): %08X\n", &janFunc);
    pFunc = &janFunc;

    printf( " Calling *pFunc at %08X\n", pFunc);
    delay( 200);    //  Allow printfs to complete on serial.
    (*pFunc)();
    printf( " Returned from *pFunc\n");
}

void setup() {
  // put your setup code here, to run once:
    cpu_irq_enable();
    // Open serial communications and wait for port to open:
    Serial.begin(9600);
    delay(200);
    Serial.println( "Starting Func Adr Verification.\n");
    myTest();
}

void loop() {
  // put your main code here, to run repeatedly: 
  
}


=============================================================================
Relevant parts of disassembly of sketch_oct05b_funcAdrVerif.cpp.elf using the command line below:-
  arm-none-eabi-objdump -t -x -d sketch_oct05b_funcAdrVerif.cpp.elf
=============================================================================


00080180 <_Z7janFuncv>:
   80180:	4b03      	ldr	r3, [pc, #12]	; (80190 <_Z7janFuncv+0x10>)
   80182:	681a      	ldr	r2, [r3, #0]
   80184:	2a14      	cmp	r2, #20
   80186:	d901      	bls.n	8018c <_Z7janFuncv+0xc>
   80188:	2200      	movs	r2, #0
   8018a:	601a      	str	r2, [r3, #0]
   8018c:	4770      	bx	lr
   8018e:	bf00      	nop
   80190:	20070558 	.word	0x20070558

00080194 <loop>:
   80194:	4770      	bx	lr
	...

00080198 <_Z6myTestv>:
   80198:	b510      	push	{r4, lr}
   8019a:	490a      	ldr	r1, [pc, #40]	; (801c4 <_Z6myTestv+0x2c>)
   8019c:	480a      	ldr	r0, [pc, #40]	; (801c8 <_Z6myTestv+0x30>)
...
...

=============
Runtime Output:
=============

Starting Func Adr Verification.

 Address of janFunc(): 00080181
 Calling *pFunc at 00080181
 Returned from *pFunc

Thanks.

I may have found my answer... need to thoroughly read the Chapter-7 of SAM3X/A Datasheet but not having enough time.

I suspect the code addresses are always divisible by 2 and that leaves the bit-0 of the instruction pointer (a code address pointer in general) a tacitly assumed 0 by the cpu. So, the bit-0 is used for carrying some other info (may be user/supervisor mode).

This answers both my questions... unless someone corrects me. :~

On ARM the last bit in the address on a jump tells the processor whether the instructions are in ARM (32-bit) or Thumb (16-bit) format. The SAM3X only supports Thumb so the last bit in a jump address should always be 1.

Thanks to stimmer for the full explanation! :slight_smile:

By the way, I wrote something junk about the instruction pointer. It has little to do in this context -- the decoder was in the back of my mind when I typed out the post in a hurry.