您的位置:

c语言中的arm,C语言中的实参和形参

本文目录一览:

arm 如何调用子程序,就是用c语言写的,好像有许多格式控制,不是很明白,请指教

用C语言写的ARM程序调用C函数和普通的C语言格式一样,没有特殊的地方;

如果用C语言调用ARM的汇编,则有规则。

在C程序和ARM汇编程序之间相互调用时必须遵守ATPCS(ARM-THUMB procedure call standard )规则。ATPCS规定了一些子程序间调用的基本规则,比如:

寄存器的使用规则

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

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

寄存器r12用于保存堆栈指针SP,当子程序返回时使用该寄存器出栈,记作IP。寄存器r13用作堆栈指针,记作SP。寄存器r14称为链接寄存器,记作LR。该寄存器用于保存子程序的返回地址。寄存器r15称为程序计数器,记作PC。  

堆栈的使用规则

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

参数的传递规则

整数参数的前4个使用r0~r3传递,其他参数使用堆栈传递;

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

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

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

arm的c语言中是什么意思

C 语言是一样的。 两者不一样的地方,不是 C 语言,而是硬件不同。 硬件不同,定义的变量,

如何用C语言定义arm状态下的r13寄存器为堆栈指针

1,你如果用C语言编程的话,堆栈跟你见不着面,编译器会处理,何来定义堆栈之说?

2,你如果是用汇编和C混合编程的话你就只能用约定俗成的SP寄存器,

3,如果只用ARM汇编的话,在汇编代码里你可以随便用任何寄存器来充当堆栈的角色,无非就是在程序初始化时将哪个寄存器赋一个地址,然后你把这个寄存器当作栈指针寄存器,进行压栈和出栈操作时来改变或恢复这个寄存器的值,这样一来就完成了在汇编代码里的操作堆栈的功能。但是在汇编代码里最重要的是要能做到恢复现场,有一个寄存器没恢复的话整个程序就会出错,还有你不用SP的话就不能用PUSH和POP指令,直接操作你要拿来当堆栈指针的寄存器就OK。

4,对于堆栈的理解问题,堆栈是一种抽象数据容器,即包括操作的数据结构,相当于C++中的类的概念,但还是有区别,无非就是划定一块内存区,定义任何数据想要在这块内存区存取都要遵守先进后出的规则,而INTEL和ARM的CPU架构里都有一个物理寄存器SP用来充当指向堆栈(你划定的那块内存区)的栈顶指针,在C语言里要实现堆栈这样的数据类型,就要用你定义的变量来充当栈顶指针,但在汇编里,就是SP了。

为了这个5分,我可没少写呀。

关于C语言中用#define和sfr定义ARM寄存器的问题

我给你解释几点:1:0X56000010 这个值是GPBCON这个寄存器在ARM地址空间的物理地址,(unsigned long *)0x56000010 是将这个地址强制转换成unsigned long *类型的指针,再在这个指针前加*号是解引用,取这个地址里的值,这完全符合C的语法,其中加的那个volatile关键字是防止C编译器对这个地址的优化,每一次对该地址的的取值必须访问到总线上去,而不能在缓冲或寄存器里取值。 2,sfr只是在嵌入式里边对特殊功能寄存器的英文简称,没有任何其它的意义,甚至你完全可以在你的人生中彻底忘掉这个sfr,但在嵌入式处理器里本来就有两类所型的寄存器,通用寄存器和特殊功能寄存器,这是基于8位单片机的知识回答这样的,在ARM里,R1-R15我们可能叫通用寄存器,指令执行需要用到这些寄存器,而其它分布在总线地址上的几百个甚至上千个寄存器我们可能叫他特殊功能寄存器(sfr),但没有人这么叫,一般都是一些控制器的配置寄存器,地址寄存器,数据寄存器等,不要和通用寄存器混淆,通 用寄存器没地址,直接用R1-R15这样的名字进行访问,而其它所有寄存器都要通过地址来访问,所以就有了上述的#define GPBCON 这个宏定义。

3,C语言中用register声明的变量叫做寄存器变量,即该变量没有放在内存上,而是放在R1-R10中的一个通用寄存器里,CPU对该变量的操作就变成了对CPU内部寄存器的操作,不访问总线,这样就提高了访问速度,实际上C编译器大部分情况下也不一定就把register 显示声明的变量放到寄存器上去,编译器是根据CPU的架构,通过一个最优的算法将选择适合的变量当作寄存器变量,所以加这个register实际上没有作用,所以基于编译器的这个特点,volatile这个关键字就变得有必要了,因为有些东西是绝对不能当做寄存器变量来访问的,例如硬件状态寄存器里的值是根据硬件的状态来更新的,所以就一定要访问到挂在总线上的这个相应的地址上来读取这个值。

关于ARM寄存器在C语言中宏定义的问题

PORTA应该要定义的吧,可能以前你只看c文件,头文件没注意吧。嵌入式系统编程,要求程序员能够利用C语言访问固定的内存地址。不进行宏定义的话就得每次用的时候用地址了,那多麻烦。关于这个定义,可以看下面讲解。。

既然是个地址,那么按照C语言的语法规则,这个表示地址的量应该是指针类型。所以,知道要访问的内存地址后,比如0x5F,

第一步是要把它强制转换为指针类型

(unsigned char *)0x5F,AVR的SREG是八位寄存器,所以0x5F强制转换为指向

unsigned char类型。

volatile(可变的)这个关键字说明这变量可能会被意想不到地改变,这样编译器就不会去假设这个变量的值了。这种“意想不到地改变”,不是由程序去改变,而是由硬件去改变——意想不到。

第二步,对指针变量解引用,就能操作指针所指向的地址的内容了

*(volatile unsigned char *)0x5F

第三步,小心地把#define宏中的参数用括号括起来,这是一个很好的习惯,所以#define SREG (*(volatile unsigned char *)0x5F)

类似的,如果使用一个32位处理器,要对一个32位的内存地址进行访问,可以这样定义#define RAM_ADDR (*(volatile unsigned long *)0x0000555F)

然后就可以用C语言对这个内存地址进行读写操作了

读:tmp = RAM_ADDR;

写:RAM_ADDR = 0x55;

#define U0RBR (*((volatile unsigned char *) 0xE000C000))

这个在单片机里很常见,

((volatile unsigned char *) 0xE000C000) 是将0xE000C000强制转换为

保存可能随时更新(volatile的作用)无符号字符型数据的地址

前面又加了*,是表示指向这个地址里面的值,这与其他普通定义的指针一样了,如char x,y,*p;p=x;*p=y;y=*p

就如同一个变量一样,既可以从这里读出值,也可以给被赋值,这里需要注意的是,这个地址值里的东西是不是既可以读又可以写,这个在datasheet应该有定义,或者看程序中都拿他干什么。

#define U0RBR (*((volatile unsigned char *) 0xE000C000)) 这个是宏定义,即UORBR替换(*((volatile unsigned char *) 0xE000C000)),宏定义是为了程序书写方便,因为在程序中可能有好多地方要使用(*((volatile unsigned char *) 0xE000C000)),在用时,总要写这么多东西麻烦。

arm编程与C语言的编程区别和方法

arm是一个处理器,而不是一种编程语言。。

对于arm的编程可以使用c语言或者汇编。。

arm和c没有要比的吧