1、链接地址和运行地址1、运行地址链接地址:他们两个是等价的,只是两种不同的说法。2、加载地址存储地址:他们两个是等价的,也是两种不同的说法。运行地址:程序在SRAM、SDRAM中执行时的地址。就是执行这条指令时,PC应该等于这个地址,换句话说,PC等于这个地址时,这条指令应该保存在这个地址内。加载地址:程序保存在Nand flash中的地址。位置无关码:B、BL、MOV都是位置位置无关码。位置有关码:LDR PC,=LABEL等类似的代码都是位置有关码。下面我们来看看一个Makefile文件sdram.bin : head.S leds.c arm-linux-gcc -c -o head.o
2、head.S arm-linux-gcc -c -o leds.o leds.c arm-linux-ld -Ttext 0x30000000 head.o leds.o -o sdram_elf arm-linux-objcopy -O binary -S sdram_elf sdram.bin arm-linux-objdump -D -m arm sdram_elf sdram.disclean:rm -f sdram.dis sdram.bin sdram_elf *.o我们可以看到sdram_elf的代码段是从0x30000000地址开始存放,这个地址我们称之为运行地址。为什么从这个
3、地址开始存放,因为SDRAM的起始地址是0x30000000.下面来看看一个启动代码* File:head.S 功能:设置SDRAM,将程序复制到SDRAM,然后跳到SDRAM继续执行*.equ MEM_CTL_BASE, 0x48000000.equ SDRAM_BASE, 0x30000000.text.global _start_start:bl disable_watch_dog 关闭WATCHDOG,否则CPU会不断重启 bl memsetup 设置存储控制器 bl copy_steppingstone_to_sdram 复制代码到SDRAM中ldr pc, =on_sdram 跳到
4、SDRAM中继续执行on_sdram: ldr sp, =0x34000000 设置堆栈 bl mainhalt_loop: b halt_loopdisable_watch_dog: 往WATCHDOG寄存器写0即可 mov r1, #0x53000000 mov r2, #0x0 str r2, r1 mov pc, lr 返回copy_steppingstone_to_sdram: 将Steppingstone的4K数据全部复制到SDRAM中去 Steppingstone起始地址为0x00000000,SDRAM中起始地址为0x30000000 mov r1, #0 ldr r2, =S
5、DRAM_BASE mov r3, #4*10241: ldr r4, r1,#4 从Steppingstone读取4字节的数据,并让源地址加4 str r4, r2,#4 将此4字节的数据复制到SDRAM中,并让目地地址加4 cmp r1, r3 判断是否完成:源地址等于Steppingstone的未地址? bne 1b 若没有复制完,继续 mov pc, lr 返回memsetup: 设置存储控制器以便使用SDRAM等外设 mov r1, #MEM_CTL_BASE 存储控制器的13个寄存器的开始地址 adrl r2, mem_cfg_val 这13个值的起始存储地址 add r3, r1
6、, #52 13*4 = 541: ldr r4, r2, #4 读取设置值,并让r2加4 str r4, r1, #4 将此值写入寄存器,并让r1加4 cmp r1, r3 判断是否设置完所有13个寄存器 bne 1b 若没有写成,继续 mov pc, lr 返回.align 4mem_cfg_val: 存储控制器13个寄存器的设置值 .long 0x22011110 BWSCON .long 0x00000700 BANKCON0 .long 0x00000700 BANKCON1 .long 0x00000700 BANKCON2 .long 0x00000700 BANKCON3 .l
7、ong 0x00000700 BANKCON4 .long 0x00000700 BANKCON5 .long 0x00018005 BANKCON6 .long 0x00018005 BANKCON7 .long 0x008C07A3 REFRESH .long 0x000000B1 BANKSIZE .long 0x00000030 MRSRB6 .long 0x00000030 MRSRB7下面来看看反汇编代码sdram_elf: file format elf32-littlearmDisassembly of section .text:30000000 :30000000: eb0
8、00005 bl 3000001c 30000004: eb000010 bl 3000004c 30000008: eb000007 bl 3000002c 3000000c: e59ff090 ldr pc, pc, #144 ; 300000a4 30000010 :30000010: e3a0d30d mov sp, #872415232 ; 0x3400000030000014: eb000033 bl 300000e8 30000018 :30000018: eafffffe b 30000018 3000001c :3000001c: e3a01453 mov r1, #1392
9、508928 ; 0x5300000030000020: e3a02000 mov r2, #030000024: e5812000 str r2, r130000028: e1a0f00e mov pc, lr3000002c :3000002c: e3a01000 mov r1, #030000030: e3a02203 mov r2, #805306368 ; 0x3000000030000034: e3a03a01 mov r3, #4096 ; 0x100030000038: e4914004 ldr r4, r1, #43000003c: e4824004 str r4, r2,
10、#430000040: e1510003 cmp r1, r330000044: 1afffffb bne 30000038 30000048: e1a0f00e mov pc, lr3000004c :3000004c: e3a01312 mov r1, #1207959552 ; 0x4800000030000050: e28f2018 add r2, pc, #2430000054: e1a00000 nop ; (mov r0, r0)30000058: e2813034 add r3, r1, #52 ; 0x343000005c: e4924004 ldr r4, r2, #430
11、000060: e4814004 str r4, r1, #430000064: e1510003 cmp r1, r330000068: 1afffffb bne 3000005c 3000006c: e1a0f00e mov pc, lr30000070 :30000070: 22011110 andcs r1, r1, #430000074: 00000700 andeq r0, r0, r0, lsl #1430000078: 00000700 andeq r0, r0, r0, lsl #143000007c: 00000700 andeq r0, r0, r0, lsl #1430
12、000080: 00000700 andeq r0, r0, r0, lsl #1430000084: 00000700 andeq r0, r0, r0, lsl #1430000088: 00000700 andeq r0, r0, r0, lsl #143000008c: 00018005 andeq r8, r1, r530000090: 00018005 andeq r8, r1, r530000094: 008c07a3 addeq r0, ip, r3, lsr #1530000098: 000000b1 strheq r0, r0, -r13000009c: 00000030
13、andeq r0, r0, r0, lsr r0300000a0: 00000030 andeq r0, r0, r0, lsr r0300000a4: 30000010 andcc r0, r0, r0, lsl r0300000a8: e1a00000 nop ; (mov r0, r0)300000ac: e1a00000 nop ; (mov r0, r0)300000b0 :300000b0: e52db004 push fp ; (str fp, sp, #-4!)300000b4: e28db000 add fp, sp, #0300000b8: e24dd00c sub sp,
14、 sp, #12300000bc: e50b0008 str r0, fp, #-8300000c0: ea000002 b 300000d0 300000c4: e51b3008 ldr r3, fp, #-8300000c8: e2433001 sub r3, r3, #1300000cc: e50b3008 str r3, fp, #-8300000d0: e51b3008 ldr r3, fp, #-8300000d4: e3530000 cmp r3, #0300000d8: 1afffff9 bne 300000c4 300000dc: e28bd000 add sp, fp, #
15、0300000e0: e8bd0800 pop fp300000e4: e12fff1e bx lr300000e8 :300000e8: e92d4800 push fp, lr300000ec: e28db004 add fp, sp, #4300000f0: e24dd008 sub sp, sp, #8300000f4: e3a03000 mov r3, #0300000f8: e50b3008 str r3, fp, #-8300000fc: e59f3030 ldr r3, pc, #48 ; 30000134 30000100: e3a02b55 mov r2, #87040 ;
16、 0x1540030000104: e5832000 str r2, r330000108: e59f0028 ldr r0, pc, #40 ; 30000138 3000010c: ebffffe7 bl 300000b0 30000110: e59f3024 ldr r3, pc, #36 ; 3000013c 30000114: e3a02000 mov r2, #030000118: e5832000 str r2, r33000011c: e59f0014 ldr r0, pc, #20 ; 30000138 30000120: ebffffe2 bl 300000b0 30000
17、124: e59f3010 ldr r3, pc, #16 ; 3000013c 30000128: e3a02e1e mov r2, #480 ; 0x1e03000012c: e5832000 str r2, r330000130: eafffff4 b 30000108 30000134: 56000010 undefined instruction 0x5600001030000138: 00007530 andeq r7, r0, r0, lsr r53000013c: 56000014 undefined instruction 0x56000014Disassembly of s
18、ection .ARM.attributes:00000000 : 0: 00002541 andeq r2, r0, r1, asr #10 4: 61656100 cmnvs r5, r0, lsl #2 8: 01006962 tsteq r0, r2, ror #18 c: 0000001b andeq r0, r0, fp, lsl r0 10: 00543405 subseq r3, r4, r5, lsl #8 14: 01080206 tsteq r8, r6, lsl #4 18: 04120109 ldreq r0, r2, #-265 ; 0x109 1c: 011501
19、14 tsteq r5, r4, lsl r1 20: 01180317 tsteq r8, r7, lsl r3 24: Address 0x00000024 is out of bounds.Disassembly of section .comment:00000000 : 0: 3a434347 bcc 10d0d24 4: 74632820 strbtvc r2, r3, #-2080 ; 0x820 8: 312d676e teqcc sp, lr, ror #14 c: 312e362e teqcc lr, lr, lsr #12 10: 2e342029 cdpcs 0, 3,
20、 cr2, cr4, cr9, 1 14: 00332e34 eorseq r2, r3, r4, lsr lr当我们从Nand flash启动时,硬件会自动将Nand flash前4kB代码拷贝到片内SRAM中,然后CPU从SRAM的0x00000000地址处开始执行程序。在这里我想纠正一个错误的观点,网上很多人都说是CPU自动把Nand flash前4kB代码拷贝到片内SRAM中,其实不然,是Nand flash控制器完成的,这个过程中CPU根本就没有参与 。通过上面的Makefile文件,我们可以知道 bl disable_watch_dog这条指令的运行地址是0x30000000,但是
21、它现在保存在SRAM的0x00000000的地址处,那么这条指令能够正确执行吗?of course,why?因为这条指令bl disable_watch_dog是位置无关码,虽然它的运行地址是在SDRAM中的0x30000000,但是它可以在Steppingstone中执行。这条指令的功能是跳转到标号disable_watch_dog处执行,它是一个相对跳转,PC=当前PC的值+偏移量OFFSET。其中当前PC的值等于下两条指令的地址,通过反汇编可以看到下两条指令的地址为0x0000 0008,而不是0x3000 0008.因为现在指令是保存在SRAM中。这条指令的机器码为eb00 0005,
22、将机器码低24位按符号位扩展成32位得到0x0000 00005.然后将0x0000 0005左移2位得到0x0000 0014。这个值就是偏移量OFFSET=0X0000 0014。所以PC=0X0000 0008+0X0000 0014=0X0000 001c.那么CPU就会到SRAM中的0x0000 001c地址处执行程序。可以发现bl指令依赖当前PC的值,这个特性使得bl指令不依赖指令的运行地址。所以接下来的bl mensetup ,bl cope_steppingstone_to_sdram都能够执行。接下来的ldr pc,=on_sdram是一条位置有关码,经过反汇编可以看到,它是
23、当前pc的值+偏移量,得到一个地址Addr,然后从内存中的这个地址去取数据Data赋给pc。现在我们计算一下Addr这个地址。Addr=当前PC的值+144。当前PC的值等于下两条指令的地址0x0000 0014,而不是0x3000 0014,因为现在程序是保存在SRAM中。所以Addr=0x0000 0014+144=0x0000 0014+0x0000 0090=0x0000 00a4.那么这个地址0x0000 00a4中保存了什么数据。通过反汇编可以看到SRAM中的0x0000 00a4这个地址保存的机器码为30000010,所以cpu会跳转到0x30000010这个地址处执行程序。这个地址0x30000010是在SDRAM中,这样程序就跳到SDRAM中去了。因为我们前面的指令 bl cope_stepping_to_sdram 已经把SRAM中4kB的程序拷贝到了SDRAM中,所以现在SDRAM中有程序了。但是如果在程序的开头放置一条这样的指令:ldr pc,=disable_watch_dog ,那么整个程序就不能够正确执行了。why?我们先来看看启动代码* File:head.S 功能:设置SDRAM,将程序复制到SDRAM,然后跳到SDRAM继续执行*
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1