目录
  1. 1. C语言内嵌汇编基本格式
  2. 2. 例1
  3. 3. 例2
  4. 4. 例3
  5. 5. 总结
C内嵌ARM汇编

汇编语言经常会用在启动引导文件中,设置好相应的堆栈和必要的功能外设,才会跳转到C入口,但是我们只是知道汇编指令的功能,看不到每一步的具体实现。下面通过C语言内嵌汇编,做一些简单的例子。

C语言内嵌汇编基本格式

C语言内嵌汇编有两种基本格式,volatile表明编译其不要优化代码,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
__asm__ __volatile__(
"xxxxxxxxxxxx\n" ;指令1 用“\n”换行
"xxxxxxxxxxxx\n" ;指令2 用“\n”换行
"xxxxxxxxxxxx\n" ;指令3 用“\n”换行
:声明输出或输入变量;“=&r” 输出变量;“+r”输入输出变量
:声明输入变量 ; “r” 输入变量
:声明保护寄存器;“r0” 。。。。
);
asm volatile(
"xxxxxxxxxxxx\n" ;指令1 用“\n”换行
"xxxxxxxxxxxx\n" ;指令2 用“\n”换行
"xxxxxxxxxxxx\n" ;指令3 用“\n”换行
:声明输出或输入变量;“=&r” 输出变量;“+r”输入输出变量
:声明输入变量 ; “r” 输入变量
:声明保护寄存器;“r0” 。。。。
);

例1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <stdlib.h>

int main(){
unsigned int register a asm("r5");

printf("a = %d\r\n",a);
__asm__ __volatile__(
"mov r5,#100\n"
:
:
:"r5"
);

printf("a = %d\r\n",a);
return 0;
}

上面简单例子是将a变量和r5通用寄存器进行绑定,在内嵌汇编里面对r5寄存器操作a的值也会相应改变

例2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>
#include <stdlib.h>

int main(){

unsigned int a=1, b=2,c=3;
int d,e,f;
__asm__ __volatile__(
"mov r0, %[a]\n"
"mov r1, %[b]\n"
"mov r2, %[c]\n"

"mov %[d], r0\n"
"mov %[e], r1\n"
"mov %[f], r2\n"
:[d]"=&r"(d),[e]"=&r"(e),[f]"=&r"(f)
:[a]"r"(a),[b]"r"(b),[c]"r"(c)
:"r0","r1","r2"
);
printf("d = %d\r\n",d);
printf("e = %d\r\n",e);
printf("f = %d\r\n",f);
return 0;
}

上面内嵌汇编的功能就是将变量a,b,c的值赋值给变量d,e,f。第一个冒号后面将C函数的变量声明为输出变量名且别名位%[d] %[e]%[f]。也可以使用默认的%0 %1 依次对C函数的变量进行操作

例3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 #include <stdio.h>
int mysum(int num1,int num2){
int sum1,sum2;
__asm__ __volatile__(
"ldr r0 ,=0xfffffff8\n"
"ldr r1 ,=0xa\n"
"adds %[sum1] ,r0,r1\n"
"ldr r0, =1\n"
"ldr r1, =1\n"
"adc %[sum2],r0,r1\n"
:[sum1]"=&r"(sum1),[sum2]"=&r"(sum2)
:[num1]"r"(num1),[num2]"r"(num2)
:"r0","r1"
);

printf("sum1 = %ld\n",sum1);
printf("sum2 = %ld\n",sum2);
return sum2;
}


int main(void) {
int a=0xfffffff4 ,b =0x11;
printf("sum =a+b= %ld\r\n",mysum(a,b));

return 0;
}

上面例子是add指令的使用,add是基础的加指令,CSPR_C不会产生进位结合借位。adds会产生CSPR_C不会产生进位结合借位。adc在相加的时候会将CSPR_C的位相加。

这里ldr是一个伪指令:ldr可以将任意值赋值给寄存器。在这里mov指令需要满足三个条件中的一个才能使用:

  1. 立即数小于255 ; eg:mov r0 ,254
  2. 立即数右移偶数次小于255 ; eg: mov r0 ,0xf100 ; 0xff00右移8位,0xf1小于0xff,
  3. 立即数是特殊值;0xfffffff

总结

这里举的例子都是比较简单的,虽然汇编使用不多,但是在能看懂汇编语言我们才可以在其基础上修改,例如堆栈的大小和基地址。

文章作者: ZhaoH.T
文章链接: http://www.funful.ink/2019/08/24/2019-08-24-C-Assembly/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 FunfulBlog

评论