arm中c嵌入汇编
- 格式:doc
- 大小:44.00 KB
- 文档页数:8
arm 空指令 c语言
在C语言中,空指令通常用于占位或者作为占位符使用。
在ARM架构中,空指令通常用于在程序中创建一个空操作,即不执行任何实际操作,只是为了占据一个指令的位置。
在C语言中,我们可以使用内联汇编来插入ARM空指令。
下面是一个简单的示例:
c.
void doNothing(void) {。
__asm__ volatile ("NOP");
}。
在这个示例中,`__asm__`关键字用于告诉编译器以下是内联汇编代码。
`volatile`关键字用于告诉编译器不要优化这段代码。
`NOP`是ARM汇编中的空指令,它告诉处理器不执行任何操作,只是简单地占据一个指令的位置。
空指令在C语言中的使用场景包括:
1. 调试,在调试过程中,我们可能需要在代码中插入一些空指令来暂停程序的执行,以便观察程序的状态。
2. 占位符,有时候我们可能需要在代码中占据一些位置,但又不需要执行任何实际操作,这时可以使用空指令作为占位符。
3. 对齐,在一些特定的内存对齐操作中,空指令也可以被使用来填充空间,以确保数据对齐到特定的边界。
需要注意的是,使用空指令应该谨慎,因为过多的空指令可能会导致代码可读性下降,同时也可能会影响程序的性能。
在实际开发中,应该根据具体情况慎重考虑是否使用空指令。
arm学习笔记五(cc++与arm汇编混合编程)混合编程常见⽅式:1 在c/c++程序中嵌⼊汇编指令语法格式:__asm{汇编语⾔程序}2 在汇编程序中访问c/c++定义的全局变量⽰例代码如下:test.c#include <stdio.h>int gVar_1=12;extern asmDouble(void)int main(void){printf("original value of gVar_1 is %d",gVar_1);admDouble();printf("modified value of gVar_1 is %d",gVar_1);return 0;}test.sAREA asmfile,CODE,READONLYEXPORT asmDouble;声明全局引⽤标号IMPORT gVar_1;引⽤asmDoubleldr r0,=gVar_1ldr r1,[r0]mov r2,#2mul r3,r1,r2str r3,[r0]mov pc,lrEND3 在c/c++程序中调⽤汇编函数⽰例代码如下:test1.sAREA asmfile,COCE,READONLYEXPORT asm_strcpy;声明全局引⽤标号asm_strcpy;函数名loop:ldrb r4,[r0],#1cmp r4,#0beq overstrb r4,[r1],#1b loopover:mov pc,lr;⽤于函数返回ENDtest1.c#include <stdio.h>extern void asm_strcpy(const char *src,char *dest);int main(){const char *s ="hello world";char d[32];asm_strcpy(s,d);printf("source:%s",s);printf("destination: %s",d);return 0;}上⾯程序jni的味道有⽊有?4 汇编程序中调⽤c/c++函数⽰例代码如下:test2.cint cFun(int a,int b,int c){return a+b+c;}test2.sEXPORT asmfileAREA asmfile,CODE,READONLY IMPORT cFun;引⽤函数ENTRY;指定应⽤程序⼊⼝mov r0,#11mov r1,#22mov r2,#33BL cFun;返回END。
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嵌入arm汇编指令嵌入 ARM 汇编指令到 C 代码中在进行嵌入式系统开发中,经常需要使用汇编指令来对特定的硬件进行操作。
而在 C 语言中,直接使用汇编指令是不被允许的,因此需要借助特定的语法和约定来嵌入 ARM 汇编指令到 C 代码中。
本文将介绍如何在 C 代码中嵌入 ARM 汇编指令,并提供一些常用的示例。
一、嵌入 ARM 汇编指令的语法在 C 代码中嵌入 ARM 汇编指令,可以使用 `asm` 关键字和特定的语法结构。
基本的语法格式如下所示:```casm("汇编指令");```其中,"汇编指令"表示要嵌入的 ARM 汇编指令,可以是单条指令或者多条指令的序列。
需要注意的是,汇编指令通常是以字符串的形式给出,因此需要使用双引号将其括起来。
二、嵌入 ARM 汇编指令的使用示例1. 嵌入汇编指令修改寄存器的值```cint main() {int a = 10;int b = 20;asm("ldr r0, %[value]" : : [value] "m" (b)); // 将 b 的值加载到寄存器 r0asm("str %[value], %[address]" : : [value] "r" (a), [address] "m" (&a)); // 将 a 的值存储到地址 &a 处return 0;}```在上述示例中,通过 `ldr` 指令将变量 b 的值加载到寄存器 r0 中,然后通过 `str` 指令将变量 a 的值存储到地址 &a 处。
2. 嵌入汇编指令实现延时功能```cvoid delay(int count) {asm("mov r1, %[value]" : : [value] "r" (count)); // 将参数 count 的值移动到寄存器 r1asm("loop: subs r1, r1, #1"); // 寄存器 r1 的值减 1asm("bne loop"); // 如果寄存器 r1 的值不等于零,则跳转到标签loop 处继续执行return;}```上述示例中定义了一个延时函数 delay,通过循环减少寄存器 r1 的值来实现延时功能。
__asm__ __volatile__内嵌汇编用法简述在阅读C/C++原码时经常会遇到内联汇编的情况,下面简要介绍下__asm__ __volatile__内嵌汇编用法。
带有C/C++表达式的内联汇编格式为:__asm__ __volatile__("Instruction List" : Output : Input : Clobber/Modify; 其中每项的概念及功能用法描述如下:1、 __asm____asm__是GCC 关键字asm 的宏定义:#define __asm__ asm__asm__或asm 用来声明一个内联汇编表达式,所以任何一个内联汇编表达式都是以它开头的,是必不可少的。
2、Instruction ListInstruction List 是汇编指令序列。
它可以是空的,比如:__asm____volatile__(""; 或 __asm__ ("";都是完全合法的内联汇编表达式,只不过这两条语句没有什么意义。
但并非所有Instruction List 为空的内联汇编表达式都是没有意义的,比如:__asm__("":::"memory";就非常有意义,它向GCC 声明:“内存作了改动”,GCC 在编译的时候,会将此因素考虑进去。
当在"Instruction List"中有多条指令的时候,可以在一对引号中列出全部指令,也可以将一条或几条指令放在一对引号中,所有指令放在多对引号中。
如果是前者,可以将每一条指令放在一行,如果要将多条指令放在一行,则必须用分号(;)或换行符(\n)将它们分开. 综上述:(1)每条指令都必须被双引号括起来 (2两条指令必须用换行或分号分开。
例如:在ARM 系统结构上关闭中断的操作int disable_interrupts (void{unsigned long old,temp;__asm__ __volatile__("mrs %0, cpsr\n""orr %1, %0, #0x80\n""msr cpsr_c, %1": "=r" (old, "=r" (temp:: "memory";return (old & 0x80 == 0;}3. __volatile____volatile__是GCC 关键字volatile 的宏定义#define __volatile__ volatile__volatile__或volatile 是可选的。
一、实验室名称:科A 209二、实验项目名称:ARM汇编基础实验三、实验原理:1、ARM中的C和汇编混合编程在嵌入式系统开发中,目前使用的主要编程语言是C和汇编。
在稍大规模的嵌入式软件中,例如操作系统,大部分的代码都是用C编写的,主要是因为C语言的结构比较好,便于人的理解,而且有大量的支持库。
尽管如此,很多地方还是要用到汇编语言,例如开机时硬件系统的初始化,包括CPU 状态的设定,中断的使能,主频的设定,以及RAM的控制参数及初始化,一些中断处理方面也可能涉及汇编。
另外一个使用汇编的地方就是一些对性能非常敏感的代码块,这是不能依靠C编译器生成代码,而要手工编写汇编,达到优化的目的。
而且,汇编语言是和CPU指令集紧密相连的,作为涉及底层的嵌入式系统开发,熟练对应汇编语言的使用也是必须的。
单纯的C或者汇编编程请参考相关的书籍或者手册,这里主要讨论C和汇编的混合编程,包括相互之间的函数调用。
下面分四种情况来进行讨论。
1) 在C语言中内嵌汇编在C中内嵌的汇编指令包含大部分的ARM和Thumb指令,不过其使用与汇编文件中的指令有些不同,存在一些限制,主要有下面几个方面:(a)不能直接向PC寄存器负责,程序跳转要使用用B或者BL指令(b)在使用物理寄存器时,不要使用过于复杂的C表达式,避免物理寄存器冲突(c)R12和R13可能被编译器用来存放中间编译结果,计算表达式值时可能将R0到R3、R12及R14用于子程序调用,因此要避免直接使用这些物理寄存器(d)一般不要直接指定物理寄存器,而让编译器进行分配。
内嵌汇编使用的标记是__asm或者asm关键字,用法如下:__asm{instruction [; instruction]…[instruction]}asm(“instruction [; instruction]”);下面通过一个例子来说明如何在C中内嵌汇编语言,#include <stdio.h>void my_strcpy(const char *src, char *dest){char ch;__asm{loop:ldrb ch, [src], #1strb ch, [dest], #1cmp ch, #0bne loop}}int main(){char *a = "forget it and move on!";char b[64];my_strcpy(a, b);printf("original: %s", a);printf("copyed: %s", b);return 0;}在这里C和汇编之间的值传递是用C的指针来实现的,因为指针对应的是地址,所以汇编中也可以访问。
A R M G C C内嵌汇编手册 Document serial number【NL89WT-NY98YT-NC8CB-NNUUT-NUT108】转自:ARM GCC 内嵌(inline)汇编手册关于这篇文档这篇文章是本人为方便各位业界同仁而翻译,方便大家开发底层代码使用,转载请注明出处,谢谢。
要是你E文功底好,本人还是建议阅读E文版的。
对于基于ARM的RISC处理器,GNU C编译器提供了在C代码中内嵌汇编的功能。
这种非常酷的特性提供了C代码没有的功能,比如手动优化软件关键部分的代码、使用相关的处理器指令。
这里设想了读者是熟练编写ARM汇编程序读者,因为该片文档不是ARM汇编手册。
同样也不是C语言手册。
这篇文档假设使用的是GCC 4 的版本,但是对于早期的版本也有效。
GCC asm 声明让我们以一个简单的例子开始。
就像C中的声明一样,下面的声明代码可能出现在你的代码中。
/* NOP 例子 */asm("mov r0,r0");该语句的作用是将r0移动到r0中。
换句话讲他并不干任何事。
典型的就是NOP 指令,作用就是短时的延时。
请接着阅读和学习这篇文档,因为该声明并不像你想象的和其他的C语句一样。
内嵌汇编使用汇编指令就像在纯汇编程序中使用的方法一样。
可以在一个asm声明中写多个汇编指令。
但是为了增加程序的可读性,最好将每一个汇编指令单独放一行。
asm("mov r0, r0\n\t""mov r0, r0\n\t""mov r0, r0\n\t""mov r0, r0");换行符和制表符的使用可以使得指令列表看起来变得美观。
你第一次看起来可能有点怪异,但是当C编译器编译C语句的是候,它就是按照上面(换行和制表)生成汇编的。
到目前为止,汇编指令和你写的纯汇编程序中的代码没什么区别。
但是对比其它的C声明,asm的常量和寄存器的处理是不一样的。
arm c与汇编相互传递参数的方法在ARM C和汇编语言编程中,传递参数是非常常见且重要的操作。
参数可以是函数调用时传递给函数的值,也可以是函数返回时传递给调用者的结果。
在下面的讨论中,我将回答如何在ARM C和汇编语言之间相互传递参数的方法。
在ARM汇编语言中,传递参数通过寄存器完成。
ARM体系结构有一组专门用于传递参数的寄存器,通常被称为r0到r3寄存器。
将参数存储在这些寄存器中,然后在函数调用或返回过程中使用它们。
在ARM C中,传递参数有两种方式,一种是使用寄存器传递,另一种是使用堆栈传递。
默认情况下,前四个参数会依次存储在r0、r1、r2和r3寄存器中。
如果参数超过四个,ARM C会使用堆栈来传递额外的参数。
例如,假设我们有一个C函数和一个相应的汇编函数,我们需要在它们之间传递参数。
C函数如下:```cint add_numbers(int a, int b);```对应的汇编函数如下:```armasm.global add_numbers_asmadd_numbers_asm:// 从r0和r1寄存器中读取参数ldr r2, [sp, #0] // 将第一个参数a加载到r2寄存器ldr r3, [sp, #4] // 将第二个参数b加载到r3寄存器// 执行计算add r0, r2, r3 // 将a和b相加并将结果存储在r0寄存器中// 返回结果bx lr // 返回调用者```在这个例子中,C函数`add_numbers`接收两个整数参数a和b,并计算它们的和。
相应的汇编函数`add_numbers_asm`通过将参数从堆栈中加载到寄存器中进行计算,并将结果存储在r0寄存器中。
最后使用`bx lr`指令返回到调用者。
以上是在ARM C和汇编语言之间相互传递参数的一种常见方法。
通过正确理解寄存器的用法和在堆栈中读取参数的方法,可以在ARM体系结构中有效地传递参数。
arm汇编基础这⾥需要提到的是ARM处理器的汇编语⾔编程的⼀些内容,在嵌⼊式ARM系统的程序设计中往往离不开ARM汇编语⾔编程。
正如⼤家所熟知的处理器初始化部分的代码通常都是⽤汇编来编写的,还有⼀些操作协处理器的代码,以及部分中断处理程序⼀样也是⽤汇编语⾔写成的。
在开始介绍ARM处理器汇编语⾔编程之前建议读者先阅读⼀些有关ARM指令集的资料,主要是指ARM指令集、Thumb指令集及ARM宏汇编部分。
有关ARM指令集和Thumb指令集这⾥就不做具体介绍,只从ARM汇编伪指令、模块化汇编语⾔程序设计、混合语⾔编程等⼏个⽅⾯对ARM处理器汇编语⾔做⼀些简单介绍。
ARM汇编伪指令介绍在ARM处理器汇编语⾔程序设计⾥,有⼀些特殊的指令助记符。
这些助记符与指令系统的助记符不同,没有相对应的操作码,通常称这些特殊的指令助记符为伪指令,它们所完成的操作称为伪操作。
伪指令在源程序中的作⽤是为完成汇编程序做各种准备⼯作的,这些伪指令仅在汇编过程中起作⽤,⼀旦汇编结束,伪指令的使命就完成了。
在ARM处理器的汇编程序中,⼤体有如下⼏种伪指令:符号定义伪指令、数据定义伪指令、汇编控制伪指令、宏指令及其他伪指令。
伪操作符可以分为以下⼏类。
1)数据定义伪操作符数据定义伪操作符主要包括LTORG、MAP、DCB、FIELD、SPACE、DCQ、DCW等,主要⽤于数据表定义、⽂字池定义、数据空间分配等。
常⽤的有DCB/DCQ/DCW分配⼀段字节/双字/字内存单元,并且将它们初始化。
2)符号定义伪操作符符号定义伪操作符包括GBLA、GBLL、GBLS、LCLA、CN、CP、DN、FN、RLIST、SETA等,⽤于定义ARM汇编程序的变量,对变量进⾏赋值,以及定义寄存器名称等。
其中⽤于全局变量声明的GBLA、GBLL、GBLS和局部变量声明的LCAL、LCLL、LCLS伪指令较为常⽤。
3)报告伪操作符报告伪操作符包括ASSERT、INFO、OPT等,主要⽤于汇编报告等。
C代码中嵌⼊汇编(ARM)C 代码中嵌⼊汇编⽽ C 中嵌⼊汇编代码由 gcc 编译器实现的,实现也⾮常简单,使⽤由编译器提供的 asm 或者 __asm__ 关键字即可,这两者没有任何区别,然后将需要执⾏的汇编指令使⽤("")包含起来即可,对应的汇编指令就会被执⾏。
我们来看看下⾯的嵌⼊汇编代码:void func(void){...asm("mov r1,r0");__asm__("mov r2,r1");...}代码⾮常简单,将寄存器 r0 的值赋值给 r1,然后赋值给 r2。
这是最简单的汇编指令,但是,通常情况下,这样的汇编代码没有产⽣输⼊输出的⾏为,也就对函数的执⾏不能做出正向的贡献。
事实上,在⼦程序的调⽤时,这种代码可能是有⽤的,因为在 arm 中 r0~r3 被⽤来传递参数和返回值。
之所以说正向的贡献是因为这种操作可能产⽣负⾯的影响,因为 r0~r2 寄存器很可能正在被程序的其它部分使⽤⽽在这⾥被意外地修改。
⽽更多地情况是,C 函数中调⽤汇编函数,是需要汇编指令进⾏⼀些特定的操作,然后在 C 函数中使⽤相应的操作结果,实现 C 和嵌⼊汇编代码的"交互",这就需要使⽤到嵌⼊汇编的另⼀种表达形式:asm(code : output operand list : input operand list : clobber list);这种嵌⼊汇编的形式⼀共分为四个部分:code[attr]output operand list[attr]input operand listclobber listoutput operand list:表⽰输出的操作数,通常是⼀个或者多个 C 函数中的变量。
input operand list:表⽰输⼊的操作数,通常是⼀个或者多个 C 函数中的变量,attr 部分表⽰操作数的属性,以字符串的形式提供,是必须的参数。
armcacheline,PLD指令C中嵌⼊汇编PLD指令:asm("PLD [%0,#128]": :"r" (psrc) );copy⾃官⽅⽂档:4.2.7. PLD、PLDW 和 PLI预载数据和预载指令。
处理器可向内存系统发送信号,告诉内存系统在不久的将来可能要从某个地址加载数据或指令。
语法PL type{cond} [Rn {, #offset}]PL type{cond} [Rn, +/-Rm {, shift}]PL type{cond} label其中:type可以是下列项之⼀:D数据地址DW要写⼊的数据地址I指令地址如果语法指定了label,则type不能为DW。
cond是⼀个可选的条件代码(请参阅)。
Notecond只能⽤在 Thumb-2 代码中,且前⾯要有IT指令。
这是 ARM 中的⽆条件执⾏指令,请⼀定不要使⽤cond。
Rn是内存地址所基于的寄存器。
offset是直接偏移量。
如果省略偏移量,则该地址为Rn中的值。
Rm是⼀个寄存器,包含要⽤作偏移量的值。
Rm不能为 r15。
对于 Thumb 指令, Rm还不能为 r13。
shift是⼀个可选的移位。
label是⼀个程序相对的表达式。
有关详细信息,请参阅。
偏移量范围预载前,会先将偏移量应⽤到Rn中的值。
所得结果将⽤作预载的内存地址。
偏移量的允许范围为:–4095 到 +4095(ARM 指令)–255 到 +4095(适⽤于Rn不是 r15 时的 Thumb-2 指令)。
–4095 到 +4095(适⽤于Rn为 r15 时的 Thumb-2 指令)。
汇编器会计算相对 PC 的偏移量。
如果label超出范围,则汇编器会⽣成错误。
寄存器或寄存器移位偏移量在 ARM 中,Rm中的值既可与Rn中的值相加,也可从其中减去。
在 Thumb-2 中,Rm中的值只能与Rn中的值相加。
所得结果将⽤作预载的内存地址。
ARM中C和汇编混合编程及示例
原文链接:/article/detail.asp?id=4145
在嵌入式系统开发中,目前使用的主要编程语言是C和汇编,C++已经有相应的编译器,但是现在使用还是比较少的。
在稍大规模的嵌入式软件中,例如含有OS,大部分的代码都是用C编写的,主要是因为C语言的结构比较好,便于人的理解,而且有大量的支持库。
尽管如此,很多地方还是要用到汇编语言,例如开机时硬件系统的初始化,包括CPU状态的设定,中断的使能,主频的设定,以及RAM的控制参数及初始化,一些中断处理方面也可能涉及汇编。
另外一个使用汇编的地方就是一些对性能非常敏感的代码块,这是不能依靠C 编译器的生成代码,而要手工编写汇编,达到优化的目的。
而且,汇编语言是和CPU的指令集紧密相连的,作为涉及底层的嵌入式系统开发,熟练对应汇编语言的使用也是必须的。
单纯的C或者汇编编程请参考相关的书籍或者手册,这里主要讨论C和汇编的混合编程,包括相互之间的函数调用。
下面分四种情况来进行讨论,暂不涉及C++。
1.在C语言中内嵌汇编
在C中内嵌的汇编指令包含大部分的ARM和Thumb指令,不过其使用与汇编文件中的指令有些不同,存在一些限制,主要有下面几个方面:
a. 不能直接向PC寄存器赋值,程序跳转要使用B或者BL指令
b. 在使用物理寄存器时,不要使用过于复杂的C表达式,避免物理寄存器冲突
c. R12和R13可能被编译器用来存放中间编译结果,计算表达式值时可能将R0到R3、R12及R14用于子程序调用,因此要避免直接使用这些物理寄存器
d. 一般不要直接指定物理寄存器,而让编译器进行分配
内嵌汇编使用的标记是__asm或者asm关键字,用法如下:
__asm
{
instruction [; instruction]
…
[instruction]
}
asm(“instruction [; instruction]”);
下面通过一个例子来说明如何在C中内嵌汇编语言,
#include <stdio.h>
void my_strcpy(const char *src, char *dest) {
char ch;
__asm
{
loop:
ldrb ch, [src], #1
strb ch, [dest], #1
cmp ch, #0
bne loop
}
}
int main()
{
char *a = "forget it and move on!";
char b[64];
my_strcpy(a, b);
printf("original: %s", a);
printf("copyed: %s", b);
return 0;
}
在这里C和汇编之间的值传递是用C的指针来实现的,因为指针对应的是地址,所以汇编中也可以访问。
2.在汇编中使用C定义的全局变量
内嵌汇编不用单独编辑汇编语言文件,比较简洁,但是有诸多限制,当汇编的代码较多时一般放在单独的汇编文件中。
这时就需要在汇编和C之间进行一些数据的传递,最简便的办法就是使用全局变量。
/* cfile.c
* 定义全局变量,并作为主调程序
*/
#include <stdio.h>
int gVar_1 = 12;
extern asmDouble(void);
int main()
{
printf("original value of gVar_1 is: %d", gVar_1);
asmDouble();
printf(" modified value of gV ar_1 is: %d", gVar_1);
return 0;
}
对应的汇编语言文件
;called by main(in C),to double an integer, a global var defined in C is used. AREA asmfile, CODE, READONL Y
EXPORT asmDouble
IMPORT gVar_1
asmDouble
ldr r0, =gVar_1
ldr r1, [r0]
mov r2, #2
mul r3, r1, r2
str r3, [r0]
mov pc, lr
END
3.在C中调用汇编的函数
在C中调用汇编文件中的函数,要做的主要工作有两个,一是在C中声明函数原型,并加extern关键字;二是在汇编中用EXPORT导出函数名,并用该函数名作为汇编代码段的标识,最后用mov pc, lr返回。
然后,就可以在C中使用该函数了。
从C的角度,并不知道该函数的实现是用C还是汇编。
更深的原因是因为C的函数名起到表明函数代码起始地址的左右,这个和汇编的label是一致的。
/* cfile.c
* in C,call an asm function, asm_strcpy
* Sep 9, 2004
*/
#include <stdio.h>
extern void asm_strcpy(const char *src, char *dest);
int main()
{
const char *s = "seasons in the sun";
char d[32];
asm_strcpy(s, d);
printf("source: %s", s);
printf(" destination: %s",d);
return 0;
}
;asm function implementation
AREA asmfile, CODE, READONL Y
EXPORT asm_strcpy
asm_strcpy
loop
ldrb r4, [r0], #1 ;address increment after read
cmp r4, #0
beq over
strb r4, [r1], #1
b loop
over
mov pc, lr
END
在这里,C和汇编之间的参数传递是通过A TPCS(ARM Thumb Procedure Call Standard)的规定来进行的。
简单的说就是如果函数有不多于四个参数,对应的用R0-R3来进行传递,多于4个时借助栈,函数的返回值通过R0来返回。
4.在汇编中调用C的函数
在汇编中调用C的函数,需要在汇编中IMPORT 对应的C函数名,然后将C的代码放在一个独立的C文件中进行编译,剩下的工作由连接器来处理。
;the details of parameters transfer comes from ATPCS
;if there are more than 4 args, stack will be used
EXPORT asmfile
AREA asmfile, CODE, READONL Y IMPORT cFun
ENTRY
mov r0, #11
mov r1, #22
mov r2, #33
BL cFun
END
/*C file, called by asmfile */
int cFun(int a, int b, int c)
{
return a + b + c;
}
在汇编中调用C的函数,参数的传递也是通过A TPCS来实现的。
需要指出的是当函数的参数个数大于4时,要借助stack,具体见ATPCS规范。
小结
以上通过几个简单的例子演示了嵌入式开发中常用的C和汇编混合编程的一些方法和基本的思路,其实最核心的问题就是如何在C和汇编之间传值,剩下的问题就是各自用自己的方式来进行处理。
以上只是抛砖引玉,更详细和复杂的使用方法要结合实际应用并参考相关的资料。
说明
以上代码在ADS 1.2的工程中编译,并在对应的AXD中软件仿真通过。
参考资料
1.杜春雷,ARM体系结构与编程,清华大学出版社,2003
2.UC/OS-II for ARM移植的相关启动代码
原文链接:/article/detail.asp?id=4145。