• ARM C内嵌asm写法


       最近在玩E2手机,想把C/Invoke(http://www.nongnu.org/cinvoke/)移植到E2上,它的CPU是arm的,系统是Linux,下了源代码,按照说明自已添了一个gcc_arm_linux的arch文件,可是在修改时发现里边还有asm代码,以前没弄过,开始完全看不懂,于是呼!在网上找来《ARM指令集》找到要用到的指令,指令到是简单,可是asm内嵌c的写法把我搞晕了,又找来《AT&T ASM参考》,这才把代码中的几个内嵌ARM汇编的宏对付上。部分代码:
    /////////////////////////////////////
    // macros
    /////////////////////////////////////

    // the following examples are given
    // for x86 in MASM syntax.  Some of these
    // macros might not need to be implemented
    // in inline assembly, depending on the arch,
    // but likely most of them will.

    // this macro stores the values in the input
    // registers in the ArchRegParms structure passed as 'regparms'.
    // In the example below we store ecx and edx because
    // they are used in the fastcall convention to pass
    // parameters.

    // 存储“输入寄存器”中的值到regparms中。

    #define ARCH_SAVE_REGPARMS(regparms) \
        __asm__(
    "str %%r0, %0; \
            str %%r1, %1; \
            str 
    %%r2, %2; \
            str 
    %%r3, %3; \
            str 
    %%r4, %4; \
            str 
    %%r5, %5; \
            str 
    %%r6, %6; \
            str 
    %%r7, %7;" : \
                "=m" ((regparms).a1), \
                
    "=m" ((regparms).a2), \
                
    "=m" ((regparms).a3), \
                
    "=m" ((regparms).a4), \
                
    "=m" ((regparms).d0), \
                
    "=m" ((regparms).d1), \
                
    "=m" ((regparms).d2), \
                
    "=m" ((regparms).d3) :: );

    // this macro does two things: copies the values
    // stored in regparms into the input registers,
    // and calls the function pointed to by the pointer
    // ep.

    // 复制regparms中的值到“输入寄存器”中,并调用指针ep指向的函数。

    #define ARCH_CALL(regparms, ep) \
        __asm__(
    "ldr %%r0, %0; \
            ldr %%r1, %1; \
            ldr 
    %%r2, %2; \
            ldr 
    %%r3, %3; \
            ldr 
    %%r4, %4; \
            ldr 
    %%r5, %5; \
            ldr 
    %%r6, %6; \
            ldr 
    %%r7, %7; \
            ldr 
    %%r8, %8; \
            bx 
    %%r8;" :: \
                "m" ((regparms).a1), \
                
    "m" ((regparms).a2), \
                
    "m" ((regparms).a3), \
                
    "m" ((regparms).a4), \
                
    "m" ((regparms).d0), \
                
    "m" ((regparms).d1), \
                
    "m" ((regparms).d2), \
                
    "m" ((regparms).d3), \
                
    "m" (ep) : \
                
    "r0", \
                
    "r1", \
                
    "r2", \
                
    "r3", \
                
    "r4", \
                
    "r5", \
                
    "r6", \
                
    "r7", \
                
    "r8");



    // saves any possible return values in the ArchRetValue
    // structure given by archvalue.

    // 保存archvalue中任何可能的返回值。

    #define ARCH_SAVE_RETURN(archvalue, type) \
        __asm__(
    "str %%r0, %0; \
            str %%r1, %1; \
            str 
    %%r4, %2;" : \
                "=m" ((archvalue).a1), \
                
    "=m" ((archvalue).a2), \
                
    "=m" ((archvalue).d0) :: );


    // stores the return values in the ArchRetValue structure
    // into any place where a caller might expect to find them

    // 存储archvalue中的值到“调用者”能找到的地方(寄存器)。

    #define ARCH_SET_RETURN(archvalue, type) \
        __asm__(
    "ldr %%r0, %0; \
            ldr %%r1, %1; \
            ldr 
    %%r4, %2;" :: \
                "m" ((archvalue).a1), \
                
    "m" ((archvalue).a2), \
                
    "m" ((archvalue).d0) : \
                
    "r0", \
                
    "r1", \
                
    "r4");



    // increases the stack size by bcount bytes
    #define ARCH_PUT_STACK_BYTES(bcount) \
        __asm__(
    "ldr %%r8, %0; \
                    sub %%sp, %%sp, %%r8;" :: \
                        "m" (bcount) : \
                        
    "r8", \
                        
    "sp");

    // decreases the stack size by bcount bytes
    #define ARCH_REMOVE_STACK_BYTES(bcount) \
        __asm__(
    "ldr %%r8, %0; \
                    add %%sp, %%sp, %%r8;" :: \
                        "m" (bcount) : \
                        
    "r8", \
                        
    "sp");

    // copies the current stack pointer into the pointer variable
    // stackp
    #define ARCH_GET_STACK(stackp) \
        __asm__(
    "str %%r13, %0;" : "=m" (stackp) :: );


    // copies the current frame pointer into the pointer variable
    // framep
    #define ARCH_GET_FRAME_PTR(framep) \    
        __asm__(
    "str %%r11, %0;" : "=m" (framep) :: );

    主要说一下AT&T ASM内嵌的写法,格式如下:
    __asm__("指令" : "操作约束 (输出参数) : (输入参数) : 寄存器约束);

    指令:
    当然就是ARM的汇编指令了,但要注意的是寄存器要用%%来约束,以防与参数%冲突。
    操作约束(
    OperationConstraint)我个人理解为参数传递方式,如:"=m",中“=”表示输出,还可以不写表示输入,"+"表示输 入和输出, “m”表示使用内存,在x86中,还可以是“a”、“b”、“c”等,表示使用什么样的寄存器。
    输出参数:对应C代码中变量,通过是由汇编代码从寄存器或内存中取出来的值,以便在C代码中使用。多个参数时,用逗号分  隔。
    输入参数:C代码向汇编代码输入的参数。
    寄存器约束(Register Constraint): 个人感觉是给“编译器”看的,帮你检查代码,防止你修改了不该改的寄存器的内容。

       在ARM中,寄存器与X86上的不同,没ax、bx什么的,它是r0~r15,其中还包括几个特殊用途的寄存器,如:r11=fp(帧指针)、r13=sp(堆栈指针)等。




  • 相关阅读:
    ES6对象展开运算符
    Vue中keep-alive的深入理解和使用
    彻底明白VUE修饰符sync
    函数去抖和函数节流
    vue cli4.0 配置环境变量
    什么是process.env?
    new Function和with
    inline-block元素没有对齐的解决方案及总结
    【译文】为什么你的浏览器会限制并发网络调用的数量?
    高德地图Marker缩放位置变化
  • 原文地址:https://www.cnblogs.com/zhongzf/p/890746.html
Copyright © 2020-2023  润新知