I am learning ARM Assembly Language. I do is write a program in c and compile it to look at the Assembly file. Below is such a compiled snippet from a program and it has this ldr r0, [pc, #28]
. Here I need help in understanding this PC thing. I know it means the program counter but I can not understand the actual purpose of the instruction.
1000037c <main>: 1000037c: b570 push {r4, r5, r6, lr} . . 10000388: f000 f812 bl 100003b0 1000038c: 4807 ldr r0, [pc, #28] 1000038e: 626c str r4, [r5, #36] . .
In the C program, it must have been an integer (>256) maybe, I don't fully understand this concept. Thanks in advance.
What you're looking at is a pre-indexed load instruction, using the value of the pc
register as the base address.
Any time your code needs to load a "large" immediate value into a register, you're likely to see something like this in tandem with a data declaration somewhere below it. You haven't shown it in your snippet, but scroll down a little bit in the assembly and you'll probably see something like:
.word 0x12345678
Or even possibly the value of a label
_some_label: ...
...
.word _some_label
As long as the .word
value is close enough in memory to where the pc
is currently executing, you can load the data using a relative offset. In your example, there should be a data word at offset 32 from where that load instruction is placed (adding 8 as per the ARM ISA for PC relative addressing).
In general this approach for loading immediate values can be tricky when you're writing assembly by hand (since you need to keep track of the exact relative offsets from where your instructions are placed), but compilers can do this very reliably, which is why you often see this in compiler-generated assembly.
This question also serves as a good reference for this, and I highly recommend you check it out.