五、C和汇编混合编程

ATPCS协议(ARM/Thumb Procedure Call Standard):它规定了一些子程序间调用的基本规则,如子程序调用过程中的寄存器、堆栈的使用规则,参数的传递规则等。

  R0~R3:函数调用时传递函数参数,如int add(int a, int b, int c)参数分别对应R0=a,R1=b, R2=c。

  R0:保存函数的返回值。

  栈传参:当函数参数超过4个时,多出来的参数利用栈来传递(一次从右往左压栈)。

C内嵌汇编:

  注意事项:内嵌汇编中不能直接向PC寄存器赋值。
       内嵌汇编指令中不要将R12、R13、R14、R0~R3指定为指令中的物理寄存器,因为这些寄存器可能会存放中间结果或用于子程序调用;通常,内嵌汇编指令中不要指定物理寄存器。
       内嵌汇编中,常量前面的“#”可以省略。
          C程序中的标号可以被内嵌汇编指令使用,但指令BL不能使用C的标号(指令B则可以)。
          编译C内嵌的汇编代码使用的是内嵌汇编器,与armasm汇编器有一些差异。

  在C程序中嵌入汇编程序,可以实现一些高级语言没有的功能,提高程序的执行效率;但是嵌入的汇编程序不具备可移植性。

  内嵌汇编的语法:
    __asm
    {
    指令[;指令] /*注释*/
    ...
    [指令]
    }

  demo:

#include <stdio.h>

int main(void)
{
    const char *src = "Hello world!";
    const char *p = src;
    char a[20];
    char *dst = a;
    char *dst_print =dst;
    int ch;
    __asm
    {
    loop:
    LDRB ch, [src], #1
    STRB ch, [dst], #1
    CMP ch, #0
    BNE loop
    }
    printf("Original string:%s\n", p);
    printf("Copied string:%s\n", dst_print);
    return 0;
}

汇编调用C:

  .s的汇编文件

    AREA Example1,CODE,READONLY    ;声明代码段Example1
    CODE32    ;声明32位ARM指令
    ENTRY
    IMPORT g    ;IMPORT汇编文件中声明引用C函数名
    IMPORT global
START
    MOV R0, #1
    MOV R2, #2
    MOV R3, #3
    LDR R7, =global    ;将global的地址给到R7
    LDR R3, [R7]
    BL g
    MOV R8, R0
    B START
    END

  .c文件

int global = 10;
int g(int a, int b, int c, int d)
{
    return a+b+c+d;
}

C调用汇编

  .s汇编文件

    AREA Example2,CODE,READONLY
    CODE32
    EXPORT strcopy    ;EXPORT对外声明汇编中的函数,表示其可被调用
strcopy
    LDRB R2, [R1], #1
    STRB R2, [R0], #1
    CMP R2, #0
    BNE strcopy
    MOV PC, LR
    END

  .c文件

#include <stdio.h>
extern void strcopy(char*d, char *s);

int main(void)
{
    char *srcstr = "First string - source";
    char dststr[] = "Second string - destination";

    printf("Before copying:\n");
    printf("%s %s\n", srcstr, dststr);

    strcopy(dststr, srcstr);

    printf("After copying:\n");
    printf("%s\n %s\n", srcstr, dststr);

    return (0);
}

猜你喜欢

转载自www.cnblogs.com/zch-blog/p/9357773.html
今日推荐