SPMC75和ASM(汇编)混合编程的应用
3、操作符约束符
约束符的作用在于指示GCC,使用在汇编指令模板中的操作数的存储类型。表1-1列出了一些约束符和它们分别代表的操作数不同的存储类型,也列出了用在操作数约束符之间的两个约束符前缀。
表 1-1 操作数存储类型约束符及约束符前缀
约束符 | 操作数存储类型 | 约束符前缀及含义解释 | |
r | 寄存器中的数值 | = | + |
m | 存储器中的数值 | 为操作数赋值 | 操作数在赋值前先参加运算 |
i | 立即数 | ||
p | 全局变量操作数 |
4.2 应用举例
利用嵌入式汇编实现对端口寄存器的操作。
//=================================================================== asm(".include Spmc75_regs.inc"); ( 1 ) //=================================================================== //------------------------------------- asm("[P_IOD_Attrib_ADDR] = %0 \n\t" \ ( 2 ) "[P_IOD_Dir_ADDR] = %0 \n\t" \ ( 3 ) "[P_IOD_Buffer_ADDR] = %0 \n\t" \ ( 4 ) "[P_IOD_Data_ADDR] = %1 \n\t" \ ( 5 ) : \ ( 6 ) :"r"(0xFFFF),"r"(0x0000) \ ( 7 ) :"1"); ( 8 ) //------------------------------------- |
在C的嵌入式汇编中,当使用端口寄存器时,需要在C文件中加入汇编的包含头文件,(1)所示。那么可以使用端口寄存器的名称,而不必去使用端口的实际地址;(2)、(3)、(4)和(5)分别对端口寄存器的各个属性赋值初始化;(6)没有输出参数;(7)操作数%0=0xFFFF,%1=0x0000,操作数的存储类型都是寄存器中的数值;(8)clobber参数,在寄存器传递实参的时候不能使用寄存器R1。
利用嵌入式汇编实现对端口寄存器的位值读取。
A . //------------------------------------- asm("r1 = %1; \n\t" \ ( 1.a ) "tstb [r1],%2; \n\t" \ ( 2.a ) "jz 2; \n\t" \ ( 3.a ) "%0 = 0x01; \n\t" \ ( 4.a ) "jmp 1; \n\t" \ ( 5.a ) "%0 = 0x00; \n\t" \ ( 6.a ) :"=r"(result) \ ( 7 ) :"i"(P_IOD_Buffer),"i"(14) \ ( 8 ) :"1","2"); ( 9 ) //------------------------------------- B . //------------------------------------- // GCC inline ASM start r1 = 28793; ( 1.b ) tstb [r1],14; ( 2.b ) jz 2; ( 3.b ) R3 = 0x01; ( 4.b ) jmp 1; ( 5.b ) R3 = 0x00; ( 6.b ) // GCC inline ASM end |
上面A、B分别是嵌入式汇编和实际编译出来的代码。首先需要清楚一点%0=i、%1=P_IOD_Buffer、%2=14,通过(7)和(8)行可以了解。(1.a)将端口IOD的地址存放到R1中;(2.a)测试IOD的14位;(3.a)如果等于零跳过两行,即跳过(4.a)和(5.a)在(6.a)中为输出参数赋值0x00;如果不等于零则顺序执行(4.a)为输出参数赋值0x01;(5.a)跳过一行,即跳过(6.a)。通过上面的过程可以应用嵌入式汇编实现对端口位的测试,将测试的结果保存在变量result中,行(7)所示。行(9)clobber参数,约束行(7)的"r"在编译时不能使用R1和R2,所以可以在(4.b)和(6.b)中看到使用了R3。但如果行(9)是":"1","2","3");",那么编译出来的(4.b)和(6.b)中只能使用R4,由此可知":"1","2","3","4");"是绝对不允许的。
典型的应用方式。
通常的应用是用宏汇编的形式定义出来,使用的时候就象函数一样来使用。
//================================================================ //Function: SETB Function //Example: SETB(_P_IOA_Data,0x8); //================================================================ #define SETB(Addr,Num) \ asm( \ "r1=%0;\n\t" \ "r2=%1;\n\t" \ "setb [r1],r2\n\t" \ : \ :"i"(Addr),"i"(Num) \ :"1","2" \ ); SETB ( P_IOD_Data , 14 ); // 置位 IOD14 SETB ( P_IOB_Data , 10 ); // 置位 IOB10 |
- 用SPMC75F2313A实现LIN结点(10-15)
- 使用SPMC75F2413A设计的通用变频器(06-07)
- 基于SPMC75F2413A单片机的直流变频洗衣机的设计(05-29)
- 基于SPMC75F2413A的直流变频洗衣机的设计方法(05-10)
- 采用SPMC75F2313A的直流伺服驱动器(05-09)
- 基于智能功率模组芯片PS21865A和SPMC75F2413A的AC变频空调方案实现(05-02)