2008年11月22日

Blackfin汇编语言之程序调用接口

ABI(Application Binary Interface)定义了应用程序和操作系统之间或函数之间在堆栈使用、参数传递以及寄存器使用上的规则,只有大家都遵守这个规则,不同的代码才可以无差错的链接到一起完成某项任务。
1。数据存储格式
BF532使用的是小端字节序。所以数据在寄存器和内存中的存储形式是:
2。寄存器使用约定
  • 专用寄存器
P6 -- SP Stack Pointer register
P7 -- FP Frame Pointer register
这两个寄存器都是固定给编译器使用的,要求4-bytes字节对齐,且必须位于适当的堆栈内存区域内

L0-L3 -- 循环长度寄存器,要求假定L0-L3寄存器的值为0,也就是说在调用函数和退出函数之前要将寄存器归零
  • 函数调用需维护的寄存器
下面这几个寄存器如果函数中需要使用到则需要在使用之前保存寄存器值,并且在函数退出之前恢复寄存器原值。
P3--P5
R4--R7
  • 函数中可以任意使用的寄存器
  1. P0 用作返回地址寄存器
  2. P1–P2
  3. R0 - R3 R0,R1,R2用作函数参数传递寄存器,R3不用作参数传递
  4. LB0–LB1
  5. LC0–LC1
  6. LT0–LT1
  7. ASTAT (Including CC)
  8. A0–A1
  9. I0–I3
  10. B0–B3
  11. M0–M3
调用函数执行顺序:
  • 栈帧指针设置。在栈保存返回地址和调用函数的FP寄存器值。设置FP寄存器值为被调用函数的栈帧地址。SP指针地址递减从而分配本地变量和编译器使用临时的内存空间。
  • 保存函数调用约定需要维护的寄存器的值;SP寄存器指向栈帧的顶部。
退出函数执行顺序:
  • 恢复函数调用约定需要维护的寄存器的值;SP寄存器指向栈帧的顶部。
  • 栈帧指针回退。FP回复为调用函数的栈帧地址;RETS设置为返回地址;SP设置为调用函数栈帧的顶部地址。
例如:
进入被调用函数:
  LINK       16;
[--SP]=(R7:4);
SP + = –16;
[FP+8]=R0; [FP+12]=R1; [FP+16]=R2;
  • LINK 16;是一条特殊的链接指令,它保存返回地址和栈帧指针FP,并在堆栈SP上分配16bytes空间给本地变量使用
  • [--SP]=(R7:4); 分配空间并保存寄存器的值
  • SP += -16; 分配空间给传出参数使用,至少为12bytes。
  • [FP+8]=R0; [FP+12]=R1; [FP+16]=R2; 保存函数参数值
退出被调用函数:
   SP + = 16;
P0=[FP+4];
(R7:4)=[SP++];
UNLINK;
JUMP (P0);
  • SP += 16;恢复SP指针
  • P0=[FP+4]; 将返回地址设置到P0寄存器
  • (R7:4)=[SP++]; 恢复保存寄存器的值
  • UNLINK; 特殊指令,恢复SP和FP指针
  • JUMP (P0); 返回函数调用之处继续执行

LINK 这条指令做了如下工作:
[--SP] = RETS;
[--SP] = FP;
FP = SP;
SP += -n;
也就是说,在每个函数的开头,首先都保存了本函数的返回地址,同时还保存了上一个调用函数的FP指针。实际上就相当于把函数的返回地址用一个单链表链接起来,只要顺着这个链表往上找,自然就可以找出调用函数的返回地址了。

没有评论: