ARM(Android NDK)混编C/C++汇编优化

本文介绍了在Android开发中利用NDK进行C/C++与ARM汇编混合编程以优化算法性能的方法。文章讨论了内嵌汇编的限制和注意事项,如不能直接设置PC寄存器,避免使用特定物理寄存器,并提供了在C中内嵌汇编、在汇编中使用C全局变量、C调用汇编函数以及汇编调用C函数的实例。
摘要由CSDN通过智能技术生成

http://blog.csdn.net/ce123/article/details/8209702 这篇文章比较不错,排版看起来很舒服。 


在进行Android开发时,一般考虑加速某些算法处理速率时,需要使用NDK进行开发,

为了进一步加速程序执行速率,还可以进行汇编级别的优化。

比如采用 NEON 技术进行代码的优化,以实现模块处理效率的成倍增长。

在C/C++中使用内联汇编的用法如下:

asm(
"ADD R0,R0,#1 \n\t"       // 使R0寄存器值增加1,后面加换行符和制表符是为了汇编代码的美观,其中有多条指令时 换行符是必须的
"SUB R0,R0,#1 "           // 使R0寄存器的值减少1
);


参考的文章有如下几篇,可能跟我的平台有所不同,所以我都不能完全照搬使用:

http://blog.csdn.net/wuzhong325/article/details/8277703

      读了一些网上找的文章,所讲述的内容大体比较零散,我在此做一个整理,方便后来者的学习和使用。

       开发Arm程序的时候,大多数时候使用C/C++语言就可以了,但汇编语言在某些情况下能够实现一些C语言无法实现的功能,这时候就要调用一些汇编语言的程序.我们需要大概了解一下在C语言中如何嵌入汇编语言.
    1.内嵌汇编语言的语法:

    __asm
    {
        指令[;指令]  
        ......
        [指令]
    } 

    2.举例:使能/禁止IRQ中断

    __inline void enable_IRQ(void)
    {
        int tmp;
        __asm                        //嵌入汇编代码
        {
            MRS  tmp,CPSR            //读取CPSR的值
            BIC  tmp,tmp,#0x80       //将IRQ中断禁止位I清零,即允许IRQ中断
            MSR  CPSR_c,tmp          //设置CPSR的值
        }
    }
    __inline void disable_IRQ(void)
    {
        int tmp;
        __asm
        {
            MRS  tmp,CPSR
            ORR  tmp,tmp,#Ox80
            MSR  CPSR_c,tmp
        }
    } 


    3.举例:字符串复制

    void my-strcpy(const char *src,char *dst)
    {
        int ch;
        __asm
        {
        loop:
    #ifndef __thumb
        LDRB ch,[src],#1
        STRB ch,[dst],#1
    #else
        LDRB ch,[src]
        ADD  src,#1
        STRB ch,[dst]
        ADD  dst,#1
    #endif
        CMP ch,#0
        BNE loop
        }
    }

    int main(void)
    {
        const char *a="Hello world!";
        char b[20];
        __asm
        {
             MOV  R0,a
             MOV  R1,b
             BL my_strcpy,{R0,R1}
        }
        return(0);
    }


    4.内嵌汇编的指令用法:

    .操作书: 内嵌的汇编指令中作为操作数的寄存器和常量可以是C表达式.这些表达式可以是char,short或int等类型,而且这些表达式都是作为无符号数进行操作的.若要有符号数,用户需要自己处理与符号有关的操作.编译器将会计算这些表达式的值,并为其分配寄存器.
    .物理寄存器:内嵌汇编中使用物理寄存器是有限制的:
        _ 不能直接向PC(程序计数器)寄存器中赋值,程序跳转只能通过B或BL指令来实现.
        _ 使用物理寄存器的指令中,不要使用过于复杂的C表达式
        _ 尽可能少的使用物理寄存器
    .常量: 在内嵌汇编指令中,常量前面的"#"可以省略

    .标号: C程序中的标号可以被内嵌的汇编指令使用.但是只有指令B可以使用C程序中的标号,而指令BL则不能使用.

    .内存单元的分配:所有内存分配均由C编译器完成,分配的内存单元通过变量供内嵌汇编器使用.内嵌汇编器不支持内嵌汇编程序中用于内存分配的伪指令.   

5.内嵌汇编注意事项:

    .必须小心使用物理寄存器,如R0~R3,IP,LR,CPSR中的标志位,避免发生冲突.
    例如:
        __asm
        {
            MOV  R0,x
            ADD  y,R0,x/y
        }
        改成下面代码会比较妥当:
        __asm
        {
            MOV var,x
            ADD y,var,x/y
        }
    .不要使用寄存器代替变量.

    .使用内嵌汇编无需保存和恢复寄存器.事实上,除了CPSR,SPSR寄存器,对物理寄存器先读后写都会引起汇编报错.
    .汇编语言中","号作为操作数分隔符.如果有C表达式作为操作数,若表达式中包含有",",则必须使用()将其规约为一个汇编操作数,例如:

    __asm
    {
        ADD x,y,(f(),z)    //"f(),z"为带有","的C表达式.
    }
    6.不同数据类型对应的汇编指令:
    unsigned char    LDRB/STRB
    unsigned short   LDRH/STRH
    unsigned int       LDR/STR
    char                   LDRSB/STRSB
    short                  LDRSH/STRSH 
    7.访问C程序的变量:
    AREA    globals,CODE,READONLY
    EXPORT  asmsubroutine
    IMPORT  globalvar        ;声明的外部变量
asmsubroutine
    LDR  R1,=blobalval
    LDR  R0,[R1]
    ADD  R0,R0,#1
    STR  R0,[R1]
    MOV  PC,LR
    END


http://blog.csdn.net/wuzhong325/article/details/8277718

一、格式
    asm volatile (“asm code”:output:input:changed);    //必须以‘;’结尾,不管有多长对C都只是一条语句
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值