I am trying to learn ARM by debugging a simple piece of ARM assembly.
.global start, stack_top
start:
ldr sp, =stack_top
bl main
b .
The linker script looks like below:
ENTRY(start)
SECTIONS
{
. = 0x10000;
.text : {*(.text)}
.data : {*(.data)}
.bss : {*(.bss)}
. = ALIGN(8);
. = . +0x1000;
stack_top = .;
}
I run this on qemu arm emulator. The binary is loaded at 0x10000. So I put a breakpoint there. As soon as the bp is hit. I checked the pc register. It's value is 0x10000. Then I disassemble the instruction at 0x10000.
I see a strange comment ; 0x1000c <start+12>. What does it mean? Where does it come from?
Breakpoint 1, 0x00010000 in start ()
(gdb) i r pc
pc 0x10000 0x10000 <start>
(gdb) x /i 0x10000
=> 0x10000 <start>: ldr sp, [pc, #4] ; 0x1000c <start+12> <========= HERE
(gdb) x /i 0x10004
0x10004 <start+4>: bl 0x102b0 <main>
Then I continued to debug:
I want to see the effect of the ldr sp, [pc, #4] at 0x10000 on the sp register. So I debug as below.
From the above disassembly, I expected the value of sp to be [pc + 4], which should be the content located at 0x10000 + 4 = 0x10004. But the sp turns out to be 0x11520.
(gdb) i r sp
sp 0x0 0x0
(gdb) si
0x00010004 in start ()
(gdb) x /i $pc
=> 0x10004 <start+4>: bl 0x102b0 <main>
(gdb) i r sp
sp 0x11520 0x11520 <=================== HERE
(gdb) x /x &stack_top
0x11520: 0x00000000
So the 0x11520 value does come from the linker script symbol stack_top. But how is it related to the ldr sp, [pc,#4] instruction at 0x10000?
ADD 1 - 9:29 AM 12/20/2019
Many thanks for the detailed answer by @old_timer.
I was reading the book Embedded and Real-Time Operating Systems by K. C. Wang. I learned about the pipeline thing from this book. Quoted as below:
So, if the pipeline thing is no longer relevant today. What reason makes the pc value 2 ahead of the currently executed instruction?
I just found below thread addressing this issue:
Why does the ARM PC register point to the instruction after the next one to be executed?
Basically, it just another case that people keep making mistakes/flaws/pitfalls for themselves as they advance the technologies.
So back to this question:
- In my assembly, it is pc-relative addressing being used.
- ARM's PC pointer is 2 ahead of the currently executed instruction. (And deal with that!)
