EmbDev.net

Forum: ARM programming with GCC/GNU tools GCC and LDR problem


von Armand I. (iostrym)


Rate this post
useful
not useful
Hi everyone, I've read in the Assembler Developper Suite User guide
that:

********
LDR Rd,=const is a pseudo instruction and that in fact, the assembler
will use MOV or MVN instead of LDR if the constant is 8 bits. If
constant is 32 bits longs it is also said that the assembler will:

- place the value in a literal pool ( a portion of memory embedded in
the code to hold constant value)
- generates an LDR instruction with a program relative address that
reads the constant from the literal pool.
***********

My question is :
Is it the same for GCC ? Is it possible to use LDR Rd,=const and gcc
will choose between LDR or MOV ?

Are these modification specific to the assembler used (Gcc, Assembler
Developper Suite, etc.) or are these things the same for all assembler
softwares ?

Thanks very much for your help !

PS: If someone have a User Guide document for GCC specific to ARM it
would help me a lot. Thanks in advance.

Best Regards,

von Clifford S. (clifford)


Rate this post
useful
not useful
> PS: If someone have a User Guide document for GCC specific to ARM it
> would help me a lot. Thanks in advance.
The GCC user guide is generic. It has sections for features and aspects
specific to a particular target. http://gcc.gnu.org/onlinedocs/

However the GCC guide will not describe the assembler. You need the gas
user guide for that, but again it is generic and does describe the
instruction set of a particular processor. You could always try it - it
might be quicker! But as gas is primarily intended as a back end for the
GCC, and supports many targets, I doubt it would implement such 'user
friendly' and target specific features.


Clifford

von Armand I. (iostrym)


Rate this post
useful
not useful
Thanks you very much for your help.

I would like to compile my boot.S to test how the assembler will manage

LDR Rd, =const

So as my target is an ARM7TDMI and the gcc version is 3.3.5, what should
be the command line to use in order to compile boot.S :

arm-elf-as boot.S ?

arm-elf-gcc boot.S ?

Thanks in advance for your help.

Regards,

Clifford Slocombe wrote:
>> PS: If someone have a User Guide document for GCC specific to ARM it
>> would help me a lot. Thanks in advance.
> The GCC user guide is generic. It has sections for features and aspects
> specific to a particular target. http://gcc.gnu.org/onlinedocs/
>
> However the GCC guide will not describe the assembler. You need the gas
> user guide for that, but again it is generic and does describe the
> instruction set of a particular processor. You could always try it - it
> might be quicker! But as gas is primarily intended as a back end for the
> GCC, and supports many targets, I doubt it would implement such 'user
> friendly' and target specific features.
>
>
> Clifford

von Martin Thomas (Guest)


Rate this post
useful
not useful
armand iostrym wrote:

> I would like to compile my boot.S to test how the assembler will manage
>
> LDR Rd, =const
>
> So as my target is an ARM7TDMI and the gcc version is 3.3.5, what should
> be the command line to use in order to compile boot.S :
>
> arm-elf-as boot.S ?
>
> arm-elf-gcc boot.S ?

Something like arm-elf-as -marm7dtmi -o objectfile.o assemblersource.s

But you can just take one of the example-applications (from my web-pages
or from the WinARM examples directory) and play around in the
startup.S/crt0.S-Files. The makefiles included in the archive create
list-files, a map-file and a dissassembly on "make all" so you will see
how the LDR gets assembled. As fas as I have seen from my little
arm-assembler tests everything is handled as explained in the documents
from arm.com about LDR.

Martin Thomas

von Armand I. (iostrym)


Rate this post
useful
not useful
Thanks,

Is your website here ?

http://gandalf.arubi.uni-kl.de/avr_projects/arm_projects/

because the projet link doesn't work :
http://gandalf.arubi.uni-kl.de/avr_projects/arm_projects/www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects

If such a remplacement was done for example

LDR rn,=const remplaced by MOV, rn,0b00000001

In wich file would it be possible to see the result ? after the assembly
I presume  I get an object file (a binary file) that I could see with

od

von Stefan (Guest)


Rate this post
useful
not useful
Some makefiles have options to make a *.lss file too which contain a
listing, but this is more useful for C source files.

Better you use the tool objdump from the gnu binutils to disassemble the
object file
(http://sourceware.org/binutils/docs-2.16/binutils/objdump.html)

arm-elf-objdump -d a.out > a.out.listing

von Armand I. (iostrym)


Rate this post
useful
not useful
Thanks, objdump is making exactly what I need

arm-elf-objdump -d boot.o :

boot.o:     file format elf32-littlearm

Disassembly of section .text:

00000000 <_start>:
   0:   e3a000d3        mov     r0, #211        ; 0xd3
   4:   e129f000        msr     CPSR_all, r0
   8:   e59fc014        ldr     r12, [pc, #14]  ; 24 <Remap_address+0x4>
   c:   e28f0008        add     r0, pc, #8      ; 0x8
  10:   e28f1008        add     r1, pc, #8      ; 0x8
  14:   e5810000        str     r0, [r1]
  18:   e1a0f00c        mov     pc, r12

0000001c <Remap_command>:
  1c:   00000001        andeq   r0, r0, r1

00000020 <Remap_address>:
  20:   20000000        andcs   r0, r0, r0
  24:   000fffff        streqsh pc, [pc], -pc

So I can see that "ldr  r12,=0x000FFFFF" has been remplaced by
 8:   e59fc014        ldr     r12, [pc, #14]  ; 24 <Remap_address+0x4>
24:   000fffff        streqsh pc, [pc], -pc

So an offset to the PC give acces to the data to load into r12. If the
offset has been to high, an error might be generated.

This disassembly show me another interogation:

--> each instruction and data have an adress but these are not real
adresses because the linker hasn't yet proceeded. right ?
--> I don't specify .data, .text and .bss section in my assembly file.
As I can read at the beginning of the disassembly file, all is put in
the .text section. even datas. So by default, if no section are defined,
everything is put is a .text section even datas and non initialized
datas. Am I right ?

Thanks a lot for your help

von Stefan (Guest)


Rate this post
useful
not useful
armand iostrym wrote:
> --> each instruction and data have an adress but these are not real
> adresses because the linker hasn't yet proceeded. right ?

Yes. The code from several object files is merged by the linker, the
addresses must not be final in this stage.
http://www.informatik.uni-hamburg.de/RZ/software/gnu/gcc/as_4.html#SEC41

> --> I don't specify .data, .text and .bss section in my assembly file.

Why?

> As I can read at the beginning of the disassembly file, all is put in
> the .text section. even datas. So by default, if no section are defined,
> everything is put is a .text section even datas and non initialized
> datas. Am I right ?

Remember for later usage: With -d objdump doesn't try to disassemble all
sections. Use -D when you want to do this. Read the manual for objdump
in order to unleash its power ;-)

> 00000020 <Remap_address>:
>   20:   20000000        andcs   r0, r0, r0
>   24:   000fffff        streqsh pc, [pc], -pc

These opcodes are not what you want to see here. At label Remap_address
are two 32 bit values. Remap_address is a pointer to these values. You
need the second value, therefore the load instruction uses a relative
address mode.

>    8:   e59fc014        ldr     r12, [pc, #14]  ; 24 <Remap_address+0x4>

#14 is a relative jump offset - get value 14 (0x0D) further than the
current pc is. Remember in this situation at position 0x8: pc is already
at 0x10: because of prefetching.

I think a object file has default text, data and bss sections (which may
be empty). Some other assembler directives such as .lcomm put data in
other sections than the .text section.

von Armand I. (iostrym)


Rate this post
useful
not useful
Stefan wrote:
> armand iostrym wrote:
>> --> each instruction and data have an adress but these are not real
>> adresses because the linker hasn't yet proceeded. right ?
>
> Yes. The code from several object files is merged by the linker, the
> addresses must not be final in this stage.
> http://www.informatik.uni-hamburg.de/RZ/software/gnu/gcc/as_4.html#SEC41
>
>> --> I don't specify .data, .text and .bss section in my assembly file.
>
> Why?
>

I thought that by default, the assembly would separate instruction and
data and put instruction in a .text section and data in a .data section.
As I can read with -D objdump. My object file contains by default 2
sections: .text contains all the code and data and the .data section is
empty. It seems there is no .bss section made by default.

I understand at the moment that objdump has seen 20000000 and 000FFFFF
in the .text section so i think that there are instruction that's why he
put gave the correspondant instruction. To be clearer, I must put adress
20 and 24 in the .data section.

To do that I have two possibility:

--> use the ".data" and ".text" assembler control directive in the
assembly file

--> specify in the linker script file to put some label in .text section
and other label such as <Remap_address> in the .data section.

Do you know which one is the better ?

The original file is the following:

#define I_BIT   (1 << 7)
#define F_BIT   (1 << 6)
#define ARM_MODE_SVC 0x13 // SVC -> supervisor mode.

  .global  _start // make symbol visible to the linker

_start:
  mov   r0, #(ARM_MODE_SVC | I_BIT | F_BIT )    /* disable interrupts. 
r1
= 11010011*/
  msr   cpsr, r0

  /* Load the address where to jump */
  ldr  r12, uClinux_kernel_decompression_address  /* get the real jump
address ( after remap ) */

  adr r0, Remap_command
  adr r1, Remap_address
    str r0, [r1]        /* REMAP command */

  mov  pc, r12      /* jump to the uClinux_kernel_decompression address 
and
break the pipeline */

Remap_command:
  .long  0x00000001    /* REMAP command */

Remap_address:
    .long  0x20000000  /* REMAP address */


Best regards,


>> As I can read at the beginning of the disassembly file, all is put in
>> the .text section. even datas. So by default, if no section are defined,
>> everything is put is a .text section even datas and non initialized
>> datas. Am I right ?
>
> Remember for later usage: With -d objdump doesn't try to disassemble all
> sections. Use -D when you want to do this. Read the manual for objdump
> in order to unleash its power ;-)
>
>> 00000020 <Remap_address>:
>>   20:   20000000        andcs   r0, r0, r0
>>   24:   000fffff        streqsh pc, [pc], -pc
>
> These opcodes are not what you want to see here. At label Remap_address
> are two 32 bit values. Remap_address is a pointer to these values. You
> need the second value, therefore the load instruction uses a relative
> address mode.
>
>>    8:   e59fc014        ldr     r12, [pc, #14]  ; 24 <Remap_address+0x4>
>
> #14 is a relative jump offset - get value 14 (0x0D) further than the
> current pc is. Remember in this situation at position 0x8: pc is already
> at 0x10: because of prefetching.
>
> I think a object file has default text, data and bss sections (which may
> be empty). Some other assembler directives such as .lcomm put data in
> other sections than the .text section.

von Stefan (Guest)


Rate this post
useful
not useful
armand iostrym wrote:
> I thought that by default, the assembly would separate instruction and
> data and put instruction in a .text section and data in a .data section.

You must "teach" the assembler what is code and what is data. Then the
assembler can sort things in the code section and things in the data
section. You teach the assembler with assembler directives i.e. with
.lcomm you teach that you want x bytes in a .bss section...

> As I can read with -D objdump. My object file contains by default 2
> sections: .text contains all the code and data and the .data section is
> empty. It seems there is no .bss section made by default.

OK.

> I understand at the moment that objdump has seen 20000000 and 000FFFFF
> in the .text section so i think that there are instruction that's why he
> put gave the correspondant instruction.

Yes. Most 32-bit values correspond to a assembler instruction. And the
disassembler will do its job even when it gets blank 32-bit values which
are not intended as opcodes.

> To be clearer, I must put adress
> 20 and 24 in the .data section.

Not at all. Remember, you are working with startup code. At the time
this code is running, you have a blank system. You are trying to pull
the system out of the ROM first. There is no data section or better
spoken the data is somewhere in the ROM and not yet transfered into the
correct data position in RAM. It is correct to have these two data
values in the code section. You only have to read the disassembler
listing for address 0x20 and 0x24 with a grain of salt.

von Armand I. (iostrym)


Rate this post
useful
not useful
This could explain why in previous bootloader I have seen, the linker
script put the complet object file of the bootloader in a single section
called .init. It seems that the name of sections isn't important.
To conclude, as the bootloader is independant of the other program and
as it's a small program with not a lot of data and even no bss section,
it's no use to have data section and text section...

Sorry, I don't understand this sentence :
"You only have to read the disassembler
listing for address 0x20 and 0x24 with a grain of salt."

Is the expression 'grain of salt' a deutsh expression?

Even if I don't need to separate data and text section for the
bootloader, do you know where it is better to indicate the differents
sections ?
In the linker script or directly in the *.S file with Assembler Control
Directive such as .text, .data, .bss, etc.

Thanks and Regards,

Stefan wrote:
> armand iostrym wrote:
>> I thought that by default, the assembly would separate instruction and
>> data and put instruction in a .text section and data in a .data section.
>
> You must "teach" the assembler what is code and what is data. Then the
> assembler can sort things in the code section and things in the data
> section. You teach the assembler with assembler directives i.e. with
> .lcomm you teach that you want x bytes in a .bss section...
>
>> As I can read with -D objdump. My object file contains by default 2
>> sections: .text contains all the code and data and the .data section is
>> empty. It seems there is no .bss section made by default.
>
> OK.
>
>> I understand at the moment that objdump has seen 20000000 and 000FFFFF
>> in the .text section so i think that there are instruction that's why he
>> put gave the correspondant instruction.
>
> Yes. Most 32-bit values correspond to a assembler instruction. And the
> disassembler will do its job even when it gets blank 32-bit values which
> are not intended as opcodes.
>
>> To be clearer, I must put adress
>> 20 and 24 in the .data section.
>
> Not at all. Remember, you are working with startup code. At the time
> this code is running, you have a blank system. You are trying to pull
> the system out of the ROM first. There is no data section or better
> spoken the data is somewhere in the ROM and not yet transfered into the
> correct data position in RAM. It is correct to have these two data
> values in the code section. You only have to read the disassembler
> listing for address 0x20 and 0x24 with a grain of salt.

von Stefan (Guest)


Rate this post
useful
not useful
armand iostrym wrote:
> This could explain why in previous bootloader I have seen, the linker
> script put the complet object file of the bootloader in a single section
> called .init. It seems that the name of sections isn't important.

It isn't, but meaningful names enhance readability.

> To conclude, as the bootloader is independant of the other program and
> as it's a small program with not a lot of data and even no bss section,
> it's no use to have data section and text section...

Yes.

> Sorry, I don't understand this sentence :
> "You only have to read the disassembler
> listing for address 0x20 and 0x24 with a grain of salt."
>
> Is the expression 'grain of salt' a deutsh expression?

Grain of wisdom? You should remember that the disassembler is a "stupid"
machine and translated some data values in some funny assembler opcodes.

> Even if I don't need to separate data and text section for the
> bootloader, do you know where it is better to indicate the differents
> sections ?
> In the linker script or directly in the *.S file with Assembler Control
> Directive such as .text, .data, .bss, etc.

Both.

You should tell the assembler that some code is special. And you should
tell the linker that the special code has to be linked not at a random
place within normal code but in front of all other code.

This is because the special code for a bootloader (or startup code) MUST
begin at address 0. The ARM7 expect the first instruction at address
0x00000000 when power goes up and the core is coming out of reset. At
power up real ARM7s have ROM mapped to address 0 which is remapped later
at an other address and address 0 is RAM after remap.

von Armand I. (iostrym)


Rate this post
useful
not useful
Thanks very much,

I have read that assembler directive .data and .text specify that the
following code placed below is placed in the corresponding section. As
if I can specify section in the object file given by the assembling and
then put these section in global section of the final object file made
by the linker.

If I have understand, in the linker script I can specify :

SECTIONS
{
    .text 0x00000000 {
     Symbol to place in this section
     or/and
     object file to place in this section
     or/and
     *(.text) can specify to place in this .text section all the .text
section of            each object file that compose the project.
     }

    .data 0x00000111 (for example) {
    ...
    }
}

My problem is that I use the assembler directive .data and .text in my
boot.s (there is no need but it's to test) :

#define I_BIT   (1 << 7)
#define F_BIT   (1 << 6)
#define ARM_MODE_SVC 0x13 // SVC -> supervisor mode.

/*
    .equ I_BIT,0b10000000
    .equ F_BIT,0b1000000
    .equ ARM_MODE_SVC,0x13
*/

    .section .text

    .global    _start /* make symbol visible to the linker */
_start:
    mov     r0, #(ARM_MODE_SVC | I_BIT | F_BIT )    /* disable
interrupts. r1 = 11010011*/
    msr     cpsr, r0

    /* Load the address where to jump */
    ldr    r12,=0x000FFFFF    /* get the real jump address ( after remap
) adresse de la décompression du kernel A CHANGER */

    adr r0, Remap_command
    adr r1, Remap_address
    str r0, [r1]        /* REMAP command */

    mov    pc, r12            /* jump to the
uClinux_kernel_decompression address and break the pipeline */

    .section .data

Remap_command:
    .long    0x00000001        /* REMAP command */

Remap_address:
    .long    0x20000000    /* REMAP address */


I do :

arm-elf-gcc

von Stefan (Guest)


Rate this post
useful
not useful
No problem here, your code assembles fine.
But i'm using GNUARM 4.1.0 under Windows 98SE with Cygwin 1.5.18.

von Armand I. (iostrym)


Rate this post
useful
not useful
"The ADR and ADRL pseudo-instructions enable you to generate an address,
within a certain range, ***** without performing a data load *****.[...]
The label used with ADR or ADRL must be within the same code section."
  -- ARM Developer Suite Assembler Guide

Are you sure the code generating with after assembling is working ? ie
the ARM instructions remplacing the pseudo instruction ADR are good ?

I use another pseudo intruction ldr rn,=label that is working. the
inconvenient is that it add a data in the .text section. The adress is
calculated during the assembly and store at the end of the .text
section.

a.out:     file format elf32-littlearm

Disassembly of section .text:

00008000 <_start>:
    8000:       e3a000d3        mov     r0, #211        ; 0xd3
    8004:       e129f000        msr     CPSR_all, r0
    8008:       e59fc00c        ldr     r12, [pc, #c]   ; 801c
<_start+0x1c>
    800c:       e3a00001        mov     r0, #1  ; 0x1
    8010:       e59f1008        ldr     r1, [pc, #8]    ; 8020
<_start+0x20>
    8014:       e5810000        str     r0, [r1]
    8018:       e1a0f00c        mov     pc, r12
    801c:       000fffff        streqsh pc, [pc], -pc
    8020:       00008124        andeq   r8, r0, r4, lsr #2
Disassembly of section .data:

00008124 <Remap_address>:
    8124:       20000000        andcs   r0, r0, r0


Regards,

von Stefan (Guest)


Rate this post
useful
not useful
armand iostrym wrote:

> Are you sure the code generating with after assembling is working ? ie
> the ARM instructions remplacing the pseudo instruction ADR are good ?

No. I tried only assembling your example code and didn't get the errors
you specified.

> "The ADR and ADRL pseudo-instructions enable you to generate an address,
> within a certain range, ***** without performing a data load *****.[...]
> The label used with ADR or ADRL must be within the same code section."
>   -- ARM Developer Suite Assembler Guide

This says clearly that is is not allowed to program with a section .data
like this:

>    adr r0, Remap_command
>    adr r1, Remap_address
>    str r0, [r1]         /* REMAP command */
>
>    mov    pc, r12       /* ... */
>
>    .section .data
>
>Remap_command:
>    .long    0x00000001  /* REMAP command */
>
>Remap_address:
>    .long    0x20000000  /* REMAP address */

But this is often the case with programming. Code which compiles or
assembles perfectly is not a guarantee for a working program.

von Armand I. (iostrym)


Rate this post
useful
not useful
Thanks you very much for everything. Just a question, how do you guess I
worked on     FPGA? Do you already work with it ?

Best regards,

von Stefan (Guest)


Rate this post
useful
not useful
armand iostrym wrote:
> Thanks you very much for everything. Just a question, how do you guess I
> worked on     FPGA? Do you already work with it ?
>
> Best regards,

Black magic ;-)

No, just kidding. You told it in another thread, maybe in a discussion
with Martin.

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.