实验内容
(1)在C程序中调用汇编语言子程序addt,实现三个数的加法运算。
(2)在汇编程序中调用C语言函数
int addt(int x,int y,int z)
,实现三个数的加法运算。
(3)在C程序中内嵌汇编程序,由内嵌汇编实现三个数的加法运算。
实验原理
- 参数传递规则
- 根据ATPCS规则,C语言与汇编语言混合编程时,当参数不超过4个时使用寄存器R0~R3,依次将各字数据传送到寄存器;参数超过4个时将剩余的字数据传送到数据栈,入栈的顺序与参数顺序相反,即最后一个参数先入栈。
- C程序调用汇编
- 在C语言程序中调用用汇编语言程序的方法是使用
关键词,以声明该汇编程序。在汇编程序中使用EXTERN
伪操作声明该程序段可以被其它程序引用。EXPORT
- 例如
AREA StrCopy,CODE,READONLY
EXPORT strcopy ;声明strcopy为导出符号
strcopy
LDRB R2,[R1],#1 ;R1中的值为源数据块首地址
STRB R2,[R0],#1 ;R0中的值为目标数据块首地址
CMP R2,#0
BEN strcopy ;未复制完,循环
MOV PC,LR ;复制完毕,返回
END
extern void strcopy(char * d, const char * s);//声明strcopy为外部引用符号
int main(void)
{
const char * str = "source";
char dest[10];
//···
strcopy(dest,src);//调用汇编函数strcopy
//···
}
- 汇编程序调用C程序
- 为保证调用时参数能够正确的传递,汇编程序的设计要遵守基本的ATPCS规则,在汇编语言程序中应该使用
伪操作来声明要引用的C语言程序,并通过BL指令来调用子程序。IMPORT
- 在C语言程序中不需要做特别的声明,和编写通常的C程序一样。
- 例如,现在有C函数g()如下,。
int g(int a, int b, int c, int d, int e)
{
return a + b + c + d + e;
}
要求在汇编函数f中调用函数g(),以实现下面的功能
int f(int i){return -g(i, 2*i, 3*i, 4*i, 5*i);}
整个汇编函数f的代码如下:
;-----------------------------------------------------------------------------------------------------
; 汇编函数 int f(int i){return -g(i, 2*i, 3*i, 4*i, 5*i);}
; 在汇编程序中调用时,预先把i的实参存入寄存器R0
;-----------------------------------------------------------------------------------------------------
EXPORT f
AREA f,CODE,READONLY
IMPORT g ;声明g为外部引用符号
STR LR,[SP,#-4] ;断点存入堆栈
ADD R1,R0,R0 ;(R1)=i*2
ADD R2,R1,R0 ;(R2)=I*3
ADD R3,R1,R2 ;(R3)=i*5
STR R3,[SP,#-4] ;将第5个参数i*5存入堆栈
ADD R3,R1,R1 ;(R3)=i*4
BL g ;调用C函数g(),返回值在寄存器R0中
ADD SP,SP,#4 ;清栈
RSB R0,R0,#0 ;函数f的返回值(R0)=0-(R0)
LDR PC,[SP],#4 ;恢复断点并返回
END
- 内嵌汇编
- 所谓内嵌汇编程序,就是在C程序中直接编写汇编程序段而形成一个语句块,这个语句块可以使用除了
和BX
之外的全部ARM指令来编写,从而可以使程序实现一些不能从C获得的底层功能。BLX
- 在使用c编译器时,定义一个内嵌汇编程序需要使用关键字
,当编译器遇到这个关键字时,会启动内嵌汇编器对关键字下面的程序进行汇编工作,其格式如下:__asm
__asm //声明内嵌汇编代码
{
//汇编语句
}
- 例如
void enable_IRQ(void)
{
int tmp;
__asm
{
MRS tmp, CPSR
BIC tmp, tmp, #0x80
MSR CPSR_c, tmp
}
}
(1)在C程序中调用汇编语言子程序addt,实现三个数的加法运算。
代码实现
main.c
#define uint32 unsigned int
extern uint32 Addt(uint32 x,uint32 y,uint32 z);
uint32 sum;
int main(void)
{
sum=Addt(1,2,3);
}
asmfile.s
AREA addt,CODE,READONLY
EXPORT Addt
Addt ADD R0,R0,R1
ADD R0,R0,R2
MOV PC,LR
END
(2)在汇编程序中调用C语言函数int addt(int x,int y,int z),实现三个数的加法运算。
代码实现
main.c
#define uint32 unsigned int
uint32 addt(uint32 x,uint32 y,uint32 z)
{
return x+y+z;
}
int main()
{
asm_main();
}
asmfile.s
EXPORT asm_main
AREA asm_main, CODE, READONLY
IMPORT addt
ENTRY
START
MOV R0,#1
MOV R1,#2
MOV R2,#3
BL addt
END
(3)在C程序中内嵌汇编程序,由内嵌汇编实现三个数的加法运算。
代码实现
main.c
#define uint32 unsigned int
uint32 addt(uint32 x,uint32 y,uint32 z);
int main(void)
{
addt(1,2,3);
return 0;
}
uint32 addt(uint32 x,uint32 y,uint32 z)
{
uint32 temp;
__asm
{
add temp, x, y
add temp, temp, z
}
}
参考文章
ARM汇编程序设计之C程序调用汇编程序
C语言调用汇编函数 实现超过32位数的加法
ARM 汇编和C语言代码的相互调用