Chinaunix首页 | 论坛 | 博客
  • 博客访问: 203960
  • 博文数量: 28
  • 博客积分: 2510
  • 博客等级: 少校
  • 技术积分: 315
  • 用 户 组: 普通用户
  • 注册时间: 2008-06-03 11:16
文章分类

全部博文(28)

文章存档

2008年(28)

我的朋友
最近访客

分类: LINUX

2008-08-03 18:45:33

参数传递规则
  1. 参数不超过4个时,可以使用寄存器R0R3来传递参数,当参数超过4个时,还可以使用数据栈来传递参数。
  2. 结果为一个32位整数时,可以通过寄存器R0返回
  3. 结果为一个64位整数时,可以通过寄存器R0R1返回,依次类推。
汇编程序、C程序及C++程序相互调用
C 程序调用汇编程序:
o      汇编程序的设置要遵循ATPCS 规则,保证程序调用时参数的正确传递。
o      在汇编程序中使用EXPORT 伪指令声明本子程序,使其它程序可以调用此子程序。
o      在C 语言程序中使用extern 关键字声明外部函数(声明要调用的汇编子程序),即可调用此汇编子程序。
o      调用汇编的C 函数:
o      示例
#include
extern void strcopy(char *d,const char *s) //声明外部函数,即要调用的汇编
                                                              //子程序
int main(void)
{
  const char *srcstr=“First string-source” //定义字符串常量
  char dstsrt[] =“Second string-destination”//定义字符串变量
  printf(“Before copying\n”);
  printf(“’%s’\n ‘%s\n,”srcstr,dststr); //显示源字符串和目标字符串的内容
  strcopy(dststr,srcstr); //调用汇编子程序,R0=dststr,R1=srcstr
  printf(“After copying\n”)
  printf(“’%s’\n ‘%s\n,”srcstr,dststr); //显示strcopy 复制字符串结果
  return(0);
}
o      被调用汇编子程序:
       AREA  SCopy,CODE,READONLY
       EXPORT strcopy  ;声明汇编程序strcopy,以便外部程序引用
strcopy              ;R0 为目标字符串的地址
                              ;R1 为源字符串的地址 ;
       LDRB R2,[R1],#1 ;读取字节数据,源地址加1
       STRB R2,[R0],#1 ;保存读取的1 字节数据,目标地址加1
       CMP r2,#0           ;判断字符串是否复制完毕
       BNE strcopy         ;没有复制完毕,继续循环
       MOV pc,lr             ;返回
       END
汇编程序调用C程序
o      汇编程序的设置要遵循ATPCS 规则,保证程序调用时参数的正确传递.
o      在汇编程序中使用IMPORT 伪指令声明将要调用的C 程序函数.
o      在调用C 程序时,要正确设置入口参数,然后使用BL 调用.
o      汇编调用C 程序的C 函数:
/*函数sum5()返回5 个整数的和*/
  int sum5(int a,lit b, int c,int d,int e)
{
  return(a+b+c+d+e); //返回5 个变量的和
}
o      汇编调用C 程序的汇编程序
       AREA  sample, CODE,READONLY
       IMPORT sum5      ;声明外部标号sum5,C 函数sum5()
CALLSUM
       STMFD SP!  {LR} ;LR 寄存器放栈
       ADD R1,R0,R0     ;设置sum5 函数入口参数,R0 为参数a
       ADD R2,R1,R0     ;R1 为参数b,R2 为参数c
       ADD R3,R1,R2,
       STR R3,[SP,# -4]!   ;参数e 要通过堆栈传递
       ADD R3,R1,R1        ;R3 为参数d
       BL sum5                ;调用sum5(),结果保存在R0
       ADD SP,SP#4         ;修正SP 指针
       LDMFD SP,PC          ;子程序返回
      
      END
嵌入式C编程
概述:
      C语言的优点是运行速度快、编译效率高、移
植性好和可读性强。C语言支持模块化程序设计,支持自顶
向下的结构化程序设计方法。因此在嵌入式程序设计中经
常会用到C语言程序设计。
      嵌入式C语言程序设计是利用基本的C语言知识,面向
嵌入式工程实际应用进行程序设计。也就是说它首先是C
言程序设计,因此必须符合C语言基本语法,只是它是面向
嵌入式的应用而设计的程序。
o      C语言的预处理伪指令在嵌入式程序设计中的应用。
1、文件包含伪指令
      格式:
#include <头文件名.h>      ;标准头文件
#include 头文件名.h”         ;自定义头文件
2、宏定义伪指令
      格式:
# define  宏标识符   宏体
       例:
n       #define  U32  unsigned  int
n       #define  U16  unsigned  short
n       #define  S32  int
n       #define  S16  short  int
n       #define  U8   unsigned  char
n       #define  S8   char
3、条件宏:先测试是否定义过某宏标识符,然后决定如何处理。这样做是为了避免重复定义。
格式:
       #ifdef         宏标识符
              #undef       宏标识符
              #define       宏标识符  宏体
       #else
              #define       宏标识符  宏体
       #endif
例:
       #ifdef  INCLUDE_SERIAL
              #undef  NUM_TTY
              #define NUM_TTY                         N_UART_CHANNELS
              #undef  CONSOLE_TTY
              #define CONSOLE_TTY                  0             
              #undef  CONSOLE_BAUD_RATE
              #define CONSOLE_BAUD_RATE     115200
       #endif
4、条件编译伪指令
格式
       #if(条件表达式1
       …
       #elif(条件表达式2
       …
       #elif(条件表达式n
       …
       #else
       …
       #endif
       这样,编译时,编译器仅对#if()…#endif之间满足某一条
件表达式的源文件部分进行编译。
使用寄存器变量
      当对一个变量频繁被读写时,需要反复访问内存,从而花费大量的存取时间。
为此,C语言提供了一种变量,即寄存器变量。这种变量存放在CPU的寄存器中,
使用时,不需要访问内存,而直接从寄存器中读写,从而提高效率。寄存器变量的
说明符是register。对于循环次数较多的循环控制变量及循环体内反复使用的变量
均可定义为寄存器变量,而循环计数是应用寄存器变量的最好候选者。
例:
       /* 1+2+3+….+n的值 */
WORD Addition(BYTE n)
{
 register is=0; for(i=1i<=n
i++)
 
{
  s=s+i
 
}
 return s
}
活用位操作 (熟练掌握)
      使用C语言的位操作可以减少除法和取模的运算。在计算机程序中数
据的位是可以操作的最小数据单位,理论上可以用位运算来完成所有的
运算和操作,因而,灵活的位操作可以有效地提高程序运行的效率
 
例:
     /* 方法1 */
int i,j;
i = 879 / 16;
j = 562 % 32;
     /* 方法2 */
int i,j;
i = 879 >> 4;
j = 562 - (562 >> 5 << 5);
int Ra ;//Ra[15:16]=11
Ra &= ~(3<<15);
C语言位运算除了可以提高运算效率外,在嵌入式
系统的编程中,它的另一个最典型的应用,而且十分广
泛地正在被使用着的是位间的(&)、(|)、非(~
操作,这跟嵌入式系统的编程特点有很大关系。
例:
     rGPCDAT=(rGPCDAT&0xFFFFFFF0)|0x0E
     rINTMSK&=~(BIT_TIMER1)
数据指针
     在嵌入式系统的编程中,常常要求在特定的内存单元读写内容,汇编有对应的
MOV指令,而除C/C++以外的其它编程语言基本没有直接访问绝对地址的能力。在
嵌入式系统的实际调试中,多借助C语言指针所具有的对绝对地址单元内容的读写能
力。以指针直接操作内存多发生在如下几种情况:
n       某I/O芯片被定位在CPU的存储空间而非I/O空间,而且寄存器对应于
某特定地址;
n       两个CPU之间以双端口RAM通信,CPU需要在双端口RAM的特定单
元(称为mail box)书写内容以在对方CPU产生中断;
n       读取在ROMFLASH的特定单元所烧录的汉字和英文字模。
例:
int *p = (int *)0xF000FF00
*p=0xABCD
#define rGPACON    (*(volatile unsigned *)0x56000000)
rGPACON0x1234
关键字volatile
        一般这个修饰符用来告知编译器,被修饰的变量是个易变的
(volatile的本意是易变的”),防止编译器进行优化。将变量加上
volatile修饰,则编译器保证对此变量的读写操作都不会被优化。
    用法
       1、中断服务程序中修改的供其它程序检测的变量需要加volatile
       2、多任务环境下各任务间共享的标志应该加volatile
       3、存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义。
阅读(1814) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~