SPMC75和ASM(汇编)混合编程的应用
◆ ASM函数中调用C程序
在ASM函数中要调用C子函数,那么应该根据C的函数原型所要求的参数类型,分别把参数压入堆栈后再调用C函数,以保证参数的正确传递。在调用调用结束后还需要进行弹栈,以恢复调用C函数前的堆栈指针。在这个过程中很容易产生bug,所以在使用的时候希望细心的处理。
ASM程序调用C 函数,输入两个UInt16参数,返回一个UInt16参数。
/*-------------------------------------------------------*/ /* ASM 程序 /*-------------------------------------------------------*/ .CODE .EXTERNAL _SP_Addition //C 函数 .PUBLIC _F_Dummy_Main _F_Dummy_Main: .proc PUSH R1,R2 to [SP]; // 寄存器保护 R2 = 0xA800; // 第二个参数 R1 = 0x00E9; // 第一个参数 // PUSH R1,R2 to [SP]; // 传递参数入栈 PUSH R2 to [SP]; // 第二个参数入栈 ( 1 ) PUSH R1 to [SP]; // 第一个参数入栈 ( 2 ) call _SP_Addition; // 调用 C 函数 ( 3 ) R1 = R1; // 函数返回值 ( 4 ) // SP + = 2; // 调整堆栈指针 ( 5 ) POP R1 from [SP]; ( 6 ) POP R2 from [SP]; ( 7 ) POP R1,R2 from [SP]; RETF; .endp /*-------------------------------------------------------*/ /* C 程序 /*-------------------------------------------------------*/ //============================================================= // ----Function: UInt16 SP_Addition(UInt16 i,UInt16 j) // -Description: C 函数,示范汇编调用 C 函数 // --Parameters: i , j :被加数和加数 // -----Returns: 两数的和 // -------Notes: none //============================================================= UInt16 SP_Addition(UInt16 i,UInt16 j) { UInt16 sum = 0; sum = i+j; return(sum); } |
如图3-3所示程序调用时堆栈使用情况。在ASM调用C的时候需要把堆栈调整成和C调用C函数的样子,所以需要对参数的传递方式有个了解,按照图3-3的形式来调整堆栈。
图3-3 程序调用时堆栈使用情况
4嵌入汇编
为了使C语言程序具有更高的效率和更多的功能,需在C语言里嵌入用汇编语言写的子程序。一方面,是为了提高子程序的执行速度和效率;另一方面,可以解决某些用C语言程序无法实现的机器语言操作。勿庸置疑,C语言代码与汇编代码的接口问题是任何C编译器都要解决的问题。
通常有两种方法可以将汇编语言代码与C语言代码联合起来,一种是把独立的汇编语言程序用C函数连接起来,通过API(Application Program Interface)的方式调用;另一种就是下面将要提到的在线汇编方法,即将直接插入汇编指令嵌入到C函数中。
采用GCC规定的在线汇编指令格式进行指令的输入,是GCC实现将μ'nSPTM汇编指令嵌入C函数中的方法。GCC在线汇编指令格式规定如下:
asm(汇编指令模板:输出参数:输入参数:clobbers参数);
若无clobber参数,则在线汇编指令格式可以简化为:
asm(汇编指令模板:输出参数:输入参数);
4.1 嵌入式汇编介绍
1、汇编指令模板
模板是在线汇编指令中的主要成分,GCC据此可以在当前产生汇编指令输出。例如下面的一条在线汇编指令:
asm("%0 += %1":"+r(foo):"r"(bar));
其中:"%0 += %1"就是模板。操作数"%0"、 "%1"作为一种形式参数,分别会由第一个冒号后面实际的输入、输出参数取代。带百分号后的数字表示的是冒号后参数的序号。例如:
asm("%0 = %1 + %2":"=r(foo):"r"(bar), "i"(10));
"%0"会由参数foo取代,"%1"会由参数bar取代,而"%2"会由数值10取代。
在汇编输出中,一个汇编指令模板里可以挂接多条汇编指令。其方法是用换行符"\n"来结束每一条指令,并可以用Tab键符"\t"将同一模板产生的汇编输出中的各条指令的换行显示时缩进到同一列,以使汇编指令显示清晰。例如:
asm("%0 += %1" \n\t "%0 += %1":"+r(foo):"i"(10));
2、操作数
在线汇编指令格式中,第一个冒号后的参数为输出操作数,第二个冒号后的参数为输入操作数,第三个冒号后跟着的则是clobber操作数。在各类操作数中,引号里的字符代表的是其存储类型约束符,括号里面的字符串表示是实际的操作数。
如果输出参数有若干个,可以用逗号将每一个参数隔开。同样,该法则适用于输入参数或clobber参数。注意clobber参数只能是1、2、3和4中的一个或多个,但不能是全部。
- 用SPMC75F2313A实现LIN结点(10-15)
- 使用SPMC75F2413A设计的通用变频器(06-07)
- 基于SPMC75F2413A单片机的直流变频洗衣机的设计(05-29)
- 基于SPMC75F2413A的直流变频洗衣机的设计方法(05-10)
- 采用SPMC75F2313A的直流伺服驱动器(05-09)
- 基于智能功率模组芯片PS21865A和SPMC75F2413A的AC变频空调方案实现(05-02)