Bare metal assembly - data not initialized

-1

I wrote some very simple code, aimed to work on bare metal RaspberryPi. My code consists of gpio.s (with function "flash", which turns LED on and off) and main.s, shown below.

.section .init
.globl _start
_start:
        mov sp, $0x8000
        b main
.section .text
.globl main
main:
        ldr r5, =variable
        ldr r4, [r5]
        cmp r4, $100
        bleq flash
loop:
        b loop
.section .data
.align 4
.globl variable
variable:
.word   100

So r4 should be filled with 100 => condition flag should be eq => LED should flash! But it does not. Why?

Apart from that example, function "flash" works, as well as in the case of adding these lines after "ldr r5, =variable":

mov r1, $100
str r1, [r5]

So it seems like memory is accessible, but doesn't get initialized. I would be grateful for your explanations.

Disassembly:

./build/output.elf:     file format elf32-littlearm

Disassembly of section .init:

00000000 <_start>:
   0:   e3a0d902    mov sp, #32768  ; 0x8000
   4:   ea00205c    b   817c <main>
Disassembly of section .text:

00008000 <getGpioAddr>:
    8000:   e59f0170    ldr r0, [pc, #368]  ; 8178 <flash2+0x14>
    8004:   e1a0f00e    mov pc, lr

00008008 <setGpioFunct>:
    8008:   e3500035    cmp r0, #53 ; 0x35
    800c:   93510007    cmpls   r1, #7  ; 0x7
    8010:   83a00001    movhi   r0, #1  ; 0x1
    8014:   81a0f00e    movhi   pc, lr
    8018:   e92d0030    push    {r4, r5}
    801c:   e1a02001    mov r2, r1
    8020:   e1a01000    mov r1, r0
    8024:   e92d4000    push    {lr}
    8028:   ebfffff4    bl  8000 <getGpioAddr>
    802c:   e8bd4000    pop {lr}
    8030:   e3a04000    mov r4, #0  ; 0x0

00008034 <subTen>:
    8034:   e351000a    cmp r1, #10 ; 0xa
    8038:   2241100a    subcs   r1, r1, #10 ; 0xa
    803c:   22844001    addcs   r4, r4, #1  ; 0x1
    8040:   2afffffb    bcs 8034 <subTen>
    8044:   e3a05004    mov r5, #4  ; 0x4
    8048:   e0030594    mul r3, r4, r5
    804c:   e0800003    add r0, r0, r3
    8050:   e3a05003    mov r5, #3  ; 0x3
    8054:   e0030591    mul r3, r1, r5
    8058:   e1a02312    lsl r2, r2, r3
    805c:   e3e0430e    mvn r4, #939524096  ; 0x38000000
    8060:   e3a05009    mov r5, #9  ; 0x9
    8064:   e0451001    sub r1, r5, r1
    8068:   e3a05003    mov r5, #3  ; 0x3
    806c:   e0030591    mul r3, r1, r5
    8070:   e1a04374    ror r4, r4, r3
    8074:   e5905000    ldr r5, [r0]
    8078:   e0055004    and r5, r5, r4
    807c:   e1855002    orr r5, r5, r2
    8080:   e5805000    str r5, [r0]
    8084:   e8bd0030    pop {r4, r5}
    8088:   e3a00000    mov r0, #0  ; 0x0
    808c:   e1a0f00e    mov pc, lr

00008090 <setPin>:
    8090:   e3500035    cmp r0, #53 ; 0x35
    8094:   83a00001    movhi   r0, #1  ; 0x1
    8098:   81a0f00e    movhi   pc, lr
    809c:   e92d0020    push    {r5}
    80a0:   e3500020    cmp r0, #32 ; 0x20
    80a4:   22401020    subcs   r1, r0, #32 ; 0x20
    80a8:   31a01000    movcc   r1, r0
    80ac:   23a02020    movcs   r2, #32 ; 0x20
    80b0:   33a0201c    movcc   r2, #28 ; 0x1c
    80b4:   e92d4000    push    {lr}
    80b8:   ebffffd0    bl  8000 <getGpioAddr>
    80bc:   e8bd4000    pop {lr}
    80c0:   e3a05001    mov r5, #1  ; 0x1
    80c4:   e1a05115    lsl r5, r5, r1
    80c8:   e7805002    str r5, [r0, r2]
    80cc:   e3a00000    mov r0, #0  ; 0x0
    80d0:   e8bd0020    pop {r5}
    80d4:   e1a0f00e    mov pc, lr

000080d8 <clearPin>:
    80d8:   e3500035    cmp r0, #53 ; 0x35
    80dc:   83a00001    movhi   r0, #1  ; 0x1
    80e0:   81a0f00e    movhi   pc, lr
    80e4:   e92d0020    push    {r5}
    80e8:   e3500020    cmp r0, #32 ; 0x20
    80ec:   22401020    subcs   r1, r0, #32 ; 0x20
    80f0:   31a01000    movcc   r1, r0
    80f4:   23a0202c    movcs   r2, #44 ; 0x2c
    80f8:   33a02028    movcc   r2, #40 ; 0x28
    80fc:   e92d4000    push    {lr}
    8100:   ebffffbe    bl  8000 <getGpioAddr>
    8104:   e8bd4000    pop {lr}
    8108:   e3a05001    mov r5, #1  ; 0x1
    810c:   e1a05115    lsl r5, r5, r1
    8110:   e7805002    str r5, [r0, r2]
    8114:   e3a00000    mov r0, #0  ; 0x0
    8118:   e8bd0020    pop {r5}
    811c:   e1a0f00e    mov pc, lr

00008120 <flash>:
    8120:   e92d4013    push    {r0, r1, r4, lr}
    8124:   e3a00010    mov r0, #16 ; 0x10
    8128:   e3a01001    mov r1, #1  ; 0x1
    812c:   ebffffb5    bl  8008 <setGpioFunct>
    8130:   e3a00010    mov r0, #16 ; 0x10
    8134:   ebffffe7    bl  80d8 <clearPin>
    8138:   eb000004    bl  8150 <wait>
    813c:   e3a00010    mov r0, #16 ; 0x10
    8140:   ebffffd2    bl  8090 <setPin>
    8144:   eb000001    bl  8150 <wait>
    8148:   e8bd4013    pop {r0, r1, r4, lr}
    814c:   e1a0f00e    mov pc, lr

00008150 <wait>:
    8150:   e3a0583f    mov r5, #4128768    ; 0x3f0000

00008154 <loop>:
    8154:   e2455001    sub r5, r5, #1  ; 0x1
    8158:   e3550000    cmp r5, #0  ; 0x0
    815c:   1afffffc    bne 8154 <loop>
    8160:   e1a0f00e    mov pc, lr

00008164 <flash2>:
    8164:   e92d4000    push    {lr}
    8168:   ebffffec    bl  8120 <flash>
    816c:   ebffffeb    bl  8120 <flash>
    8170:   e8bd4000    pop {lr}
    8174:   e1a0f00e    mov pc, lr
    8178:   20200000    .word   0x20200000

0000817c <main>:
    817c:   e59f500c    ldr r5, [pc, #12]   ; 8190 <loop+0x4>
    8180:   e5954000    ldr r4, [r5]
    8184:   e3540064    cmp r4, #100    ; 0x64
    8188:   0bffffe4    bleq    8120 <flash>

0000818c <loop>:
    818c:   eafffffe    b   818c <loop>
    8190:   00008194    .word   0x00008194
Disassembly of section .data:

00008194 <variable>:
    8194:   00000064    .word   0x00000064

Linker scripts, makefile etc. taken from: http://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok01.html

memory
assembly
arm
raspberry-pi
asked on Stack Overflow Jul 22, 2013 by user2607529 • edited Jul 22, 2013 by user2607529

3 Answers

0

from your link (you should not ask questions here using links, put the code in the question)

0000817c <main>:
    817c:       e59f500c        ldr     r5, [pc, #12]   ; 8190 <loop+0x4>
    8180:       e3a01064        mov     r1, #100        ; 0x64
    8184:       e3540064        cmp     r4, #100        ; 0x64
    8188:       0bffffe4        bleq    8120 <flash>

0000818c <loop>:
    818c:       eafffffe        b       818c <loop>
    8190:       000081a0        .word   0x000081a0
Disassembly of section .data:

000081a0 <variable>:
    81a0:       00000064        .word   0x00000064
        ...

you are moving r1 a 100 but comparing r4 which has not been initialized at least in this code, so that is unpredictable what will happen. if you replace that with a mov r4,[r5] it should work as desired as r5 is getting the address of the word that contains the #100 and then you read from that address into r4.

I assume you have verified that if you simply bl flash it works (not a conditional but always go there) as desired?

In this bare metal mode you definitely have access to read/write memory, no worries there.

David

answered on Stack Overflow Jul 22, 2013 by old_timer
0

Memory is normally initialized as part of the C runtime code. If you are writing bare-metal assembly without including the functionality of the C runtime then your variables in RAM will not be initialized. You need to explicitly initialize the value of variable in your own code.

answered on Stack Overflow Jul 22, 2013 by (unknown user)
0

Finally found out! Really subtle, and it's not my fault indeed. I had taken the makefile and linker script from Alex Chadwick tutorial, and the linker script looked like that:

SECTIONS {
    /*
    * First and formost we need the .init section, containing the IVT.
    */
    .init 0x0000 : {
        *(.init)
    }

    /* 
    * We allow room for the ATAGs and the stack and then start our code at
    * 0x8000.
    */
    .text 0x8000 : {
        *(.text)
    }

    /* 
    * Next we put the data.
    */
    .data : {
        *(.data)
    }

    /*
    * Finally comes everything else. A fun trick here is to put all other 
    * sections into this section, which will be discarded by default.
    */
    /DISCARD/ : {
        *(*)
    }
}

.init section was based at 0x0000, and then the .text started at 0x8000. But actually, kernel.img is loaded at address 0x8000 by Pi (real address of .init was 0x8000), so: whole .text section (as well as the following sections) were shifted - due to that fact, addresses of labels were misassumed at the assembling-linking time. Only pc-relative addressing could work, as PC was set correctly. The solution is to start the image at 0x8000:

SECTIONS {
    /*
    * First and formost we need the .init section, containing the IVT.
    */
    .init 0x8000 : {
        *(.init)
    }

    .text : {
        *(.text)
    }

    /* 
    * Next we put the data.
    */
    .data : {
        *(.data)
    }

    /*
    * Finally comes everything else. A fun trick here is to put all other 
    * sections into this section, which will be discarded by default.
    */
    /DISCARD/ : {
        *(*)
    }
}

I've just checked the template on his website and it's corrected now, so there is no point contacting him. I must have downloaded template before this correction. Thank you guys for your attempts.

answered on Stack Overflow Jul 24, 2013 by user2607529

User contributions licensed under CC BY-SA 3.0