免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1764 | 回复: 1
打印 上一主题 下一主题

深入分析S3C2440启动代码中大小端问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-02-17 23:15 |只看该作者 |倒序浏览
深入分析S3C2440启动代码中大小端问题










深入分析S3C2440启动代码中大小端问题
一、ADS1.2中关于大小端的设置以及对编译后的代码的影响



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


大端模式下编译,生成二进制文件的内容

根据上面的内容可以看出:它们的字节序是相反的,也就是说,ADS1.2中对大小端的设置会影响最终生成的二进制文件的字节序。
二、S3C2440启动代码中与大小管相关的代码
Option.inc中相关代码
  1. [plain] view plaincopyprint?<span style="white-space:pre">        </span>GBLL<span style="white-space:pre">   </span>ENDIAN_CHANGE  
  2. ENDIAN_CHANGE<span style="white-space:pre">   </span>SETL<span style="white-space:pre">   </span>{TRUE}  
  3.   
  4.   
  5. <span style="white-space:pre">        </span>GBLA<span style="white-space:pre">   </span>ENTRY_BUS_WIDTH  
  6. ENTRY_BUS_WIDTH<span style="white-space:pre"> </span>SETA<span style="white-space:pre">   </span>16  
  7. <span style="white-space:pre">                </span>GBLL<span style="white-space:pre">        </span>ENDIAN_CHANGE
  8. ENDIAN_CHANGE<span style="white-space:pre">        </span>SETL<span style="white-space:pre">        </span>{TRUE}


  9. <span style="white-space:pre">                </span>GBLA<span style="white-space:pre">        </span>ENTRY_BUS_WIDTH
  10. ENTRY_BUS_WIDTH<span style="white-space:pre">        </span>SETA<span style="white-space:pre">        </span>16
  11. 2440init.s中相关代码

  12. [plain] view plaincopyprint?    AREA    Init,CODE,READONLY  
  13.   
  14.     ENTRY  
  15.       
  16.     EXPORT  __ENTRY  
  17. __ENTRY  
  18. ResetEntry  
  19.     ;1)The code, which converts to Big-endian, should be in little endian code.  
  20.     ;2)The following little endian code will be compiled in Big-Endian mode.  
  21.     ;  The code byte order should be changed as the memory bus width.  
  22.     ;3)The pseudo instruction,DCD can not be used here because the linker generates error.  
  23.     ASSERT  :DEF:ENDIAN_CHANGE  
  24.     [ ENDIAN_CHANGE  
  25.         ASSERT  :DEF:ENTRY_BUS_WIDTH  
  26.         [ ENTRY_BUS_WIDTH=32  
  27.             b   ChangeBigEndian     ;DCD 0xea000007  
  28.         ]  
  29.   
  30.         [ ENTRY_BUS_WIDTH=16  
  31.             andeq   r14,r7,r0,lsl #20   ;DCD 0x0007ea00  
  32.         ]  
  33.   
  34.         [ ENTRY_BUS_WIDTH=8  
  35.             streq   r0,[r0,-r10,ror #1] ;DCD 0x070000ea  
  36.         ]  
  37.         |  
  38.         b   ResetHandler  
  39.     ]  
  40.     b   HandlerUndef    ;handler for Undefined mode  
  41.     b   HandlerSWI  ;handler for SWI interrupt  
  42.     b   HandlerPabort   ;handler for PAbort  
  43.     b   HandlerDabort   ;handler for DAbort  
  44.     b   .       ;reserved  
  45.     b   HandlerIRQ  ;handler for IRQ interrupt  
  46.     b   HandlerFIQ  ;handler for FIQ interrupt  
  47.   
  48. ;@0x20  
  49.     b   EnterPWDN   ; Must be @0x20.  
  50. ChangeBigEndian  
  51. ;@0x24  
  52.     [ ENTRY_BUS_WIDTH=32  
  53.         DCD 0xee110f10  ;0xee110f10 => mrc p15,0,r0,c1,c0,0  
  54.         DCD 0xe3800080  ;0xe3800080 => orr r0,r0,#0x80;  //Big-endian  
  55.         DCD 0xee010f10  ;0xee010f10 => mcr p15,0,r0,c1,c0,0  
  56.     ]  
  57.     [ ENTRY_BUS_WIDTH=16  
  58.         DCD 0x0f10ee11  
  59.         DCD 0x0080e380  
  60.         DCD 0x0f10ee01  
  61.     ]  
  62.     [ ENTRY_BUS_WIDTH=8  
  63.         DCD 0x100f11ee  
  64.         DCD 0x800080e3  
  65.         DCD 0x100f01ee  
  66.     ]  
  67.     DCD 0xffffffff  ;swinv 0xffffff is similar with NOP and run well in both endian mode.  
  68.     DCD 0xffffffff  
  69.     DCD 0xffffffff  
  70.     DCD 0xffffffff  
  71.     DCD 0xffffffff  
  72.     b ResetHandler  
  73.         AREA    Init,CODE,READONLY

  74.         ENTRY
  75.        
  76.         EXPORT        __ENTRY
  77. __ENTRY
  78. ResetEntry
  79.         ;1)The code, which converts to Big-endian, should be in little endian code.
  80.         ;2)The following little endian code will be compiled in Big-Endian mode.
  81.         ;  The code byte order should be changed as the memory bus width.
  82.         ;3)The pseudo instruction,DCD can not be used here because the linker generates error.
  83.         ASSERT        :DEF:ENDIAN_CHANGE
  84.         [ ENDIAN_CHANGE
  85.                 ASSERT  :DEF:ENTRY_BUS_WIDTH
  86.                 [ ENTRY_BUS_WIDTH=32
  87.                         b        ChangeBigEndian            ;DCD 0xea000007
  88.                 ]

  89.                 [ ENTRY_BUS_WIDTH=16
  90.                         andeq        r14,r7,r0,lsl #20   ;DCD 0x0007ea00
  91.                 ]

  92.                 [ ENTRY_BUS_WIDTH=8
  93.                         streq        r0,[r0,-r10,ror #1] ;DCD 0x070000ea
  94.                 ]
  95.                 |
  96.                 b        ResetHandler
  97.         ]
  98.         b        HandlerUndef        ;handler for Undefined mode
  99.         b        HandlerSWI        ;handler for SWI interrupt
  100.         b        HandlerPabort        ;handler for PAbort
  101.         b        HandlerDabort        ;handler for DAbort
  102.         b        .                ;reserved
  103.         b        HandlerIRQ        ;handler for IRQ interrupt
  104.         b        HandlerFIQ        ;handler for FIQ interrupt

  105. ;@0x20
  106.         b        EnterPWDN        ; Must be @0x20.
  107. ChangeBigEndian
  108. ;@0x24
  109.         [ ENTRY_BUS_WIDTH=32
  110.                 DCD        0xee110f10        ;0xee110f10 => mrc p15,0,r0,c1,c0,0
  111.                 DCD        0xe3800080        ;0xe3800080 => orr r0,r0,#0x80;  //Big-endian
  112.                 DCD        0xee010f10        ;0xee010f10 => mcr p15,0,r0,c1,c0,0
  113.         ]
  114.         [ ENTRY_BUS_WIDTH=16
  115.                 DCD 0x0f10ee11
  116.                 DCD 0x0080e380
  117.                 DCD 0x0f10ee01
  118.         ]
  119.         [ ENTRY_BUS_WIDTH=8
  120.                 DCD 0x100f11ee
  121.                 DCD 0x800080e3
  122.                 DCD 0x100f01ee
  123.         ]
  124.         DCD 0xffffffff  ;swinv 0xffffff is similar with NOP and run well in both endian mode.
  125.         DCD 0xffffffff
  126.         DCD 0xffffffff
  127.         DCD 0xffffffff
  128.         DCD 0xffffffff
  129.         b ResetHandler
复制代码
我们可以看到,在Option.inc将ENDIAN_CHANGE设置FALSE,程序将直接运行b ResetHandler,S3C2440默认是处于小端模式,ADS1.2中的设置默认也是小段模式,一切风平浪静。
现在,我们在ADS1.2中设为打断模式,并把ENDIAN_CHANGE设置FALSE设为TURE,现在问题就来了,请看下面的分析。
在编译程序时,根据ENTRY_BUS_WIDTH宏会将下面三条指令的之一放在0地址处
b        ChangeBigEndian           ;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怎么能执行大端模式下的指令呢,比如b        ChangeBigEndian            ;DCD 0xea000007???
原因如下:
        如果一个基于 ARM 芯片将存储器系统配置为其中一种存储器格式(如小端) ,而实际连接的存储器系统配置为相反的格式(如大端) ,那么只有以字为单位的指令取指、数据装载和数据保存能够可靠实现。其它的存储器访问将出现不可预期的结果。也就就是说在32位模式下,大小端模式对指令取指、数据装载和数据保存没有影响。
b        ChangeBigEndian在大端模式下机器码是0xea000007,这是32位模式下,其四个字节从低到高分别是:07 00 00 ea。那没b        ChangeBigEndian这条指令在8位模式下,要被小端模式的S3C2440执行,就要人为的修改为0x070000ea。
b        ChangeBigEndian这条指令在16位模式下,要被小端模式的S3C2440执行,就要人为的修改为 0x0007ea00。后面修改协处理CP15中的寄存器C1的代码时类似的。




欢迎讨论,如有错误请指出,谢谢

论坛徽章:
0
2 [报告]
发表于 2012-02-17 23:16 |只看该作者
谢谢分享
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP