Issue
Probably a common beginner question, and similar questions have been asked on this site, but I can't find any help on a couple points. If you have a 32-bit symbol defined with .word
, and you want to load it into register r1
, what's the conventional way to do it?
.syntax unified
.cpu cortex-m4
.thumb
/* ... */
_allones: .word 0xffffffff
test:
/* This seems to not work as expected */
ldr r1,_allones @ Value is corrupted/misaligned?
/* Two-line solution */
ldr r1,=_allones @ Loads the address of _allones into r1, not the value itself
ldr r1,[r1] @ Get value proper
My confusion is when you see tutorials like this one where only the ldr r1,=_allones
is used to load the value of _allones
(see "Initialization Code", first listing and explanation), and the answer I linked above which makes it seem like the first option in my example should work. Target is Cortex-M4, in Thumb mode, with unified syntax.
FWIW The ldr r1,_allones
line instead loads the last two bytes of _allones
and then the first two bytes of its address in memory, or something in that vain, I haven't looked that closely at the value.
Solution
In general, ldr r1, =sym
will load the value of the symbol sym
into r1
. (It does so by assembling the value of sym
into memory at a location called a literal pool which is fairly near to the instruction, so that it can be reached with the pc-relative literal form of the load instruction.)
But there are two different ways to define a symbol. It can be defined as a label, like sym:
, in which case the value of the symbol is the address that it labels (which may not actually be known until the linking stage of the build). That's the case in your code. But a symbol can also be defined as a numerical constant, like sym EQU 12345
, in which case its value is simply the number 12345. That's what is happening in the tutorial.
So if you want to load 0xffffffff
into r1
, the two possibilities would look as follows:
allones:
.word 0xffffffff
...
ldr r1, =allones @ now r1 contains the address where 0xffffffff is stored
ldr r1, [r1] @ load from that address
or
allones EQU 0xffffffff
...
ldr r1, =allones
Of course, if the value actually is 0xffffffff
, then it would be best to just write mov r1, 0xffffffff
, or allones equ 0xffffffff ; mov r1, allones
. (The #
is optional in some assemblers.) The mov
immediate instruction has a limited set of values that can be used as the immediate, but 0xffffffff
is one of them. Some assemblers might optimize ldr r1, =const
into mov r1, const
when the constant has an appropriate value.
Answered By - Nate Eldredge Answer Checked By - Robin (PHPFixing Admin)
0 Comments:
Post a Comment
Note: Only a member of this blog may post a comment.