本帖最后由 吾要单片机 于 2018-5-15 21:47 编辑
七、 独特的栈段结构
栈段是用于保存寄存器数据和子程序自动变量数据的内存空间。当前主流CPU的栈段结构如图1所示,从图1中可看出在栈段(STACK)内,寄存器数据区和子程序自动变量数据区是混合在一起,并且寄存器数据区栈指针(SP)和子程序自动变量数据区栈帧指针(FP)都是从高地址向低地址方向增长,在此本人将这种栈段结构称为单向栈段结构。本酷能指令集架构所使用的栈段结构有别于当前主流CPU的栈段结构,其栈段结构如图2所示。从图2中可看出在该栈段(STACK)内,寄存器数据区和子程序自动变量数据区是完全分开的,寄存器数据区保存在高地址区域,而子程序自动变量数据区保存在低地址区域,寄存器数据区栈指针(SP)的增长方向是从高地址向低地址,而子程序自动变量数据区栈帧指针(FP)的增长方向是从低地址向高地址,在此本人将这种栈段结构称为双向栈段结构。
由于两者的栈段结构有不同,所以程序对栈段操作也是有所不同,主要有3个不同点: 1、FP对齐不同: 对于图1(当前主流CPU所使用的单向栈段结构)来说,FP总是和SP一样,都是与寄存器字长对齐,而对于图2(本指令集架构所使用的双向栈段结构)来说, SP是与寄存器字长对齐,而FP对齐于子程序第一个自动变量的数据类型(字节,半字,字,双字),与静态数据段存储的方式相同,存储更密集。 2、对SP、FP操作不同: 在图1(当前主流CPU所使用的单向栈段结构)中,由于寄存器数据区和子程序自动变量数据区是混合在一起,所以子程序func1对SP和FP的操作有: ①对于ARM32来说(5级流水线),其操作有: func1: mov ip, sp; 保存栈指针,耗时为1T stmfd sp!, {fp, ip, lr, pc};把fp, ip,lr, pc依次压栈,耗时为4T sub fp, ip, #4;产生新的栈帧指针,耗时为1T sub sp, sp, #16;开辟新的自动变量数据区,耗时为1T ...... ldmdbfp, {fp, ip, pc};恢复fp、 ip、 pc,回到调用着的状态,耗时为4T ......
从ARM的这5条指令可以算出子程序对SP和FP操作的耗时为11T(周期),其代码长度为20Byte。
②对于MIPS32来说(5级流水线),其操作有: func1: addi sp, sp, -32;开辟新的自动变量数据区,耗时为1T sw ra, 28(sp);保存ra,耗时为1T sw s8, 24(sp);保存fp,耗时为1T move s8, sp;产生新的栈帧指针fp,耗时为1T ...... lw ra, 28(sp);恢复ra,耗时为1T lw s8, 24(sp);恢复fp,耗时为1T jr ra;子程序返回,恢复pc,耗时为2T addi sp, sp, 32;恢复sp,延时槽 ......
从MIPS的这8条指令可以算出子程序对SP和FP操作的耗时为8T(周期),其代码长度为32Byte。
③对于X86来说,其操作有: func1: push ebp;耗时为1T mov ebp,esp;耗时为1T sub esp,40h;耗时为1T ...... mov esp,ebp;耗时为1T pop ebp;耗时为1T ret;耗时为2T ......
从X86的这6条指令可以算出子程序对ESP和EBP操作的耗时为7T(周期),其代码长度为10Byte。
在图2(酷能指令集所使用的双向栈段结构)中,由于寄存器数据区和子程序自动变量数据区是完全分开的,所以子程序func1对SP和FP的操作有(使用酷能指令集):
func1: add fp, #24; 产生新的栈帧指针,耗时为1T ...... ret;恢复sp、pc、lr、fp,回到调用者的状态,耗时为2T ......
从这2条指令可以看出,子程序不需要再用指令单独对SP进行操作,所以简化了进入/退出子程序的操作,其耗时为3T(周期),比图1(当前主流CPU的单向栈段结构)的ARM、MIPS和X86的操作快多了。当使用本32位指令集时,其代码长度为8Byte;而当使用本16位指令集时,其代码长度为6Byte,真是短小精悍的典范!
三种指令集调用子程序的情况对比表 指令集 | ARM32 | MIPS32 | X86 | 酷能32 | 酷能16 | 代码长度(Byte) | 20 | 32 | 10 | 8 | 6 | 总耗时(周期) | 11 | 8 | 7 | 3 | 3 |
从上表可以看出本酷能指令集具有先进性和创新性。
3、对子程序的自动变量寻址不同: 在图1中,对子程序的自动变量寻址的偏移量都是负整数,而在图2中,对子程序的自动变量寻址的偏移量是正整数,这和静态数据段(DATA)变量寻址的偏移量相同。
从上面比较分析结果看出,使用图2(本指令集架构所使用的双向栈段结构)的结构具有操作简单的优点,主要原因是子程序自动变量数据区没有插入寄存器数据,从而使得计算fp变得简单,同样的,由于寄存器数据区没有插入子程序自动变量数据,也使得维护sp、pc寄存器时简化了一些操作,但是最主要的还是由于本酷能指令集有CALL和RET指令(看指令操作说明,里面包含有对LR和FP的出入栈操作,和X86有很大差别),可以大幅度的简化调用子程序时寄存器出入栈的操作,所以优势非常明显。 |