arm汇编语言调用C函数之参数传递

合集下载

arm汇编调用c语言

arm汇编调用c语言

arm汇编调用c语言在嵌入式系统开发中,ARM汇编语言是一种重要的编程语言,它可以直接操作硬件资源,提高系统的性能和效率。

然而,ARM汇编语言的编写相对复杂,可读性较差,因此在实际开发中,我们通常会使用C语言来编写大部分的代码。

那么,如何在ARM汇编中调用C语言函数呢?本文将介绍一种常用的方法。

首先,我们需要了解一些基本的概念。

在ARM架构中,函数调用的过程可以简化为以下几个步骤:保存寄存器、传递参数、调用函数、恢复寄存器、返回结果。

在ARM汇编中,我们可以使用一些特殊的指令来完成这些操作。

首先,我们需要保存寄存器。

在ARM架构中,R0-R3寄存器用于传递参数,R4-R11寄存器用于保存临时变量。

在调用C语言函数之前,我们需要将这些寄存器的值保存起来,以免被C语言函数修改。

可以使用STMFD指令将这些寄存器的值保存到栈中。

接下来,我们需要传递参数。

在ARM架构中,函数的参数通常通过寄存器传递。

如果参数的个数超过了寄存器的数量,多余的参数将通过栈传递。

可以使用MOV指令将参数的值保存到相应的寄存器中。

然后,我们可以调用C语言函数。

在ARM汇编中,可以使用BL指令来调用函数。

BL指令会将当前函数的返回地址保存到LR寄存器中,并跳转到目标函数的地址。

在C语言函数执行完毕后,可以使用BX LR指令返回到调用函数的地址。

最后,我们需要恢复寄存器。

在调用C语言函数之前,我们将寄存器的值保存到了栈中,因此在函数执行完毕后,需要将这些值从栈中恢复出来。

可以使用LDMFD指令将这些值恢复到相应的寄存器中。

除了上述的基本操作,还需要注意一些细节。

例如,栈的大小需要根据实际情况进行调整,以免发生栈溢出的情况。

另外,C语言函数的返回值通常保存在R0寄存器中,可以使用MOV指令将其保存到其他寄存器中,以便后续的操作。

总结起来,ARM汇编调用C语言函数的过程可以简化为以下几个步骤:保存寄存器、传递参数、调用函数、恢复寄存器、返回结果。

汇编语言的过程调用与c语言的函数调用

汇编语言的过程调用与c语言的函数调用
; ()
{{
(*)(*);
}}
两个函数都是返回变量和地积,可通用地或称为参数化版本可用于任意两整数之积,而专用地版本仅能计算全局变量和地乘积.文档来自于网络搜索
从变量地作用域原则出发,我们可以将变量分为全局变量和局部变量;换一个方式,从变量地生存期来分,可将变量分为动态存储变量及静态存储变量.文档来自于网络搜索
, .....
作为遵从调用约定()调用者,则需这样调用上述过程:
;
;
;
, * ;
而如果遵从调用约定,则:
,
......
, [ ] ;
, [ ];
......
* ;
,
, ;
......
, [ ];
, [ ];
, [ ;
, [ ];
......
, ;
* ;
在被调用地过程内,分为种情况:
.无参数,也无局部变量
;
另一选择是,将用作地变量声明为.
;
;
还有另一种方法,即,总是传递指针.
; (, )
, ;
,
,
,
,
, []
,
, []
这种方法在保留了我们可以声明仅需地变量类型地同时,也确保位地方法正确压栈.语言中地每一个函数都是一个独立地代码块.一个函数地代码块是隐藏于函数内部地,不能被任何其它函数中地任何语句(除调用它地语句之外)所访问(例如,用语句跳转到另一个函数内部是不可能地).构成一个函数体地代码对程序地其它部分来说是隐蔽地,它既不能影响程序其它部分,也不受其它部分地影响.换言之,由于两个函数有不同地作用域,定义在一个函数内部地代码数据无法与定义在另一个函数内部地代码和数据相互作用.文档来自于网络搜索

C程序访问ARM汇编程序中的函数

C程序访问ARM汇编程序中的函数

C程序访问ARM汇编程序中的函数
C 程序调用ARM 汇编子程序,要做的主要工作有两个:一是在C 程序中用关键字EXTERN 声明ARM 汇编子程序的函数原型(C 程序是函数结构的程
序设计风格),声明该函数的实现代码在其他文件中;二是在ARM 汇编子程序
中用伪指令EXPORT 导出子程序名,并且用该子程序名最为ARM 汇编代码段
的标识,最后用MOV PC,LR 指令返回。

这样,在C 程序中就可以像调用C 函数一样调用该ARM 汇编子程序了。

无论是C 语言中的函数名还是ARM 汇编语言中的标号,其作用一样,都只是起到表明该函数名或标号存储单元起始地
址的作用。

具体操作步骤如下:
(1)ARM 汇编程序中,用该子程序名作为ARM 汇编代码段的标识,定义
程序代码,最后用MOV PC,LR 指令返回;
(2)ARM 汇编程序中用伪指令EXPORT 导出子程序名;
(3)C 程序中用关键字EXTERN 声明该ARM 汇编子程序的函数原型,然
后就可在C 程序中访问该函数;
(4)函数调用时的参数传递规则:寄存器组中的【R0R3】作为参数传递而
返回值用寄存器R0 返回,如果参数数目超过4 个,则使用堆栈进行传递。

程序清单如下:
// main.c
#include
extern void my_strcpy(const char *src,char *dest);
int main(){ char *strsrc = “Welcome to XU”;char temp[32] = {0};。

C和汇编之间的函数调用.

C和汇编之间的函数调用.

●C 和汇编之间的函数调用ARM 工程中, C 程序调用汇编函数和汇编程序调用 C 函数时经常的事情,遵守ARM-Thumb 过程调用标准 ATPCS (ARM-Thumb Procedure Call Standard 。

ATPCS 标准—— ARM 编译器使用的函数调用规则(详见下面(温故知新 C 语言程序中的调用int main({printf("1234+5678=%d\n",sum(1234,5678;return 0;}请编写 sum 函数,实现两个数的相加。

int sum(int x,int y{int s;s=x+y;return s}C 程序调用汇编程序函数要点:1. 在汇编语言中,用该函数名作为汇编代码段的标识,定义函数代码, 最后用MOV PC,LR返回2. 在汇编语言中用 EXPORT 导出函数名3. 在 C 语言中用 extern 关键词声明函数原型。

4. 函数调用时参数传递规则:寄存器组中的 {R0-R3}作为参数传递和结果返回寄存器,如果参数数目超过 4个,则使用堆栈进行传递。

;工程 exp10_1_2;汇编函数文件 strcopy.s;把 R1指向的数据块复制到 R0指向的存储块。

AREA StrCopy,CODE,READONLYEXPORT strcopystrcopyLDRB R2,[R1],#1STRB R2,[R0],#1CMP R2,#0BNE strcopyMOV PC,LREND; C 文件 main.c;调用 strcopy 函数extern void StrCopy(char *d,const char *s; //声明 strcopy 为外部引用符号int main(void{const char *src=” Source ” ;char dest[12]=” Destination ” ;strcopy(dest,src; //调用汇编函数 strcopyprintf(“ After copying:\n” ;printf(“ %s\n%s\n” ,src,dest;return(0;}根据 ATPCS 的 C 语言程序调用汇编函数规则,参数由左向右依次传递给寄存器 R0~R3,可知汇编函数 strcopy 在 C 程序中的原型应该为:void strcopy(char *d,const char *s;其中,参数 d 对应 R0,参数 s 对应 R1。

armc语言调用汇编函数

armc语言调用汇编函数

armc语言调用汇编函数
ARM系列处理器的程序开发,可以采用ARM汇编语言和C语言来实现,而两者可以互相调用。

本文主要介绍一种ARM处理器下,C语言调用汇编语言编写的函数的实现过程。

二、C语言调用汇编函数的实现
1. 首先,要在汇编代码中定义函数,函数的开始以及结束用特定的指令来表示,如下所示:
MyAdd PROC
;
MyAdd ENDP
2. 接着,定义C语言源程序中的函数,以下是MyAdd函数在C 语言源程序中的定义:
int MyAdd ( int a, int b ) //定义函数MyAdd,参数a,b
{
int c;
asm{
add a,b,c //汇编语言指令,将参数a ,b的和结果送给c
}
return c;
}
3. 若要将汇编语言定义的函数MyAdd引入C语言源程序,那么只需要在C语言源程序的前面加上如下的宏定义:
#define MyAdd ( int a, int b )
( {
int c ;
asm{
add a,b,c
}
c ;
} )
4. 最后,在C语言源程序的其他地方,就可以用MyAdd函数来调用汇编代码中定义的函数,实现C语言调用汇编函数的功能。

三、结论
ARM系列处理器的程序开发可以采用ARM汇编语言和C语言来实现,两者之间可以互相调用,C 语言也可以调用汇编语言编写的函数,只需要定义一个宏,就可以实现C语言调用汇编函数。

汇编与C语言的相互调用

汇编与C语言的相互调用

汇编与C语言的相互调用汇编与C语言的相互调用一、实验目的阅读Embest EduKit-III启动代码,观察处理器启动过程;学会使用Embest IDE辅助信息窗口来分析判断调试过程和结果;学会在Embest IDE环境中编写、编译与调试汇编和C语言相互调用的程序。

二、实验设备硬件:PC机。

软件:Embest IDE Pro2004集成开发环境,Windows98/2000/NT/XP。

三、实验原理1.ARM过程调用ATPCS(ARM)ATPCS是一系列用于规定应用程序之间相互调用的基本规则,这此规则包括:支持数据栈限制检查;支持只读段位置无关(ROPI);支持可读/写段位置无关(RWPI);支持ARM程序和Thumb程序的混合使用;处理浮点运算。

使用以上规定的ATPCS规则时,应用程序必须遵守如下:程序编写遵守ATPCS;变量传递以中间寄存器和数据栈完成;汇编器使用-apcs开关选项。

关于其他ATPCS规则,用户可以参考ARM处理器相关书籍或登录ARM公司网站。

程序只要遵守ATPCS相应规则,就可以使用不同的源代码编写程序。

程序间的相互调用最主要的是解决参数传递问题。

应用程序之间使用中间寄存器及数据栈来传递参数,其中,第一个到第四个参数使用R0-R3,多于四个参数的使用数据栈进行传递。

这样,接收参数的应用程序必须知道参数的个数。

但是,在应用程序被调用时,一般无从知道所传递参数的个数。

不同语言编写的应用程序在调用时可以自定义参数传递的约定,使用具有一定意义的形式来传递,可以很好地解决参数个数的问题。

常用的方法是把第一个或最后一个参数作为参数个数(包括个数本身)传递给应用程序。

ATPCS中寄存器的对应关系如表3-5所列:ARM寄存器ARPCS别名APTCS寄存器说明R0~R3a1~a4参数/结果/scratch寄存器1-4R4v1局部变量寄存器1R5v2局部变量寄存器2R6v3局部变量寄存器3R7v4,wr局部变量寄存器4Thumb状态工作寄存器R8v5ARM状态局部变量寄存器5R9v6,sb ARM状态局部变量寄存器6RWPI的静态基址寄存器R10v7,s1ARM状态局部变量寄存器7数据栈限制指针寄存器R11v8ARM状态局部变量寄存器8R12ip子程序内部调用的临时(scratch)寄存器R13sp数据栈指针寄存器R14lr链接寄存器R15PC程序计数器2.main()函数与__gccmain()当应用程序中包含了main()函数,将会引起对C运行时库的初始化。

C语言和汇编语言参数的传递

C语言和汇编语言参数的传递

C语言和汇编语言参数的传递在C语言中,函数参数的传递有两种方式:值传递和引用传递。

在值传递中,函数将参数的实际值复制到形式参数中,这意味着在函数内对参数的任何更改都不会影响到原始变量。

而在引用传递中,函数通过传递变量的地址来传递参数,这允许函数直接操作原始变量,因此在函数内对参数的任何更改都会影响到原始变量。

C语言中,参数的传递方式是根据函数声明时参数类型的决定的。

例如,如果参数是基本数据类型(如整数或浮点数),则使用值传递;如果参数是指针类型,则使用引用传递。

尽管在C语言中,通过指针传递可以实现引用传递的效果,但是它并不是真正的引用传递。

在汇编语言中,参数的传递方式主要依赖于具体的指令集架构。

通常,汇编语言中只有值传递,因为汇编语言中没有高级语言中的变量和函数的概念,只有寄存器和内存地址。

在汇编语言中,将参数的值加载到寄存器中,然后通过寄存器传递给函数或子程序。

这些值可以是常数、寄存器或者内存地址。

在x86指令集架构中,参数可以通过寄存器传递,如EAX、EBX、ECX、EDX等,也可以通过栈传递。

在函数调用之前,参数的值通常会被存储在特定的寄存器中,然后通过指令将这些值传递给函数。

对于超过寄存器数量的参数,剩余的参数会被依次存储在栈上,由函数内部通过栈指针来访问。

与C语言相比,汇编语言中参数的传递要更为低级和复杂。

由于汇编语言中直接操作寄存器和内存,因此需要手动将参数的值加载到寄存器或内存中,然后将寄存器或内存中的值传递给函数或子程序。

另外,由于没有类型检查,程序员需要确保传递给函数或子程序的参数类型和数量是正确的。

总的来说,C语言和汇编语言在参数的传递方面存在一些不同之处。

C语言提供了更高级的抽象,允许使用引用传递,而汇编语言更为低级,只能通过寄存器或栈传递参数。

因此,在编写程序时,需要根据具体的需求和语言特性来选择合适的参数传递方式。

ARM在汇编代码中调用C函数.

ARM在汇编代码中调用C函数.

ARM在汇编代码中调用C函数对于ARM体系来说,不同语言撰写的函数之间相互调用(mix calls)遵循的是ATPCS(ARM-Thumb Procedure Call Standard),ATPCS主要是定义了函数呼叫时参数的传递规则以及如何从函数返回,关于ATPCS的详细内容可以查看ADS1.2 Online Books ——Developer Guide的2.1节。

这篇文档要讲的是汇编代码中对C函数调用时如何进行参数的传递以及如何从C函数正确返回不同于x86的参数传递规则,ATPCS建议函数的形参不超过4个,如果形参个数少于或等于4,则形参由R0,R1,R2,R3四个寄存器进行传递;若形参个数大于4,大于4的部分必须通过堆栈进行传递。

我们先讨论一下形参个数为4的情况.实例1:test_asm_args.asm//--------------------------------------------------------------------------------IMPORT test_c_args ;声明test_c_args函数AREA TEST_ASM, CODE, READONLYEXPORT test_asm_argstest_asm_argsSTR lr, [sp, #-4]! ;保存当前lrldr r0,=0x10 ;参数 1ldr r1,=0x20 ;参数 2ldr r2,=0x30 ;参数 3ldr r3,=0x40 ;参数 4bl test_c_args ;调用C函数LDR pc, [sp], #4 ;将lr装进pc(返回main函数)ENDtest_c_args.c//--------------------------------------------------------------------------------void test_c_args(int a,int b,int c,int d){printk("test_c_args:\n");printk("%0x %0x %0x %0x\n",a,b,c,d);}main.c//--------------------------------------------------------------------------------int main(){test_asm_args();for(;;);}程序从main函数开始执行,main调用了test_asm_args,test_asm_args调用了test_c_args,最后从test_asm_args返回main.代码分别使用了汇编和C定义了两个函数,test_asm_args 和test_c_args,test_asm_args调用了test_c_args,其参数的传递方式就是向R0~R3分别写入参数值,之后使用bl语句对test_c_args进行调用。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

arm汇编语言调用C函数之参数传递于ARM体系来说,不同语言撰写的函数之间相互调用(mix calls)遵循的是 ATPCS(ARM-Thumb Procedure Call Standard),ATPCS 主要是定义了函数呼叫时参数的传递规则以及如何从函数返回,关于ATPCS的详细内容可以查看ADS1.2 Online Books ——Developer Guide的2.1节。

这篇文档要讲的是汇编代码中对C函数调用时如何进行参数的传递以及如何从C函数正确返回。

不同于x86的参数传递规则,ATPCS建议函数的形参不超过4个,如果形参个数少于或等于4,则形参由R0,R1,R2,R3四个寄存器进行传递;若形参个数大于4,大于4的部分必须通过堆栈进行传递。

我们先讨论一下形参个数为4的情况.实例1:test_asm_args.asm//--------------------------------------------------------------------------------IMPORT test_c_args ;声明test_c_args函数AREA TEST_ASM, CODE, READONLYEXPORT test_asm_argstest_asm_argsSTR lr, [sp, #-4]! ;保存当前lrldr r0,=0x10 ;参数 1ldr r1,=0x20 ;参数 2ldr r2,=0x30 ;参数 3ldr r3,=0x40 ;参数 4bl test_c_args ;调用C函数LDR pc, [sp], #4 ;将lr装进pc(返回main函数)ENDtest_c_args.c//--------------------------------------------------------------------------------void test_c_args(int a,int b,int c,int d){printk("test_c_args:\n");printk("%0x %0x %0x %0x\n",a,b,c,d);}main.c//--------------------------------------------------------------------------------int main(){test_asm_args();for(;;);}程序从main函数开始执行,main调用了test_asm_args,test_asm_args 调用了test_c_args,最后从test_asm_args返回main。

代码分别使用了汇编和C定义了两个函数,test_asm_args 和 test_c_args,test_asm_args调用了test_c_args,其参数的传递方式就是向R0~R3分别写入参数值,之后使用bl语句对test_c_args进行调用。

其中值得注意的地方是用红色标记的语句,test_asm_args在调用test_c_args之前必须把当前的 lr入栈,调用完test_c_args之后再把刚才保存在栈中的lr写回pc,这样才能返回到main函数中。

如果test_c_args的参数是8个呢?这种情况test_asm_args应该怎样传递参数呢?实例2:test_asm_args.asm//--------------------------------------------------------------------------------IMPORT test_c_args ;声明test_c_args函数AREA TEST_ASM, CODE, READONLYEXPORT test_asm_argstest_asm_argsSTR lr, [sp, #-4]! ;保存当前lrldr r0,=0x1 ;参数 1ldr r1,=0x2 ;参数 2ldr r2,=0x3 ;参数 3ldr r3,=0x4 ;参数 4ldr r4,=0x8str r4,[sp,#-4]! ;参数 8 入栈ldr r4,=0x7str r4,[sp,#-4]! ;参数 7 入栈ldr r4,=0x6str r4,[sp,#-4]! ;参数 6 入栈ldr r4,=0x5str r4,[sp,#-4]! ;参数 5 入栈bl test_c_args_lotsADD sp, sp, #4 ;清除栈中参数 5,本语句执行完后sp指向参数6 ADD sp, sp, #4 ;清除栈中参数 6,本语句执行完后sp指向参数7 ADD sp, sp, #4 ;清除栈中参数 7,本语句执行完后sp指向参数8 ADD sp, sp, #4 ;清除栈中参数 8,本语句执行完后sp指向 lrLDR pc, [sp],#4 ;将lr装进pc(返回main函数)ENDtest_c_args.c//--------------------------------------------------------------------------------void test_c_args(int a,int b,int c,int d,int e,int f,int g,int h){printk("test_c_args_lots:\n");printk("%0x %0x %0x %0x %0x %0x %0x %0x\n",a,b,c,d,e,f,g,h);}main.c//--------------------------------------------------------------------------------int main(){test_asm_args();for(;;);}这部分的代码和实例1的代码大部分是相同的,不同的地方是test_c_args的参数个数和test_asm_args的参数传递方式。

在test_asm_args中,参数1~参数4还是通过R0~R3进行传递,而参数5~参数8则是通过把其压入堆栈的方式进行传递,不过要注意这四个入栈参数的入栈顺序,是以参数8->参数7->参数6->参数5的顺序入栈的。

直到调用test_c_args之前,堆栈内容如下:sp->+----------+| 参数5 |+----------+| 参数6 |+----------+| 参数7 |+----------+| 参数8 |+----------+| lr |+----------+test_c_args执行返回后,则设置sp,对之前入栈的参数进行清除,最后将lr装入pc返回main函数,在执行 LDR pc, [sp],#4 指令之前堆栈内容如下:+----------+| 参数5 |+----------+| 参数6 |+----------+| 参数7 |+----------+| 参数8 |sp->+----------+| lr |+----------+基于ARM的C语言与汇编语言混合编程1、C语言与汇编语言混合编程应遵守的规则ARM编程中使用的C语言是标准C语言,ARM的开发环境实际上就是嵌入了一个C语言的集成开发环境,只不过这个开发环境与ARM的硬件紧密相关。

在使用C语言时,要用到和汇编语言的混合编程。

若汇编代码较为简洁,则可使用直接内嵌汇编的方法;否则要将汇编程序以文件的形式加入到项目中,按照ATPCS(ARM/Thumb过程调用标准,ARM/Thumb Procedure Call Standard)的规定与C程序相互调用与访问。

在C程序和ARM汇编程序之间相互调用时必须遵守ATPCS规则。

ATPCS规定了一些子程序间调用的基本规则,哪寄存器的使用规则,堆栈的使用规则和参数的传递规则等。

1)寄存器的使用规则子程序之间通过寄存器r0~r3来传递参数,当参数个数多于4个时,使用堆栈来传递参数。

此时r0~r3可记作A1~A4。

在子程序中,使用寄存器r4~r11保存局部变量。

因此当进行子程序调用时要注意对这些寄存器的保存和恢复。

此时r4~r11可记作V1~V8。

寄存器r12用于保存堆栈指针SP,当子程序返回时使用该寄存器出栈,记作IP。

寄存器r13用作堆栈指针,记作SP。

寄存器r14称为链接寄存器,记作LR。

该寄存器用于保存子程序的返回地址。

寄存器r15称为程序计数器,记作PC。

2)堆栈的使用规则ATPCS规定堆栈采用满递减类型(FD,Full Descending),即堆栈通过减小存储器地址而向下增长,堆栈指针指向内含有效数据项的最低地址。

3)参数的传递规则整数参数的前4个使用r0~r3传递,其他参数使用堆栈传递;浮点参数使用编号最小且能够满足需要的一组连续的FP寄存器传递参数。

子程序的返回结果为一个32位整数时,通过r0返回;返回结果为一个64位整数时,通过r0和r1返回;依此类推。

结果为浮点数时,通过浮点运算部件的寄存器F0、D0或者S0返回。

2、汇编程序调用C程序的方法汇编程序的书写要遵循ATPCS规则,以保证程序调用时参数正确传递。

在汇编程序中调用C程序的方法为:首先在汇编程序中使用IMPORT伪指令事先声明将要调用的C语言函数;然后通过BL指令来调用C函数。

例如在一个C源文件中定义了如下求和函数:int add(int x,int y){return(x+y);}调用add()函数的汇编程序结构如下:IMPORT add ;声明要调用的C函数……MOV r0,1MOV r1,2BL add ;调用C函数add……当进行函数调用时,使用r0和r1实现参数传递,返回结果由r0带回。

函数调用结束后,r0的值变成3。

3、C程序调用汇编程序的方法C程序调用汇编程序时,汇编程序的书写也要遵循ATPCS规则,以保证程序调用时参数正确传递。

在C程序中调用汇编子程序的方法为:首先在汇编程序中使用EXPORT伪指令声明被调用的子程序,表示该子程序将在其他文件中被调用;然后在C程序中使用extern关键字声明要调用的汇编子程序为外部函数。

例如在一个汇编源文件中定义了如下求和函数:EXPORT add ;声明add子程序将被外部函数调用……add ;求和子程序addADD r0,r0,r1MOV pc,lr……在一个C程序的main()函数中对add汇编子程序进行了调用:extern int add (int x,int y); //声明add为外部函数void main(){int a=1,b=2,c;c=add(a,b); //调用add子程序……}当main()函数调用add汇编子程序时,变量a、b的值会给了r0和r1,返回结果由r0带回,并赋值给变量c。

相关文档
最新文档