-1

我写了一些非常简单的代码,旨在在裸机 RaspberryPi 上工作。我的代码由 gpio.s(具有“flash”功能,可以打开和关闭 LED)和 main.s 组成,如下所示。

.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

所以 r4 应该填充 100 => 条件标志应该是 eq => LED 应该闪烁!但事实并非如此。为什么?

除了该示例之外,函数“flash”以及在“ldr r5, =variable”之后添加这些行的情况下也有效:

mov r1, $100
str r1, [r5]

所以看起来内存是可访问的,但没有被初始化。我将不胜感激您的解释。

拆卸:

./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

链接器脚本、makefile 等取自:http ://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok01.html

4

3 回答 3

0

终于发现了!真的很微妙,这确实不是我的错。我从 Alex Chadwick 教程中获取了 makefile 和链接器脚本,链接器脚本看起来像这样:

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 部分基于 0x0000,然后 .text 从 0x8000 开始。但实际上,kernel.img 由 Pi 加载到地址 0x8000(.init 的实际地址为 0x8000),因此:整个 .text 部分(以及以下部分)被移动 - 由于这个事实,标签的地址被错误假设在组装链接时。只有 PC 相对寻址才能工作,因为 PC 设置正确。解决方案是在 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/ : {
        *(*)
    }
}

我刚刚检查了他网站上的模板,现在已经更正了,所以联系他没有意义。我必须在更正之前下载模板。谢谢你们的尝试。

于 2013-07-24T11:30:19.727 回答
0

从你的链接(你不应该在这里使用链接提问,将代码放在问题中)

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
        ...

您正在将 r1 移动 100,但比较至少在此代码中尚未初始化的 r4,因此无法预测会发生什么。如果你用 mov r4,[r5] 替换它,它应该可以正常工作,因为 r5 正在获取包含 #100 的单词的地址,然后你从该地址读取到 r4​​。

我假设您已经验证了,如果您只是 bl flash 它可以按需要工作(不是有条件的,但总是去那里)?

在这种裸机模式下,您绝对可以访问读/写内存,不用担心。

大卫

于 2013-07-22T17:22:34.433 回答
0

内存通常作为 C 运行时代码的一部分进行初始化。如果您正在编写裸机程序集而不包括 C 运行时的功能,那么您在 RAM 中的变量将不会被初始化。您需要variable在自己的代码中显式初始化 的值。

于 2013-07-22T19:20:16.337 回答