Linux_ARM体系结构与汇编(Day17)

零 安装交叉编译器
    1. 创建共享目录
    2. 拷贝压缩包 arm-cortex_a9-eabi-4.7-eglibc-2.18.tar.gz
    3. 解压 tar xvf arm-cortex_a9-eabi-4.7-eglibc-2.18.tar.gz
    4. 修改环境变量 PATH
    5. vi ~/.bashrc 
         添加 export PATH=$PATH:/opt/arm-cortex_a9-eabi-4.7-eglibc-2.18/bin
    6. 验证
        source ~/.bashrc
        arm-  +  TAB 键 
        如果可以补全,则说明交叉编译工具安装成功


一 回忆昨天的内容

   三大系统软件的烧录
   EMMC分区
   【      】   【ubootpak.bin】 【uImage】 【rootfs_ext4.img】 【大片】
   0 ~ 512byte   513byte  ~  1M   1M ~  65M  65M  ~  819M       .....
   
   bootcmd    加载引导linux内核到内存中
   bootargs   给linux内核传参
   
   setenv bootcmd mmc read 0x48000000 0x800 0x3000 \; 
   bootm 0x48000000    
   setenv bootargs root=/dev/mmcblk0p2 init=/linuxrc 
     console=ttySAC0,115200 maxcpus=1 lcd=wy070ml tp=gslx680-linux
     saveenv

二 ARM体系结构与汇编
    2.1 什么是ARM:
            Advanced RISC Machines
            RISC : 精简指令集 ---》 ARM MIPS LA IBM
            CISC : 复杂指令集 --->  intel AMD 
            
            www.arm.com
            
            指令集            架构                soc        
            ARMV4T             ARM7                s3c44b0
            ARMV5TE            arm9                S3C2410
            armv6                arm11                s3c6410
            armv7                cortex-a        sp5v210
            armv8                cortex-a53    s5p6818
                                    cortex-r        实时性较强的领域
                                    cortex-m        以单片机的价格实现32bit的性能
                                    
            流水线:
                三级流水线  取指令   解码指令  执行指令
            
            for (i = 0; i < 10; i++) //执行效率更高
            {
                for (j = 0; j < 10000; j++)
                {
                    .....
                }
            }
            
            for (j = 0; j < 10000; j++)
            {
                for (i = 0; i < 10; i++)
                {
                    ......
                }
            }
                
            CPI 怎么算?                    
            指令周期/周期内执行指令的个数
            
    2.2 ARM编程模型
        2.2.1 ARM的工作模式 7种
        
        svc: 管理模式,系统上电,执行软中断指令
        fiq: 快速中断,发生了高优先级的中断
        irq:发生了低优先级的中断
        abort:当产生了非法访问存储器时
        undef:遇到不认识的指令
        system:与用户共用寄存器,需要特权
        user:应用程序和系统任务运行在用户模式
        
        前5种是异常模式,后两种是正常模式
        前6种是特权模式,后一种是非特权模式
        
        2.2.2 ARM的工作状态:
            ARM 状态:执行ARM (32bit)指令时
            Thumb 状态:执行Thumb (16bit)指令时
            
            0x90000002 
            
            以上两种状态可以切换,
            异常处理过程中必须处于ARM状态
            
      2.2.3 寄存器的组织结构
          寄存器和特殊功能寄存器的区别:
          1.存放的位置不同:
              寄存器位于 ARM core 内部
              特殊功能寄存器 位于ARM core外部
          2.访问的方式不一样:
              特殊功能寄存器都有特定的物理地址
              寄存器只有名字没有地址
              C很难访到
              
          * (volatile int *) (0xc001c000)  ---> GPIOCOUT        
          
          ARM核中一共有37个32bit的寄存器
          其中一共有32个通用寄存器
          命名为r0~r15
          r11 (fp, frame pointer 忽略)
          r13 (sp, stack pointer)
          r14 (lr, 保存函数的指针)
          r15 (pc, 保存取指令的位置)
          
          6个状态寄存器:
           1个cpsr程序状态寄存器
           5个spsr是cpsr的备份
               [4:0] mode 模式位,标识当前arm核处于什么模式,
               在特权模式下,可以写该寄存器
               [5] T位,1,当前处于Thumb状态, 0 arm状态
               [7] I位,1,禁止RIQ 
                                0, 使能RIQ
               [6] F位,1,禁止FIQ
                                0, 使能FIQ
               [28] v位 有符号数据在做运算的时候有进位
               [29] C位 运算结果最高位有进位 
                0xfffffffc + 10 => C = 1
               [30] Z位 运算结果为0, z位为1
               [31] N,运算结果为负, =1
               
           每一种模式下,都只能访问其中的一个子集
           
      2.2.4 异常向量与异常向量表
          裸板程序:
              main (){
                  xxx_init ();
                  ...
                  while (1) 
                  {
                      周期性事件
                  }
              }         
              + 异常处理
              
          ARM Core 支持 7种工作模式
          reset (复位异常) 按下复位键
          undef (未定义的异常) 执行到不认识的指令
          swi (软中断异常) 执行汇编指令“swi”
          prefetch abort (预取值终止异常) 
          取指令时进行了非法的存储器访问
          data abort 取数据时进行了非法的存储器访问
          irq (中断异常) 按键中断
          fiq (快速中断) 高优先级中断发生时
          
          7种异常会导致arm进入5种异常模式
          当异常产生时,ARM核硬件上自动做4件事:
          1. 备份cpsr 
              spsr_ = cpsr
          2. 修改 cpsr 
              a) 切换为arm工作模式 CPSR[T] 
              b) 切换为异常工作模式 CPSR[4:0] 
              c) 禁止中断 CPSR[I] = 1 CPSR[F] = 1
          3. 保存返回地址到LR_
          4. 给pc赋值 
              reset 异常 ==》pc = 0x00
              ..
              fiq 异常 ===》 pc = 0x1C
          
          从异常返回的时候,软件上需要处理:
              1)恢复cpsr
              2)返回被打断的位置 
              
          fun(){
          ...
          return 
          }    
          main (){
              func (); //i++指令的地址 ---》 LR
              i++;
          }
          
      2.2.5 ARM 支持的数据类型        
          byte
          half word
          word
          double word
          对齐方式:
              4字节对齐,存储的地址可以被4整除
              struct stu{
                  int a;
                  char c;
                  short d;
                  int b;
              };
              sizeof (struct stu) = 12;
              
          大小端的判断:
              int a = 0x12345678;
              字节序:
                                  大端模式    小端模式
              地址             值                  值
              0x00             12                    78
              0x01             34                    56
              0x02             56                    34
              0x03             78                    12
              
              权重最大的在低地址叫大端
              编程实现arm处理器大小端的判断?
              参见代码: Endian.c
              
三 arm汇编
    3.1 基本概念
    arm 汇编语言,又叫助记符语言
    大多数系统设计的主要工作都集中在编译代码(C),
    一般不需要了解指令集,但是以下情况会用到汇编:
    
    嵌入式系统中需要初始化和中断服务程序
    所有的系统都需要调试,可能会用汇编调试
    可以通过汇编语言来提升系统的性能
    有些指令编译器无法产生,只能通过汇编完成
    
    3.2 ARM汇编指令
    
        ARM汇编指令的特点
        1)大多数汇编指令都是单周期
        2)大多数arm汇编指令可以条件执行
        
        3.2.1 分支跳转指令
        b {cond} <目标地址> //类似于goto
        b main 
        b 指令应用实例:
        
        start:
            cmp r0,r1
            beq not_copy
            move r0,r1
        not_copy:
            b .
        
        bl {cond} <目标地址> //函数调用 l是 link
        bl main //在向main跳转之前,记录下下一条指令的地址到LR
        注意:目标地址的范围:土32M
         为指令的条件码 EQ, NE , CC, CS ,LT...
         为指令跳转的目标地址,
        将指令中的24位带符号的补码立即数扩展为32位,将32bit左移两位,
        将得到的数值加到pc寄存器中,得到目的地址。
        
        指令的编码格式
        31      28      25    24   23          0
            cond            B                L                    target
            
        bl指令的应用实例:
            start:
                mov r0, #1
                mov r1, #2
                bl  DoAdd
                b .       // 跳转到当前地址
                
            DoAdd:                
                add r0, r0, r1
                mov pc, lr
                
        bx 
        blx
        b {l} {cond}
        b {l} {cond}
        x,带状态切换 
        Rn,一定是通用寄存器 r0~r15
        注意:跳转的范围不受限制 (0~4G) 
        
        
        bx指令的应用实例:
        
        .code 32   arm指令 32bit
        ARM_code:
            ADR R0, THUMB_code + 1  @R0中存放的是要跳转的地址
            BX  R0 
            
        .code 16   thumb 指令 16bit
        THUMB_code:
            ADR R0, ARM_code 
            BX  R0
        
        3.2.2 数据处理指令
            1)移位指令 
                LSL: logical shift left 逻辑左移
                        , LSL # 
                        , LSL @移位的位数由Rs寄存器的bit[7:0]
                        
                LSR:
                        logical shift right 逻辑右移,空出的位0
                        , LSR # 
                        
                ASR:
                        Arithmetic shift right 算数右移
                        最高位补符号位
                        
                ROR:
                        ROR 循环右移
                RRX:
                     带扩展位的循环右移 新的最高位由CPSR的C位,而且更新C位
                     
            2) 数据传输指令
                mov {cond} {s} ,
                cond, 可以条件
                s, 操作结果影响cpsr的NZCV位
                    mov R0, #10   @ r0 = 10 
                    movs R0, #10  @ r0 = 10, N = 0  Z = 0 
                    
              Rd 一定是通用寄存器
              operand : 有三种表现形式
                  mov r0, #10
                                  注意立即数的合法性问题
                                  存在一个8bit的立即数,
                                  循环右移偶数位得到,那么这个立即数就是合法的
                  mov r0, r2  @  r0 = r2 
                  mov r0, r2, lsl #2 @r0 = r2 << 2
                  moveqs r0, r1 @ if (CPSR.Z ==1) 
                                                  movs r0, r1 
                                                  @ r0 = r1 if (r0 == 0) Z = 1 else Z = 0
                                                  @ N = r0[31]
                                                  
                 mvn {cond} {s} ,                             
                 将operand表示的数据的反码传送到目标寄存器r0中
                 并根据操作的结果影响CPSR的NZCV位
                 
        3.2.3 算数运算指令
            add {cond} {s} , ,
            cond, 可以条件执行
            s,操作结果影响NZCV位
                N = r[31]
                if (Rn == 0) Z = 1 else Z = 0
                最高位有进位 C = 1 else C = 0
            
            Rd, Rn 一定是通用寄存器
            operand 有三种表现形式
                    add r0, #10 
                    add r0, r1, r2
                    add r0, r1, r2, lsl #3  @r0 = r1+r2*8
        
            adc {cond} {s} , ,
                adc r0, r1, r2  @r0 = r1 + r2 + C
                64bit的加法运算:
                                            高             低
                    被加数            r0            r1
                    加数                r2            r3
                    和                    r0            r1
                 
                     adds r1, r1, r3
                     adc  r0, r0, r2
            
            sub {cond} {s} , ,
            s, 注意对C位影响
            Rn > Operand  C = 1
            C = 0
            
            sbc {cond} {s} , ,
                sbc r0, r1, r2  @r0 = r1-r2-NOT(C)  @出现负负得正的效果
                
                64bit的减法:
                                        高                低
                被减数            r4                r5
                减数                r6                r7
                差                    r8                r9    
            
            subs r9, r5, r7 @if (r5 > r7) C = 1
            sbc  r8, r4, r6 @r8 = r4 - r6 -NOT(C)
            
            rsb {cond} {s} , ,  @逆向减法指令
                rsb r0, r1, r2  @r0 = r2 - r1
                rsb r0, r1, #8  @r0 = 8 - r1
                rsb r0, #8, r1  @不对,语法错误
                rsb r0, r0, #0  @取相反数
                
            练习:求1到10的累加和,结果保存到r0中
            参见代码 add.s
            
            作业:对照 数据手册 和电路原理图 读懂01工程文件
            建立ctags文件:
            ctags -R * 
            如何跳转:光标移到要跳转的位置  --》ctrl + } 
                                跳回来 ctrl + t
                
                

你可能感兴趣的:(物联网实训,linux,arm)