I am a beginner and I am studying 32-bit ARM as a part of my Computer Organization course. The meaning for B 25
or BEQ 25
is given as go-to PC + 8 + 100
. I understand what that 100
means. It is the offset, as ARM is byte addressed we need to increment the Program Counter by 25*4
. But what does that +8
mean? Can someone help me with this?
For real pipeline reasons possibly but today for reverse compatibility the pc is "two ahead". Two instructions ahead and for full sized instructions that is 4+4 or 8 bytes. Think fetch, decode, execute, by the time you get to execute the pc is two ahead.
Assembly language is specific to the assembler not the target. B 25 is a strange operand on that branch instruction, but based on your question the assumption is that is the immediate encoded in the instruction which is units of words. The destination address would then be PC (OF THE B 25 INSTRUCTION!!!) plus 25*4 plus 8. 25 * 4 is because 4 bytes per word. So the destination address is PC of the instruction plus 100 plus 8.
Disassembly of section .text:
00000000 <skip-0x24>:
0: e1a00000 nop ; (mov r0, r0)
4: e1a00000 nop ; (mov r0, r0)
8: e1a00000 nop ; (mov r0, r0)
c: e1a00000 nop ; (mov r0, r0)
10: ea000003 b 24 <skip>
14: e1a00000 nop ; (mov r0, r0)
18: e1a00000 nop ; (mov r0, r0)
1c: e1a00000 nop ; (mov r0, r0)
20: e1a00000 nop ; (mov r0, r0)
00000024 <skip>:
24: eafffffe b 24 <skip>
The encoding here:
10: ea000003 b 24 <skip>
shows a 3 as an immediate and the address of the instruction is 0x10 so
0x10 + (3*4) + 8 = 0x10+12+8= 0x10+20 = 0x10+0x14 = 0x24
this one has a negative number encoded 0xFFFFFFFE times 8 is 0xFFFFFFF8
24: eafffffe b 24 <skip>
so 0x24 + 0xFFFFFFF8 + 8 = 0x24
Note that b 24 in the disassembly means branch to address 0x24 not the 25 like your question implies as an immediate.
And for thumb mode they did two ahead as well with 16 bits or two bytes per instruction, 4 bytes ahead 2+2.
Disassembly of section .text:
00000000 <skip-0x12>:
0: 46c0 nop ; (mov r8, r8)
2: 46c0 nop ; (mov r8, r8)
4: 46c0 nop ; (mov r8, r8)
6: 46c0 nop ; (mov r8, r8)
8: e003 b.n 12 <skip>
a: 46c0 nop ; (mov r8, r8)
c: 46c0 nop ; (mov r8, r8)
e: 46c0 nop ; (mov r8, r8)
10: 46c0 nop ; (mov r8, r8)
00000012 <skip>:
12: e7fe b.n 12 <skip>
so for this one (two bytes per instruction so 3 * 2)
8: e003 b.n 12 <skip>
0x08 + (0x3<<1) + 4 = 0x08 + 0x6 + 4 = 0x12
Other instruction sets might fake the pc during execution to be address of the instruction, or most often you see it pointing at the next instruction. It is all arbitrary, it is what it is and your code or certainly the machine code offsets have to conform to the architecture.
Short answer look at the acorn docs, three stage pipeline, so think fetch, decode, execute so by the time you execute the pc is fetching two instructions ahead. And the non-acorn ARM continued with that scheme despite having deeper pipes.
Instructions a,b,c,d (not real instructions just for demonstration purposes)
0x10 a
0x14 b
0x18 c
0x1C d
PC
0x10 fetch a
0x14 fetch b decode a
0x18 fetch c decode b execute a
0x1C fetch d decode c execute b
So instruction a lives at address 0x10 but when it executes the pc is 0x18. This is the 8 byte difference that gets added into the encoding.