打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
ARM

1 嵌入式结构

名称 说明
应用程序 app
libc.so.6、libstdc++.so、libjpeg.so、…
GUI QT(C++)、Android(Java)、Mini-GUI(C)、GTK()
文件系统 Filesystem
内核 Linux、Android
bootloader uboot、myboot
板卡 SOC+DDR+NAND(EMMC)+LCD+SOUND+NET…
SOC CPU(arm)+总线+控制器


Arm公司只设计处理器架构,Arm1 Arm2 …. Arm6

版本 内核 芯片
v4 arm7TDMI S3C44B0
arm920T S3C2440(火,资料多)
v5 arm10
v6 arm1176 S3C6410
arm11MP
v7 arm-cortex-a,针对以应用为主(消费电子、高端的嵌入式设备)
a8 S5PV210(单核)
a9 Exynos4412(4核)、Imax6.Q/D、Omap4460(TI)
a15 Exynos5210(a15以上才支持硬件除法)
arm-cortex-r
r4/r6
arm-cortex-m(m系列都支持硬件除法)
m3 STM32F10xxx(ST)
m4 STM32F40xxx
m7 STM32F7xxx
v8 arm-cortex-a50(都是64位)
a53(消费电子、高端的嵌入式设备)
a57(服务器)
arm-cortex-a72


除arm外的芯片

名称 说明
mips 网络设备(路由)
ppc 航空航天,高端路由
51 仪器仪表

2 ARM架构

2.1 结构

SOC=CPU(arm)+总线+控制器i5--PIC-E--桥(芯片组)ARM=arm_core    执行arm指令,哈弗结构    cache       高速缓存        I-cache 缓存代码        D-cache 缓存数据    TCM         要求访问速度高的,可以存在这里        I-tcm   存代码        D-tccm  存数据

2.2 协处理器

名称 说明
CP15 cache、tcm、指令分支预测等的开关,处理器的大小端、MMU的开关、页表
CP14 调试
CP10 NENO
CP11 VFP

2.3 寄存器

r13~r15不要随便用,所有函数按1、2、3的顺序执行,保证调用函数之后能够正确返回

1、LR->SP2、SP->LR3、PC=LR
名称 说明
CPSR 当前程序状态寄存器
SPSR 保存程序状态寄存器
r0~r12 写程序时随便用
r13 SP stack pointer(指向在栈中的地址)
r14 LR link register(函数返回时的指向)
r15 PC process counter(指向程序执行地方)

2.4 指令集

arm-cortex-m 只支持thumb thumb2

名称 位数 说明
arm指令 32位 高效,占空间比较大
thumb指令 16位 比arm低效,占空间比较小
thumb2指令 32/16位混合

2.5 七种工作模式

名称 位数
user 用户模式,执行用户程序
system 系统模式
svc 管理模式,执行boot kernel
abort 模式,处理非法访问地址
irq 中断模式
fiq 快速中断
unde 未定义模式,处理未定义指令


普通模式:user 只能修改NZCVQ
特权模式:system,svc,unde,abort,irq,fiq
异常模式:svc,unde,abort,irq,fiq 每个异常模式都有自己的r13,r14,SPSR

模式切换:CPSR[NZCVQ EAIFT M[4:0]]    N       负操作1,否则0    Z       零操作1,否则0    C       加法,如果有进位1,否则0   减法,如果有借位0,否则1    V       有溢出1,否则0    Q       有饱和1,否则0    E       如果小端0,否则1    A       中止禁止位,如果为1则禁止了中止异常    I       中断禁止位    F       快速禁止位    T       如果执行的thumb指令则位2,否则为0    M[4:0]  只有特权模式可以写

3 ARM汇编,在C中嵌套汇编

int main(void){    int a = 100;    int b = 30;    int c = 50;    //假设前面有C代码,把一个数放进r0,自己写的汇编改变了r0的值,这就出问题,所以自己使用前要存下r0的值    //使用完后恢复它,在保护寄存器行写一下就可以    __asm__ __volatile__(        "mov %0,#20\n"              //把a的值改为20,%0代表a,不能直接写20,不然会认为是地址,加个#号        "mov r0,#123\n"             //把r0寄存器的值赋值123,汇编指令都要\n结尾        "mov %1,r0\n"        "mov r1,%2\n"        "mov %0,r1\n"        :"=&r"(a),"=&r"(b)          /**                                     * 声明输出变量(只能写不能读)和输入输出变量,第一个声明的是%0,                                     * 第二个是%1,=是输出变量,+是可读可写变量,&是独占寄存器,r代表是寄存器,                                     * =后记住加&                                     */        :"r"(c)                     //声明输入变量,只能读不能写        :"r0","r1"                  //保护寄存器,使用寄存器之后还原原来寄存器的值    );    printf("hello asm %d %d %d\n",a,b,c);   /**    * out = in_out;    * in_out = in;    */    int in_out = 200;    int out;    int in = 52;    asm volatile(        "mov %0,%1\n"        "mov %1,%2\n"        :"=&r"(out),"+r"(in_out)        :"r"(in)        :    )    printf("hello asm out=%d in_out=%d\n",out,in_out);    int d,f,e;    asm volatile(        "mov %[d],#1\n"        "mov %[f],#2\n"        :[d]"=&r"(d),[e]"=&r"(e),[f]"=&r"(f)        //可以直接指定每个变量的标号,就可以用%0,%1这种方式访问                                                    //在""前加[随便字符串]即可,解决添加变量在中间后序号改变        :        :    )    printf("hello asm d=%d f=%d\n",d,f);    //减法sub    int g,h,i;    asm volatile(        "mov r0,#9\n"        "mov r1,#8\n"        //要实现g = r0-r1;        "sub %0,r0,r1\n"        :"=&r"(g)        :        :"r0","r1"    );    printf("hello asm sub g=%d\n",g);   /**     * 32位处理器上进行64位减法,I存高位,H存低位    * 0x33333333 00000004    * 0x11111111 00000005    * 0x22222221 ffffffff    */    asm volatile(        "mov r0,#4\n"        "mov r1,#5\n"        //C减法,如果有借位,Clear C置0,反之Set C置1,看上面模式切换那里,sub加s表示需要借位        "subs %0,r0,r1\n"        "ldr r0,=0x33333333"        "ldr r1,=0x11111111"        //%1 = r0-r1-!C        "sbc %1,r0,r1\n"        :"=&r"(h),"=&r"(i)        :        :"r0","r1"    );    printf("sub = %#x%08X\n",i,h);    //乘法    int mul;    asm volatile(        "mov r0,#3\n"        "mov r1,#4\n"        //mul的三个操作数必须都是寄存器,%0 = r0*r1        "mul %0,r0,r1\n"        :"=&r"(mul)        :        :"r0","r1"    );    printf("hello asm mul=%d\n",mul);    asm volatile(        "mov r0,#3\n"        "mov r1,#4\n"        "mov r2,#5\n"        //mla %0 = r0*r1+r2     结果是17        //mls %0 = r0*r1-r2     结果是7        "mla %0,r0,r1,r2\n"        :"=&r"(mul)        :        :"r0","r1","r2"    );    printf("hello asm mul=%d\n",mul);    /**     * 条件执行,大多数的arm指令都支持     * thumb指令只有跳转指令才支持     * 大于gt,小于lt,等于eq,不等于ne,小于等于le,大于等于ge     */    int k=5,m=6,l;    asm volatile(        "subs r0,%1,%2\n"        //条件执行        "movgt %0,#1\n"     //k-m>0则l=1        "moveq %0,#2\n"     //k-m=0则l=2        "movlt %0,#3\n"     //k-m<0则l=3        :"=&r"(l)        :"r"(k),"r"(m)        :"r0"    );    printf("hello asm l=%d\n",l);    //专门比较指令    asm volatile(        "mov r0,#4\n"        "mov r1,#5\n"        //cmp指令加不加s都行        "cmp r0,r1\n"        "movgt %0,#1\n"     //r0>r1则l=1        "moveq %0,#2\n"     //r0=r1则l=2        "movlt %0,#3\n"     //r0<r1则l=3        :"=&r"(l)        :        :"r0","r1"    );    printf("hello asm l=%d\n",l);    //专门比较是否相等指令    asm volatile(        "mov r0,#4\n"        "mov r1,#5\n"        //teq指令加不加s都行        "teq r0,r1\n"        "moveq %0,#1\n"     //r0=r1则l=1        "movne %0,#2\n"     //r0!=r1则l=2        :"=&r"(l)        :        :"r0","r1"    );    printf("hello asm l=%d\n",l);    //判断某一个寄存器的某一位是否为0,此题输出1    asm volatile(        //0xf0 = 1111 0000,从右边第0位开始数        "mov r0,#0xf0\n"        //r0&(1<<4)按位与的操作,判断第四位是否为0        "tst r0,#(1<<4)\n"        "moveq %0,#0\n"     //如果等于0,输出0        "movne %0,#1\n"     //如果不等于0,输出1        :"=&r"(l)        :        :"r0"    );   /**    * 逻辑运算    * and   两个是1才是1,其余都是0    * orr   有1个是1都是1    * eor  不同为1,相同为0    * bic       *    * mvn r0,#0xff  按位取反    * r0 = ~0x000000ff = 0xffffff00    *    * 移位运算符<<向左移,>>向右移    * 需要移位的数字 << 移位的次数   * 例如: 3 << 2,则是将数字3左移2位    * 首先把3转换为二进制数字0000 0000 0000 0000 0000 0000 0000 0011,然后把该数字高位(左侧)的两个零移出    * 其他的数字都朝左平移2位    * 最后在低位(右侧)的两个空位补零。则得到的最终结果是0000 0000 0000 0000 0000 0000 0000 1100    * 则转换为十进制是12。不溢出的情况下    * 相当于3*2的2次方    * 3*(2^2) = 12    */    int and,orr,eor,bic;    asm volatile(        "mov r0,#5\n"   //0000..0101        "mov r1,#6\n"   //0000..0110        //%0 = r0&r1        "and %0,r0,r1\n"        "orr %1,r0,r1\n"        "eor %2,r0,r1\n"        "mov r0,#0xff"  //想把第2位清零,从右边第0位开始数        "bic %3,r0,#4\n"//或者#4 = #(1<<2)        :"=&r"(and),"=&r"(orr),"=&r"(eor),"=&r"(bic)        :        :"r0","r1"    );    printf("hello asm and=%d orr=%d eor=%d bic=%x\n",and,orr,eor,bic);   /**    * lsl逻辑左移,lsr逻辑右移    * asr算术右移,ror循环右移    */    int lsl,lsr,asr,ror;    asm volatile(        "mov r0,#20\n"        "mov %0,r0,lsl #1\n"    //%0 = r0<<1  结果是40        "mov %0,r0,lsr #1\n"    //%1 = r0>>1  结果是10        "mov r0,#-20\n"         //20 = 0000...10100 -20 = 1000...10100 补码:1111...01100                                //计算机中存的都是补码        "mov %2,r0,lsr #1\n"    //逻辑右移一位得到0111...0110        "mov %3,r0,asr #1\n"    //算术右移一位得到1111...0110        "mov r0,#0#ff\n"        "mov %4,r0,ror #4\n"    //把最低位循环4次移到最高位,得到0xf000000f        :"=&r"(lsl),"=&r"(lsr),"=&r"(asr),"=&r"(ror)        :        :"r0",    );    printf("hello asm lsl=%d lsr=%d asr=%d ror=%x\n",lsl,lsr,asr,ror);    int n;    //读CPSR    asm volatile(        "mrs %0,cpsr\n"        :"=&r"(n)        :        :    );    printf("cpsr = %#x\n",n);    //CPSR中有NZCVQ EAIFT    asm volatile(        "mrs r0,cpsr\n"        "orr r0,r0,#(1<<7)\n"        "msr cprs,r0\n"         //修改CPSR中的值,此时处于用户模式,只能修改NZCVQ这5位,这里修改了第7位,修改失败        :        :        :"r0"    );    return 0;}

4 syscall

/* * 直接调用内核函数* 内核中为每一个系统调用有编号* 在<Linux_src>/arch/arm/include/asm/unistd.h中* fork 2* read 3* write 4*/int main(void){    char *s = "hell syscall\n";    int ret;    write(1,s,strlen(s));    syscall(4,1,s,strlen(s));    //对于arm平台系统调用号有一个0x900000的偏移    asm volatile(        "mov r0,#1\n"        "mov r1,%1\n"        "mov r2,#14\n"        "swi 0x900004\n"    //进入内核        "mov %0,r0\n"       //返回值在r0中        :"=&r"(ret)        :"r"(s)        :"r0","r1","r2"    );    printf("ret =%d\n,ret");    return 0;}
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
arm 汇编指令 积累
ARM汇编指令
ARM协处理器 - linux内核与驱动
ARM嵌入式开发中的GCC内联汇编简介
面向未来:理解ARM处理器的新一代技术
【转】C语言内嵌汇编(asm)
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服