深入分析S3C2440启动代码中大小端问题

来源:互联网 发布:中岛美嘉长相知乎 编辑:程序博客网 时间:2024/05/01 20:16

深入分析S3C2440启动代码中大小端问题

一、ADS1.2中关于大小端的设置以及对编译后的代码的影响


下面是一段代码在线段模式下编译,生成的二进制文件的内容

大端模式下编译,生成二进制文件的内容
根据上面的内容可以看出:它们的字节序是相反的,也就是说,ADS1.2中对大小端的设置会影响最终生成的二进制文件的字节序。

二、S3C2440启动代码中与大小管相关的代码

Option.inc中相关代码

[plain] view plaincopyprint?
  1. GBLL    ENDIAN_CHANGE  
  2. NDIAN_CHANGE    SETL    {FALSE}  
  3.     GBLA    ENTRY_BUS_WIDTH  
  4. NTRY_BUS_WIDTH  SETA    16  


2440init.s中相关代码
[plain] view plaincopyprint?
  1.     AREA    Init,CODE,READONLY  
  2.   
  3.     ENTRY  
  4.       
  5.     EXPORT  __ENTRY  
  6. __ENTRY  
  7. ResetEntry  
  8.     ;1)The code, which converts to Big-endian, should be in little endian code.  
  9.     ;2)The following little endian code will be compiled in Big-Endian mode.  
  10.     ;  The code byte order should be changed as the memory bus width.  
  11.     ;3)The pseudo instruction,DCD can not be used here because the linker generates error.  
  12.     ASSERT  :DEF:ENDIAN_CHANGE  
  13.     [ ENDIAN_CHANGE  
  14.         ASSERT  :DEF:ENTRY_BUS_WIDTH  
  15.         [ ENTRY_BUS_WIDTH=32  
  16.             b   ChangeBigEndian     ;DCD 0xea000007  
  17.         ]  
  18.   
  19.         [ ENTRY_BUS_WIDTH=16  
  20.             andeq   r14,r7,r0,lsl #20   ;DCD 0x0007ea00  
  21.         ]  
  22.   
  23.         [ ENTRY_BUS_WIDTH=8  
  24.             streq   r0,[r0,-r10,ror #1] ;DCD 0x070000ea  
  25.         ]  
  26.         |  
  27.         b   ResetHandler  
  28.     ]  
  29.     b   HandlerUndef    ;handler for Undefined mode  
  30.     b   HandlerSWI  ;handler for SWI interrupt  
  31.     b   HandlerPabort   ;handler for PAbort  
  32.     b   HandlerDabort   ;handler for DAbort  
  33.     b   .       ;reserved  
  34.     b   HandlerIRQ  ;handler for IRQ interrupt  
  35.     b   HandlerFIQ  ;handler for FIQ interrupt  
  36.   
  37. ;@0x20  
  38.     b   EnterPWDN   ; Must be @0x20.  
  39. ChangeBigEndian  
  40. ;@0x24  
  41.     [ ENTRY_BUS_WIDTH=32  
  42.         DCD 0xee110f10  ;0xee110f10 => mrc p15,0,r0,c1,c0,0  
  43.         DCD 0xe3800080  ;0xe3800080 => orr r0,r0,#0x80;  //Big-endian  
  44.         DCD 0xee010f10  ;0xee010f10 => mcr p15,0,r0,c1,c0,0  
  45.     ]  
  46.     [ ENTRY_BUS_WIDTH=16  
  47.         DCD 0x0f10ee11  
  48.         DCD 0x0080e380  
  49.         DCD 0x0f10ee01  
  50.     ]  
  51.     [ ENTRY_BUS_WIDTH=8  
  52.         DCD 0x100f11ee  
  53.         DCD 0x800080e3  
  54.         DCD 0x100f01ee  
  55.     ]  
  56.     DCD 0xffffffff  ;swinv 0xffffff is similar with NOP and run well in both endian mode.  
  57.     DCD 0xffffffff  
  58.     DCD 0xffffffff  
  59.     DCD 0xffffffff  
  60.     DCD 0xffffffff  
  61.     b ResetHandler  
我们可以看到,在Option.inc将ENDIAN_CHANGE设置FALSE,程序将直接运行b ResetHandler,S3C2440默认是处于小端模式,ADS1.2中的设置默认也是小段模式,一切风平浪静。
现在,我们在ADS1.2中设为打断模式,并把ENDIAN_CHANGE设置FALSE设为TURE,现在问题就来了,请看下面的分析。
在编译程序时,根据ENTRY_BUS_WIDTH宏会将下面三条指令的之一放在0地址处
bChangeBigEndian    ;DCD 0xea000007
andeq r14,r7,r0,lsl #20   ;DCD 0x0007ea00
streq r0,[r0,-r10,ror #1] ;DCD 0x070000ea
其实这三条指令的功能都是一样,只是根据数据带宽调整了字节序,都是跳转到0x24处的ChangeBigEndian执行,ChangeBigEndian的作用就是通过协处理CP15中的寄存器C1来改变S3C2440的大小端模式。
先来看一下这三条指令。因为我们已经在ADS中设置为大端模式,所以这些指令是以大端模式进行编译的,而S3C2440此时还是小端模式,S3C2440怎么能执行大端模式下的指令呢,比如bChangeBigEndian    ;DCD 0xea000007???
原因如下:
如果一个基于 ARM 芯片将存储器系统配置为其中一种存储器格式(如小端) ,而实际连接的存储器系统配置为相反的格式(如大端) ,那么只有以字为单位的指令取指、数据装载和数据保存能够可靠实现。其它的存储器访问将出现不可预期的结果。也就就是说在32位模式下,大小端模式对指令取指、数据装载和数据保存没有影响。(注意:如果实际的存储器格式与芯片的存储器格式不符时,只有以字为单位的数据存取才正确,否则将出现不可预期的结果。)
bChangeBigEndian在大端模式下机器码是0xea000007,这是32位模式下,其四个字节从低到高分别是:07 00 00 ea。那没bChangeBigEndian这条指令在8位模式下,要被小端模式的S3C2440执行,就要人为的修改为0x070000ea。在存储器中存储的顺序:从低地址到高地址分别是 07 00 00 ea,S3C2440按小端模式取指令时,取得是0xea000007。
bChangeBigEndian这条指令在16位模式下,要被小端模式的S3C2440执行,就要人为的修改为 0x0007ea00。在存储器中存储的顺序:从低地址到高地址分别是 0007 ea00,S3C2440按小端模式取指令时,取得是0xea000007。
后面修改协处理CP15中的寄存器C1的代码时类似的。

转载自http://blog.csdn.net/ce123
0 0