Chinaunix首页 | 论坛 | 博客
  • 博客访问: 78813
  • 博文数量: 20
  • 博客积分: 1481
  • 博客等级: 上尉
  • 技术积分: 452
  • 用 户 组: 普通用户
  • 注册时间: 2010-09-11 11:01
文章存档

2011年(2)

2010年(18)

我的朋友

分类: LINUX

2010-12-21 22:58:43

首先介绍下堆栈使用的基础知识。
一般ARM栈分配在高地址,然后往低地址方向增长。函数调用的过程一般使用A0-A3作为保护现场,如果参数太多,则要用到堆栈来存储参数,入栈的顺序则和编译器有关系。。。

过程调用标准
1.寄存器使用规则
       R0-R3 调用后无需恢复之前的内容
       R4-R11保存局部变量的值
       R12 临时栈指针,记作IP,
       R13 数据栈指针,记作SP。
       R14 链接寄存器,保存子程序的返回地址
       R15 程序计数器


2. 数据栈的使用规则
    一般采用FD,满递减的方式
3. 参数传递规则
    参数少于4个用R0-R3。参数多于4个采用数据栈。最后一个参数先入栈。

下面看一个VC++6.0中压栈顺序的约定,主要通过关键字__cdecl __stdcall __fastcall thiscall来实现.
关键字             堆栈清除                   入栈数序
__cdecl           调用者                     从右到左
__stdcall         函数自身                   从右到左
__fastcall        函数自身                   从右到左 优先使用ECX,EDX
thiscall          函数自身                   从右到左 优先使用ECX传递this指针。

所以用__cdecl声明的函数可以实现可变参数的功能。

可变参数的使用
typedef char *va_list;

#define  _AUPBND        (sizeof (acpi_native_int) - 1)
#define  _ADNBND        (sizeof (acpi_native_int) - 1)
                        
#define _bnd(X, bnd)    (((sizeof (X)) + (bnd)) & (~(bnd)))
#define va_arg(ap, T)   (*(T *)(((ap) += (_bnd (T, _AUPBND))) - (_bnd (T,_ADNBND))))
#define va_end(ap)      (void) 0
#define va_start(ap, A) (void) ((ap) = (((char *) &(A)) + (_bnd (A,_AUPBND))))

va_list   arg_ptr;   //参数列表的指针
va_start(arg_ptr,   i);    //参数列表指针指向第一个参数
s=va_arg(arg_ptr,char*); //取一个char*的参数出来
   
va_end(arg_ptr);  //释放参数列表指针。


static char sprint_buf[1024];
int printf(char *fmt, ...)
{
	va_list args;
	int n;
	va_start(args, fmt);
	n = vsprintf(sprint_buf, fmt, args);
	va_end(args);
	write(stdout, sprint_buf, n);
	return n;
}

阅读(2361) | 评论(0) | 转发(1) |
1

上一篇:中断控制器

下一篇:Linux进程学习笔记

给主人留下些什么吧!~~