C语言&汇编混合编程

本文介绍了嵌入式开发中C和汇编混合编程的必要性,包括在boot阶段初始化、系统调用扩展、性能优化等方面的应用。通过AArch64架构的实例,展示了C调用汇编、C内嵌汇编以及汇编调用C的多种方式,并给出了详细的代码示例和编译运行过程。
摘要由CSDN通过智能技术生成

在嵌入式开发中,汇编和C和混合编程是有必要的,比如在如下场景:

  1. 在boot阶段没有C的运行环境,需要编写汇编代码配置基本的硬件环境和C的运行环境;
  2. 添加新的系统调用;
  3. 需要用汇编加速部分对延时高要求的地方;
  4. 一些特权寄存器的操作,无法用C语言实现,只能采用汇编;
  5. 触发中断时,需要从中断向量处的汇编代码过渡到C实现的中断服务函数;
  6. 。。。。。。

本文以AArch64为例,示例是计算2个int型数的加减法。 编译器使用aarch64-linux-gnu-gcc。

1. C调用汇编

1.1 汇编和C写在同一个.c文件中

// 源文件test_c_asm.c 
#include <stdio.h> 
 
asm( 
    ".text\n" 
    ".global Add\n" 
    ".type Add, %function\n" 
    "Add:\n" 
    "add w0, w0, w1\n" 
    "ret" 
); 
 
extern int Add(int, int); 
int main(int argc,char** argv) 
{ 
    int b=1,c=2; 
    int a = Add(b,c); 
    printf("res =  %d\n", a); 
    return 0; 
}  

编译:

aarch64-linux-gnu-gcc test_c_asm.c -o test  

运行:

./test  

输出:

res =  3  

1.2 汇编和.c写到不同的文件

汇编代码写到.S文件中,C代码写到.c文件中。

汇编代码add.S:

.text 
.global Add 
.type Add, %function 
 
Add: 
    add w0, w0, w1 
    ret 

C代码test.c:

// 源文件test.c 
#include <stdio.h> 
 
extern int Add(int, int); 
int main(int argc,char** argv) 
{ 
    int b=1,c=2; 
    int a = Add(b,c); 
    printf("res =  %d\n", a); 
    return 0; 
}  

编译:

aarch64-linux-gnu-gcc test.c add.S -o test  

运行:

./test  

输出:

res =  3  

1.3 C内嵌汇编

1.3.1 不指定变量使用的寄存器

C源文件test_c_embeded_asm.c

#include <stdio.h> 
 
int Add(int a, int b) 
{ 
    int res = 0; 
    asm( 
        "add %w[result], %w[i], %w[j]" 
        : [result] "=r"(res) 
        : [i] "r"(a), [j] "r"(b) 
    ); 
} 
 
extern int  Add(int, int); 
int main(int argc,char** argv) 
{ 
    int b=1,c=2; 
    int a = Add(b,c); 
    printf("res =  %d\n", a); 
    return 0; 
}  

编译:

aarch64-linux-gnu-gcc test_c_embeded_asm.c -o test  

运行:

./test  

输出:

res =  3  

1.3.2 指定变量使用的寄存器

#include <stdio.h> 
 
int Sub(int a, int b) 
{ 
    int res = 0; 
    asm( 
        "sub %w0, %w1, %w2" 
        : "=r"(res) 
        : "r"(a), "r"(b) 
        : "memory" 
    ); 
} 
 
int main(int argc,char** argv) 
{ 
    register int b asm("w1") =1; 
    register int c asm("w2") =2; 
 
    int a = Sub(b,c); 
    printf("res =  %d\n", a); 
    return 0; 
}  

编译:

aarch64-linux-gnu-gcc test_c_embeded_asm2.c -o test  

运行:

./test 

输出:

res =  -1  

2. 汇编调用C

下面是一个综合性示例中,调用关系如图:

将汇编和C写到一个文件中test_asm_call_c.c :

#include <stdio.h> 
 
int Sub(int a, int b) 
{ 
    return a-b; 
} 
 
asm( 
    ".section .text\n" 
    ".global SubASM\n" 
    ".type SubASM, %function\n" 
 
    "SubASM:\n" 
        "stp     x29, x30, [sp, -32]!\n" /* 压栈X29,X30, X29是帧指针寄存器(FP)。 
                                            X30是链接寄存器(LR)。*/ 
        "bl Sub\n"   // 调用C语言实现的Sub函数 
        "ldp     x29, x30, [sp], 32\n" // 出栈X29,X30 
        "ret\n" 
   ); 
 
extern int SubASM(int, int); 
int main(int argc,char** argv) 
{ 
    int b=1,c=2; 
    int a = SubASM(b,c); // 调用汇编函数 
    printf("res =  %d\n", a); 
    return 0; 
}  

编译:

aarch64-linux-gnu-gcc test_asm_call_c.c -o test  

运行:

./test  

输出:

res =  -1  

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值