手机操作系统 2016-11-15
内联汇编即在C中直接使用汇编语句进行编程,使程序可以在C程序中实现C语言不能完成的一些工作,例如,在下面几种情况中必须使用内联汇编或嵌入型汇编
__asm__ __volatile__("asm code":output:input:changed registers);
Note:
"mov r0, r0\n\t" "mov r1,r1\n\t" "mov r2,r2"
:"constraint" (variable)
"constraint"
用于定义variable的存放位置: r
表示使用任何可用的寄存器 m
表示使用变量的内存地址 +
可读可写 =
只写 &
表示该输出操作数不能使用输入部分使用过的寄存器,只能用"+&"
或"=&"
的方式使用
:"constraint" (variable/immediate)
"constraint"
用于定义variable的存放位置: r
表示使用任何可用的寄存器(立即数和变量都可以) m
表示使用变量的内存地址 i
表示使用立即数
int a=100,b=200; int result; __asm__ __volatile__( "mov %0,%3\n\t" //%0是一个占位符,表示result,之后的类推 "ldr r0,%1\n\t" "ldr r1,%2\n\t" "str r0,%2\n\t" "str %1,%1\n\t" :"=r"(result),"+m"(a),"+m"(b) :"i"(123) );
C和汇编相互调用要特别注意遵守相应的ATPCS规则
//.c #include <stdio.h> extern void strcopy(char* des, const char* src); int main(){ const char* srcstr = "src string"; char desstr[]="des string"; strcopy(desstr, srcstr); return 0; }
;.asm .global strcopy strcopy: ;R0指向目的字符串 ;R1指向源字符串 LDRB R2, [R1], #1 ;加载字节并更新源字符串指针地址 STRB R2, [R0], #1 ;存储季节并更新目的字符串指针地址 CMP R2, #0 ;判断是否为字符串结尾 BNE strcopy ;如果不是,程序跳转到strcopy继续循环 MOV pc, ir ;程序返回
//.c int fcn(int a, int b , int c, int d, int e){ return a+b+c+d+e; }
;.asm ;假设程序进入f时,R0中的值为i ;int f(int i){return fcn(i, 2*i, 3*i, 4*i, 5*i);} .text .global _start _start: STR lr, [sp, #-4]! ;保存返回地址lr ADD R1, R0, R0 ;计算2*i(第2个参数) ADD R2, R1, R0 ;计算3*i(第3个参数) ADD R3, R1, R2 ;计算5*i STR R3, [SP, #-4]! ;第5个参数通过堆栈传递 ADD R3, R1, R1 ;计算4*i(第4个参数) BL fcn ;调用C程序 ADD sp, sp, #4 ;从堆栈中删除第五个参数 .end