c语言调用汇编语言
在main.c中调用在test.s中定义的init_1函数,并通过调试的方式跟踪寄存器的内容来验证。
值得注意的是,在ARM中,寄存器R0~R3保存的是函数的参数,当参数大于4个后,多余的参数将会被压入栈中。而返回结果会被保存在R0当中。
main.c代码
#include<stdio.h>
extern void Init_1(void);
int main()
{
Init_1();
return 0;
}
test.s代码
AREA My_Function,CODE,READONLY ;这一行必要的除了My_Function可以自己取名以外,其他的都是模板
EXPORT Init_1 ; 与在c文件中定义的Init_1函数关联起来
; 高级语言中的声明和使用变量其实是对板子寄存器的使用,所以我们只需要直接使用寄存器即可
Init_1
MOV R1,#0 ; 设R1寄存器为i
MOV R2,#0 ; 设R2寄存器为j
LOOP ; 写在最左边的是程序段的段名,执行跳转程序时用到
CMP R1,#10 ; 比较R1和10的大小
BHS LOOP_END ; 如果R1大于等于10,则跳转到LOOP_END程序段,反之忽略该语句,直接执行下面的语句
ADD R2,#1 ; j++
ADD R1,#1 ; i++
B LOOP ; 循环
LOOP_END
NOP
END ; 必须空格后再写END,不然会被认为是段名,表示程序结束
在keil中设置对应断点。
点击build后开始调试 按F11,可以看到R1、R2的值不断增加。 直到值变为0xA,也就是十进制的11的时候退出循环。
修改init_1函数功能再次调用
把init_1函数修改为传入一个整数x,然后返回x+100的值。 main.c代码
# include<stdio.h>
extern int Init_1(int x);
int main(){
int x=Init_1(1);
printf("%d",x);
return 0;
}
test.s代码
AREA My_Function,CODE,READONLY
EXPORT Init_1 ; 与在c文件中定义的Init_1函数关联起来
; 高级语言中的声明和使用变量其实是对板子寄存器的使用,所以我们只需要直接使用寄存器即可
Init_1
ADD R0,#1 ; 将传入的值+1
MOV PC,LR ; LR(R14)保存返回地址,PC(R15)是当前地址,把LR给PC就是从子程序返回,返回R0
LOOP ; 写在最左边的是程序段的段名,执行跳转程序时用到
CMP R1,#10 ; 比较R1和10的大小
BHS LOOP_END ; 如果R1大于等于10,则跳转到LOOP_END程序段,反之忽略该语句,直接执行下面的语句
ADD R2,#1 ; j++
ADD R1,#1 ; i++
B LOOP ; 循环
LOOP_END
NOP
END ; 必须空格后再写END,不然会被认为是段名,表示程序结束
设置断点 重新build后开始调试 进入init_1函数前R0寄存器的值
执行一次后R0的值变为0x65,也就是十进制的101。 继续调试,到调用printf函数,可以看到x的值为0x65,也就是十进制的101。
在汇编函数中调用c语言函数
在mian.c中定义一个fun函数,作用是把传入的一个整形参数+1再返回。 main.c代码
# include<stdio.h>
extern int Init_1(int x);
int fun(int x);
int main(){
int x=Init_1(1);
printf("%d",x);
return 0;
}
int fun(int x){
return x+2;
}
test.s代码
AREA My_Function,CODE,READONLY
EXPORT Init_1 ; 与在c文件中定义的Init_1函数关联起来
IMPORT fun ; 声明get5 为外部引用
; 高级语言中的声明和使用变量其实是对板子寄存器的使用,所以我们只需要直接使用寄存器即可
Init_1
ADD R0,#1 ;将传入的值+1
MOV R1,#0 ; 设R1寄存器为i
MOV R2,#0 ; 设R2寄存器为j
BL fun ; 调用fun,返回的值传入R0
MOV PC,LR ;LR(R14)保存返回地址,PC(R15)是当前地址,把LR给PC就是从子程序返回,返回R0
LOOP ; 写在最左边的是程序段的段名,执行跳转程序时用到
CMP R1,#10 ; 比较R1和10的大小
BHS LOOP_END ; 如果R1大于等于10,则跳转到LOOP_END程序段,反之忽略该语句,直接执行下面的语句
ADD R2,#1 ; j++
ADD R1,#1 ; i++
B LOOP ; 循环
LOOP_END
NOP
END ; 必须空格后再写END,不然会被认为是段名,表示程序
重新设置断点
重新build再调试 R0初始值为1。 执行init_1函数后+1
执行完fun函数后再+2
|