堆栈操作
ARM体系结构使用多寄存器的load-store指令来完成堆栈操作。Pop操作(出栈)使用一条多寄存器的load指令,push操作(入栈)使用一条多寄存器的store指令。
在使用一个堆栈的时候,需要确定堆栈在存储器空间中是向上生长还是向下生长的。一个堆栈或者是递增的(ascending, “A”)-向上(高地址空间)生长,或者是递减的(descending,“D”)-向下(低地址空间)生长。
满堆栈(full stack,“F”)是指堆栈指针sp指向堆栈的最后一个已使用的地址或满位置(也就是sp指向堆栈的最后一个数据项位置);相反,空堆栈(empty stack,“E”)是指sp指向堆栈的第一个没有使用的地址或空位置(也就是sp指向堆栈的最后一个数据项的下一个位置)。
有一些多寄存器load-store指令的别名支持堆栈操作(见下表)。在pop的右边下一列,是与之实际等价的load指令。
堆栈操作寻址方式
寻址方式 |
说明 |
pop |
=LDM |
push |
=STM |
FA |
递增满 |
LDMFA |
LDMDA |
STMFA |
STMIB |
FD |
递减满 |
LDMFD |
LDMIA |
STMFD |
STMDB |
EA |
递增空 |
LDMEA |
LDMDB |
STMEA |
STMIA |
ED |
递减空 |
LDMED |
LDMIB |
STMED |
STMDA |
ARM制定了ARM-Thumb过程调用标准(ATPCS),定义了例程如何被调用,寄存器如何被分配。在ATPCS中,堆栈被定义为递减式满堆栈,因此LDMFD和STMFD指令分别用来支持pop和push功能。
若要检查一个堆栈,须关注堆栈的3个属性:堆栈基址、堆栈指针及堆栈限制。堆栈基址是堆栈在存储器中的起始地址;堆栈指针初始时指向堆栈基址单元,随着数据压栈,堆栈指针连续移动并始终指向栈顶;如果堆栈指针超出了堆栈限制,就会发生堆栈溢出错误。下面的一小段代码用于检测递减式堆栈的溢出错误:
SUB sp, sp, #size
CMP sp, r10
BLL0 _stack_overflow; 条件
ATPCS把寄存器r10定义为堆栈限制或sl(stack limit)。这是一个可选的操作,因为堆栈检查只有在堆栈检查使能的时候才可使用。BLL0指令是一个加了条件助记符L0的带链接的分支指令。如果在执行一个push操作后,sp小于r10,就发生了堆栈溢出错误。如果堆栈指针在执行pop操作后,超出了堆栈基址,那么就产生了堆栈下溢(stack underflow)错误。
发表评论 评论 (0 个评论)