ARM汇编与C混合汇编
-
一、ATPCS标准
-
概念
-
参数规则
-
返回值规则
-
函数返回值通过r0带回
-
#include <stdio.h> int function(void) { //局部变量:栈区分配空间,函数调用结束的时候,栈空间释放 int data = 100; return data; } int main(int argc, const char *argv[]) { int a = function(); printf("a = %d\n", a); //a: 100 return 0; } 问题:为什么data作为局部变量,还能将值传出来? 通过寄存器获取,将data的值放到r0寄存器中 在调用后,获取的返回值从r0中读取即可 栈区空间正常释放,r0寄存器中的值不会消失 #include <stdio.h> int *function(void) { int data = 100; return &data; } int main(int argc, const char *argv[]) { int *a = function(); printf("*a = %d\n", *a); //*a: 100或者Segmentation fault (core dumped)段错误(访问非法地址) return 0; } 问题:为什么*a打印出来还是100? 栈空间内容没有被释放,因为栈空间没有被重新划分 在打印之前调用其他函数,栈空间会被重新划分
-
-
栈模式规则
-
-
二、混合编程优势
-
三、汇编调用C语言
-
操作
-
例子1(==传入参数<=4个 >寄存器传递)
-
//asm.s文件 .global _start _start: @将r0-r3分别赋值O-3,然后作为参数传入到func(int a,int b,int c,int d) @函数中,求和保存到sum中,然后函数调用结束将sum返回,返回值保存到r2寄存器中 ldr sp,=0x40001ff0 @在对栈操作之前,必须先设置sp(Stack Pointer)的值 mov r0,#0 @参数1 mov r1,#1 @参数2 mov r2,#2 @参数3 mov r3,#3 @参数4 bl sum @跳转到sum函数,返回的结果在r0中 mov r2,r0 @返回值保存到r2寄存器中 stop: b stop //test.c文件 int sum(int a, int b, int c, int d) { int sum = 0; sum = a + b + c + d; return sum; }
-
-
例子2(==传入参数>4个 >栈传递)
-
//asm.s文件 .global _start _start: @在例子1的基础上将传参数量增加到6个 ldr sp,=0x40001ff0 @在对栈操作之前,必须先设置sp(Stack Pointer)的值 mov r0,#0 @参数1 mov r1,#1 @参数2 mov r2,#2 @参数3 mov r3,#3 @参数4 mov r4,#4 @参数5 mov r5,#5 @参数6 stmfd sp!,{r4,r5} @将r4、r5入栈(满栈递减模式) bl sum @跳转到sum函数,返回的结果在r0中 mov r2,r0 @返回值保存到r2寄存器中 stop: b stop //test.c文件 int sum(int a, int b, int c, int d, int e, int f) { int sum = 0; sum = a + b + c + d + e + f; return sum; }
-
-
-
四、C程序中调用汇编
-
格式:
-
示例
-
//asm.s文件 .global _start _start: @C程序中调用汇编 ldr sp,=0x40001ff0 @在对栈操作之前,必须先设置sp(Stack Pointer)的值 mov r0,#1 mov r1,#2 bl addTwoNum mov r2,r0 stop: b stop //test.c文件 int addTwoNum(int a,int b) { int c; asm( "add r0,%1,%2\n" //add r0,a,b ==> r0 = a + b "mov %0,r0\n" //mov c,r0 ==> c = r0 :"=r"(c) //输出列表%0 :"r"(a),"r"(b) //输入列表%1,%2 :"r0" ); return c; }
-
C语言不能直接操作寄存器,如果想操作得使用内联汇编的方式
-
-
IRQ使能示例
-
使能IRQ异常,需要操作CPSR寄存器
-
//asm.s文件 .global _start _start: @使能IRQ异常 ldr sp,=0x40001ff0 @在对栈操作之前,必须先设置sp(Stack Pointer)的值 bl enable_irq mov r1,r0 stop: b stop //test.c文件 int enable_irq(void)//使能IRQ(I置0)清0取反要用与 { int status; asm( "mrs r0,cpsr\n" //将CPSR寄存器中的值读取到r0中 "mov r1,#1\n" //r1 = 1 "bic r0,r0,r1,lsl #7\n" //r0 = r0 &~(r1 << 7) 将CPSR第7位(I)置0(默认为1) "msr cpsr,r0\n" //将r0的值储存到CPSR中 "mov %0,r0\n" //status在代码中有自己的编号 %0 :"=r"(status) //输出status变量 : //输入列表为空 :"r0","r1" ); return status; }
-
-
IRQ禁止示例
-
//asm.s文件 .global _start _start: @使能IRQ异常 ldr sp,=0x40001ff0 @在对栈操作之前,必须先设置sp(Stack Pointer)的值 bl enable_irq bl disable_irq mov r1,r0 stop: b stop //test.c文件 int disable_irq(void)//禁止IRQ(I置1)某位置1要用或 { int status; asm( "mrs r0,cpsr\n" //将CPSR寄存器中的值读取到r0中 "mov r1,#1\n" //r1 = 1 "orr r0,r0,r1,lsl #7\n" //r0 = r0 | (r1 << 7) 将CPSR第7位(I)置1 "msr cpsr,r0\n" //将r0的值储存到CPSR中 "mov %0,r0\n" //status在代码中有自己的编号 %0 :"=r"(status) //输出status变量 : //输入列表为空 :"r0","r1" ); return status; }
-
-
-
五、volatile关键字
-
六、异常处理