PowerPC栈帧分析报告

合集下载

32位PowerPC构架通用寄存器分析及总结一

32位PowerPC构架通用寄存器分析及总结一

32位PowerPC构架通用寄存器分析及总结一第一部分 32位 PowerPC构架下寄存器概述32 位PowerPC构架寄存器模型可以分成三个类级别:UISA,VEA,OEA,我们根据这三个级别把PowerPC所使用的所有寄存器分为三类:第一类:用户指令集构架(UISA-User Instruction Set Architecture)下所使用的寄存器;第二类:虚拟环境构架(VEA-Virtual Environment Architecture)下所使用的寄存器;第三类:操作系统环境(OEA-Operating Environment Architecture)下所使用的寄存器;PowerPC指令集构架为所有的算术逻辑运算指令定义了“寄存器到寄存器”格式的指令,这些指令的操作数来自或者来自于寄存器,或者来自于指令中的立即数。

而对于“三寄存器”格式的指令,PowerPC指令集定义其中一个寄存器用来存目的操作数,另外两个寄存器用来存放源操作数。

这样的话,存放源操作数的寄存器还可以被其它指令使用,从而减少了某些操作的指令数目。

并且对于访问寄存器,PowerPC构架定义了明确的load和store访存指令(这是RISC指令集的典型特点)。

备注:寄存器中的保留位允许软件写任何值(其实就是0或者1),但是读出来的值,未必是我们写出来的值。

它的值依赖于具体的执行系统。

接下来,我们分别来介绍这三类寄存器。

第二部分 UISA寄存器集合用户模式下的寄存器可以被所有的用户级软件和特权级软件所使用,它包含以下的寄存器:32个通用寄存器GPRs(General-purpose registers):GPR0-GPR31;32个浮点寄存器FRPs(Floating-point registers):FPR0-FPR31;1个条件寄存器:CR(Condition register);1个XER寄存器;1个LR(Link register)寄存器;1个CTR(Count register)寄存器;1个浮点状态控制寄存器:FPSCR(Floating-point status and control register);备注:不管是单精度数还是双精度数,在浮点寄存器中都是以双精度格式存储。

32位PowerPC构架通用寄存器分析及总结三

32位PowerPC构架通用寄存器分析及总结三

32位PowerPC构架通用寄存器分析及总结三4.6SR(Segment Registers)寄存器OEA定义了16个32位的SR寄存器,段寄存器SR可以使用mtsr/mfsr,mtsrin/mfsrin指令进程访问。

随着CR[0]位(我们称之为T位)的值的不同,CR寄存器有两种不同的格式。

当T位为1时格式如下:CR[1]位:系统模式保护位CR[2]位:用户模式保护位CR[3]位:不可执行保护位CR[4:7]位:保留位CR[8:31]位:VSID位,我们在4.5节页面地址映射中已经看到该位段的作用。

当T位为0时格式如下:CR[1]位:系统模式保护位CR[2]位:用户模式保护位CR[3]位:不可执行保护位CR[3:11]位:Bus unit IDCR[12:31]位:Device-specific data for I/O controller备注:这个位段,我现在不清楚,暂时附上datasheet原文,以后再修改O(∩_∩)O~4.7 DAR(Data Address Register)寄存器存放访存指令产生的引发中断的有效地址,比较简单。

格式如下:4.8 SPRG0–SPRG3寄存器提供给操作系统使用,格式如下:SPRG0:操作系统可能会加载一个独立的物理地址到该寄存器中,来标识一个内存区域是第一级的中断句柄专用的。

SPRG2:可以被第一级的中断来保存通用寄存器的内容,该内容可以作为内存中保存其它通用寄存器的基地址。

SPRG2和SPRG3可以在操作系统需要时使用!备注:E600有8个SPRGs寄存器。

4.9 DSISR寄存器用来决定DSI中断的中断源,格式如下:4.10 SRR0(Machine Status Save/Restore Register 0)寄存器当发生中断时,SRR0用来保持中断发生的那一刻MSR的状态,当中断返回结束执行rfi指令时,SRR0用来恢复MSR寄存器的值,它也可以用来保持系统调用之前的那条指令的有效地址,当系统中断结束时会执行rfi指令,汇编SPR0保持的地址赋值给NIA(Next Instruction Address)寄存器(也就是我们通常说的PC寄存器)格式如下:4.11 SRR1(Machine Status Save/Restore Register 1)该寄存器同4.104.12 FPECR(Floating-Point Exception Cause Register)FPECR寄存器用来支持产生浮点中断的原因。

基于PowerPC的移动通信系统进程堆栈深度分析的方法研究

基于PowerPC的移动通信系统进程堆栈深度分析的方法研究

第12卷 第4期集美大学学报(自然科学版)Vol .12 No .4 2007年10月Journal of J i m ei University (Na t u ral Science )Oct .2007 [收稿日期]655[作者简介]贺冰琰(—),女,讲师,硕士,从事嵌入式操作系统、计算机网络研究[文章编号]1007-7405(2007)04-0356-04基于PowerPC 的移动通信系统进程堆栈深度分析的方法研究贺冰琰(集美大学计算机工程学院,福建厦门361021)[摘要]介绍了基于Po werPC 的移动通信系统中两种计算运行期时应用进程堆栈使用深度的方法:1)个体累加法;2)总体测试法.主要阐述了两种方法的基本原理并给出了具体的实现代码.[关键词]Po we rPC;G NU 编译器;垂直层次结构;移动通信系统;堆栈[中图分类号]TP 393109[文献标志码]A0 引言在移动通信系统中,经常发生应用子系统的应用进程的堆栈溢出或其他堆栈使用问题而导致的系统故障或系统崩溃,造成整个系统的服务中断.应用子系统的应用进程是整个系统使用堆栈最多、最频繁的模块,也是出现问题最多的模块.因此,确保应用子系统合理使用堆栈以及在最坏情况下能够分配到足够的堆栈是至关重要的,这就需要对子系统中的每个进程的堆栈使用深度进行有效的计算和分析.本文提出了两种检测运行期时进程的堆栈使用深度的方法.1 Po werPC 处理器的堆栈结构确保永不发生堆栈溢出的唯一途径就是:先分析代码确定程序的最大堆栈用量,然后检查是否分配了足够的堆栈.测试不大可能触发导致系统出现最坏情况的特定的瞬时输入组合.在本系统中,设备单板主处理器采用的是嵌入式微处理器P owerPC,设备软件的开发采用Torna 2do 集成开发环境.Tornado 是开发基于Vx W orks 实时嵌入式应用系统的平台,V x W orks 使用G NU 的GCC 编译器.了解PowerPC 处理器的堆栈帧结构和G NU 编译器的压栈方式,就可得到设备软件子系统中应用进程堆栈的使用深度.因此,首先从设备单板上一个应用进程的一段C /AS M 的混合代码入手,研究堆栈的结构.exte rn “C ”V O I D P_S_SER _S APEntry (WORD16wState,WORD16wSigl,VO I D 3pSiglPa ra,VO I D 3pVa rP ){ 0x526d92c P_S_SER _S APEn try:st w u r1,0xffd8(r1)//1:把寄存器r1的内容放入r1-0x 28的内存单元,并且r1=r1-0x 28.r1是堆栈指针0x526d930 +0x004: mfs p r r0,LR //2:把返回地址寄存器的内容赋给r0,以便保存到堆栈0x526d934 +0x008: st w r29,0x 1c (r1)0x526d938 +0x00c: st w r30,0x 20(r1)0x526d93c +0x010: st w r31,0x 24(r1)//3:保存需要使用的寄存器的值到堆栈中200-0-11974. 第3期贺冰琰:基于Po werPC 的移动通信系统进程堆栈深度分析的方法研究0x526d940 +0x014: st w r0,0x 2c (r1)//4:保存返回地址到堆栈中0x526d944 +0x018: or r31,r1,r1 //把r1赋给r31,使用r31对堆栈进行寻址0x526d948 +0x01c: sth r3,0x8(r31)0x526d94c +0x020: sth r4,0xa (r31)0x526d950 +0x024: st w r5,0x c (r31)0x526d954 +0x028: st w r6,0x 10(r31)//5:保存传入的函数参数到堆栈中以上斜体部分的代码是函数的宣言部分,由编译器自动生成.T_P_S_SE R _SAP 3p t V a r;pt Var =stati c _cast <T_P_S_SER_S AP 3>(pVarP );0x526d958 +0x 02c:l w z r0,0x 10(r31)0x526d95c +0x030:st w r0,0x 14(r31)//此处可以看到局部变量pt Va r 在堆栈中的位置s w itch(wState)0x526d960 +0x 034:lhz r9,0x8(r31)由此,可以绘出函数的堆栈帧的具体情况(如图1所示).通过函数宣言的5个步骤完成了一个函数压栈的基本操作.PPC 处理器提供32个用户寄存器r 0~r 31,G NU 编译器使用寄存器的基本规则是:寄存器r 1作为堆栈指针SP;寄存器r3~r 11用于函数参数的传递;寄存器r13~r 31根据代码的具体情况进行使用[1].由于函数的不同,G NU 编译器产生的代码也不同,从而使压栈操作的第3步和第5步有所不同,压入的寄存器个数不同,但是不影响堆栈帧的基本结构.因此,当一个函数func1调用另一个函数func2时会形成如图2所示的堆栈帧.2 计算运行期时应用进程堆栈使用深度的方法由堆栈帧结构可以获得一些检测应用进程堆栈使用深度的方法,通过堆栈指针r1的不同使用情况判断出堆栈的使用深度.本文主要进行了个体累加法和总体测试法这两种方法的尝试.211 个体累加法1)功能描述这种方法的基本思想是对进程中每层调用的函数的局部堆栈进行累积,从而得到进程堆栈最大使用深度[]由于每次函数调用后堆栈指针发生变化,那么可以认为的变化量′就是函数的局部堆栈使用深度的大小宏UDG STK ()实现计算进程最大堆栈使用深度的功能通过这种方法还可以知道进程中哪些函数使用堆栈过大,针对这些函数可以进一步分析和优化7532.r1r1r1-r 1.J E ..集美大学学报(自然科学版)第12卷2)实现流程a .定义全局变量ty pedef struct tag T_StkChk { WORD32d w B aseSP; //进程堆栈基值WORD32d w MaxStk Dp t ; //进程最大堆栈深度WORD32d wCurStk Dp t ; //进程当前堆栈深度WORD32d wStkS i ze; //进程预设的堆栈大小}T _StkChk;T_St kChk t StkChk ={0,0,0,40960};b .定义如下宏#define GET BASESP ()__as m __("st w 1,%0":"=m "(tStk Chk 1d w B aseSP ));//得到进程的堆栈基值#define J UDGESTK()__a s m __("st w 1,%0":"=m "(tStk Chk 1d wCurStk Dp t));//得到当前函数堆栈的r1tSt kChk 1dwCurStk Dp t =tStkChk 1d w B aseSP -tStkChk 1d wCurStk Dp t ;//计算进程当前的堆栈深度if (tStk Chk 1d wCurStk Dp t >t StkChk 1dw M axSt kDp t )//是否大于进程最大堆栈深度tSt kChk 1dw M axStk Dp t =tStkChk 1d wCurStk Dpt;//如果是赋值给最大深度OSS_ASSERT (tStk Chk 1d w MaxStk Dp t <t StkChk 1d wStkSize );//断言最大深度小于预期的深度c .定义全局函数VO I D PrintStk ()//用于打印进程最大堆栈的使用深度{OSS_Printf (PRT_SER _S AP,"\r \n M axSk Dp t =0x%4x!",StkChk 1d w MaxStk Dpt);}d .使用方法在进程的入口处使用宏GET BASESP ()得到进程堆栈的基值.exte rn "C "V O I D P_S_SER _S APEntry (WORD16wState,WORD16wSigl,VO I D 3pSiglPa ra,VO I D 3pVa rP ){ T_P_S_SER_S AP 3p t Var;pt Va r =static_ca st <T_P _S_SER _S AP 3>(pVarP);GET BASESP ();}在进程的每个函数的入口处使用宏JUDGESTK ()检测进程堆栈使用深度.VO I D CS APAppCB::P rocessEvent (WORD16wSi gl,const VO I D 3pSiglPa ra ){ JU D G ESTK();}212 总体测试法1)功能描述这种方法是把进程的堆栈分配到一块静态分配的内存上,该块内存已经初始化为0.调用函数ChkStk ()检查内存时只要找到第一个不为0的地方,就可得到进程堆栈深度.这种方法的优点在于实时地反映进程的堆栈使用深度.2)实现流程a .定义全局变量定义的数组大小是堆栈的大小加上16作为保护;PPC 的堆栈是向低的地址增长的;PPC 是4字节对齐的,地址一定要是4的倍数,因此取数组的下标要注意.定义全局数组作为进程的堆栈:B Y TE g_ucStk [4096+16];B Y TE 3g_pucStk;WORD32d wStkPoint ;g_pucStk =&g_ucStk[4092].b .定义宏#f R LS ()____(",%""="(S ));____("z ,%""="(_S ));用于替换系统的堆栈到自己分配的内存上#f R STS ()____("z ,%""="(S ));用于恢复堆栈指针853de ine EP P as m st w 10:m dw tkPo i nt a s m l w 10:m g puc tk //de ine E P as m l w 10:m d w t kPoint // 第3期贺冰琰:基于Po werPC 的移动通信系统进程堆栈深度分析的方法研究c .定义全局函数VO I D ChkStk (){ WORD32d w Lp;for (dw Lp =0;d wLp <MAX_STK_S IZ E;d w Lp ++){ if (0==g_ucStk [d w Lp ]){ OSS_Printf (PRT_SE R _S AP,"\r \n M axSk Dpt =0x%4x !",MAX_STK_SIZE -d w Lp +1);break;}}}d .使用方法进程入口处使用宏R EP LSP ()替换堆栈区;在进程中每个OSS_Set NextState ()使用宏RE 2STSP ()恢复SP;在Shell 中使用函数ChkStk ()得到结果.3 两种方法的应用举例在应用子系统里每个应用进程实际就是一个大的函数,P_S_SendMsg()是一个发送消息进程,采用个体累加法来获取P_S_Send M sg ()进程的最大堆栈使用深度.首先在P_S_SendMsg ()进程的入口处调用GETBASESP (),然后在P_S_Send M sg ()中的每个函数入口处都添加宏JU D G ESTK ().如果P_S_Send M sg ()有100个函数,需要在这100个函数的入口处添加宏JUDGESTK (),最后在Shell 中使用函数PrintStk ()得到结果.如果子系统功能复杂,进程中函数众多,使用该方法则相对麻烦.采用总体测试法来获取P_S_Send M sg ()进程的实时堆栈使用深度,根据前面介绍的使用方法在P_S_Send M sg()增加代码,首先在进程入口处添加REPLSP (),然后在P_S_Send M sg ()中的每个OSS_Set NextState ()函数入口处都添加宏RESTSP (),最后在Shell 中使用函数C hkStk ()得到结果.显然总体测试法比较简单.本文提出的两种方法都已经经过实际的应用测试,可以准确地反馈运行期时进程的堆栈使用深度,对程序代码的优化和堆栈的合理使用具有一定的借鉴意义.[参考文献][1]MOT ORO LA I N C 1Upc860Powe rcem icc use r πs manual [E B /OL ].[2005201210].http://w w w 1free scale 1co m /doc /ref_m anual/MPC860u m 1pdf .[2]SE AN M B E ATT Y .嵌入式软件设计中查找缺陷的几个技巧[E B /OL ].[2004205216].htt p://w w w .ee tchina .co m /ART_8800336240_617693_dea37411200405.HT M.S tudy of Stack D epth Ca lcul a ti on for the P r ocess i n theM ob ile C o mm un i ca ti on Syste m Ba sed on Power PCHE B ing 2yan(Sch ool of Co mputer Engi neering,Ji me i Univ e rsity,Xiamen 361021,China)Abstra ct:T wo m ethods of stack depth calcula tion about the r unning ti m e app licati on pr ocess in the mo 2bile c ommunication syste m ba sed on e m bedded PowerPC p r oce ss or were intr oduced .O ne was “individual cu 2m ulati on ”,the otherwas “collectivity test ”.The basic p rinci p les and code realizati on of the t w om ethodswas yK y ;G NU ;y;y ;(责任编辑 朱雪莲)953intr oduced mainl.e wor ds:Po werPC co mp iler v ertica l hie r a r ch mobile co mmunicati on s ste m stack。

PowerPC简介及编程要点

PowerPC简介及编程要点

PowerPC简介及编程一,PowerPC芯片PowerPC是早期Motorola和IBM联合为Apple的MAC机开发的CPU芯片,商标权同时属于IBM和Motorola,并成为他们的主导成品.IBM主要的PowerPC产品有PowerPC604s(深蓝内部的CPU),PowerPC750,PowerPCG3(1.1GHz).Motorola主要有MC和MPC系列.尽管他们产品不一样,但都采用PowerPC的内核.这些产品大都用在嵌入式系统中.Motorola的MPC860简介MPC860 PowerQUICC (Quad Integrated Communications Controller) 内部集成了微处理器和一些控制领域的常用外围组件, 特别适用于通信产品. 包括器件的适应性, 扩展能力和集成度等. MPC860 PowerQUICC集成了两个处理块.一个处理块是嵌入的PowerPC核, 另一个是通信处理模块( CPM, Communications Processor Module), 通信处理模块支持四个串行通信控制器(SCC, Serial Communication Controller), 实际上它有八个串行通道: 四个SCC,两个串行管理控制器(SMC, Serial Management Channels), 一个串行外围接口电路( SPI, Serial Peripheral Interface ) 和一个I2C( Inter-Integrated Circuit ) 接口. 由于CPM分担了嵌入式PowerPC核的外围工作任务, 这种双处理器体系结构功耗要低于传统的体系结构的处理器.单出口, 嵌入式PowerPC核32比特版本(与PowerPC结构定义完全兼容)32x32位通用寄存器(GPRs, General Purpose Registers)o4K数据Cache和4K指令Cache, 分别带有一个MMU.o存储管理单元(MMU)32-输入翻译后备缓冲器( TLBs )o32位数据,地址线∙存储控制器(八个存储体)o单线存储模块无逢接口,静态随即存取存储器(RAM), EPROM, FLASH MEMORY或DRAM等。

powerPC架构及编程资料

powerPC架构及编程资料
从最初的 PowerPC 体系结构的开发开始,就根据特定的市场需求而发 生分支。当前,PowerPC 体系结构家族树有两个活跃的分支,分别是 PowerPC AS体系结构和 PowerPC Book E体系结构。PowerPC AS 体系结构 是 IBM 为了满足它的 eServer pSeries UNIX 和 Linux 服务器产品家族及它 的 eServer iSeries 企业服务器产品家族的具体需要而定义的。PowerPC Book E 体系结构,也被称为 Book E,是 IBM 和 Motorola 为满足嵌入式市 场的特定需求而合作推出的。
PowerPC架构及在vxworks下的开发
报告人 : miko
1. powerPC概述 2. MPC8260架构及编程设计 3. 其它类型powerPC基于RISC系统、运行AIX V3的新产品线RS/6000。该 系统架构后来被称为POWER(POWER1),意为增强RISC性能优化 (Performance Optimization With Enhanced RISC)架构。
图为:PowerPC 603e处理器
G3 系列
首次面世是在 1998 年,PowerPC 740 和 PowerPC 750 与 604e 非常类 似 , PowerPC 740/750 是世界上 第一组基于铜的微处理器 ,当它用于 Apple 计算机时,通常称为 G3 ,工 作频率为 400 MHz。由于使用了铜芯 片技术,处理性能提高了近1/3。
图2是MC68030的两个版本,最早使 用在1991年10月推出的PowerBook 140 上.
MC68000处理器 MC68030处理器
G1 系列(只是为了表示方便,非 正式的官方名称)

PowerPC和DSP对比

PowerPC和DSP对比

PowerPC和DSP对比一、主要性能参数对比ASDP tigersharp主要参数Word 资料Word 资料主要DSP的浮点性能对比:Speed Scores for floating-point packaged processors BDTImark2000(BDTI认证结果) Word 资料(BDTI主要是针对DSP的benchmark,没有MPC7410和Powerpc的数据)一些算法,像FFT,可以充分利用7410的矢量数学运算。

1024点,浮点复数FFT可以在27us内完成,相比之下,C6701需要108us。

其他算法,像无线应用中的turbo解码器,VLIW结构处理的更有效率。

很明显,具有AltiVec核的PowerPC G4(74xx)具有较高的核时钟速率与性能。

P O W e r P C 的核时钟速率几乎是目前T i g e r s H A R C的3.3倍(不久更快版本的TigerSHARC将发布)。

AltiVec核每个周期执行单条指令,每128位向量包含4个独立的32位数据单元,这就是众所周知的sIM-D(单指令多数据)结构。

当执行一次乘加(MAC)矢量运算时,达到峰值处理能力,每周期可完成8次浮点操作。

对于1 GHz的MPC7455,峰值处理能力可达8000M 次/s浮点运算。

AltiVec每周期能执行8次整数或定点操作,峰值整数运算能力为8000MOPS(百万次操作/s)。

相反,TigerSHARC有两个独立的32位处理器核,或称MIMD(多指令多数据)结构。

每个计算单元每周期能执行一次乘法以及和差分运算,对于300 MHz ADSPTSl0lS每周期完成6次浮点运算或1800MFLOPS峰值运算能力。

当执行16位整数运算时,TigerSHARC 可以利用它的超标量体系结构,分离两个独立3 2位计算单元成2个单独的16位S1MD单元。

这样每个操作在两个数据单元,每个周期总共12次操作。

IBM PowerPC 汇编简介

IBM PowerPC 汇编简介

IBM PowerPC 汇编简介/developerworks/cn/linux/hardware/ppc/assembly/#resourcesHollis Blanchard (hollis@), 软件开发人员, IBM简介:目前汇编语言在编程领域并未广为人知,而 PowerPC 汇编更是异乎寻常的陌生。

Hollis Blanchard 从 PowerPC 的角度对汇编语言作了概述并对比了三种体系结构 ia32、ppc 和 ppc64 的示例。

标记本文!发布日期: 2004 年 3 月 09 日通常,高级语言都具有向程序员隐藏许多普通的和重复性细节这一非常好的优点,这样程序员就可以专注于他们的目标。

然而,有时程序员必须使用较低级语言,例如当编写直接处理硬件的代码或编写对性能极其敏感的代码的时候。

汇编语言是最接近硬件的编程语言,这就很自然使它成为上述那些情况下最终使用的一种语言。

本文假设您对计算机设计(例如,您应该知道处理器中有寄存器并能访问内存)和操作系统(系统调用、异常和进程堆栈)有基本了解。

本文对于不熟悉汇编的 PowerPC 程序员以及已知道 ia32 汇编并想扩展眼界的程序员都很有用。

PowerPC 简介PowerPC 体系结构规范(PowerPC Architecture Specification)发布于 1993 年,它是一个 64 位规范 ( 也包含 32 位子集 )。

几乎所有常规可用的 PowerPC(除了新型号 IBM RS/6000 和所有 IBM pSeries 高端服务器)都是 32 位的。

PowerPC 处理器有广泛的实现范围,包括从诸如 Power4 那样的高端服务器 CPU 到嵌入式CPU 市场(任天堂 Gamecube 使用了 PowerPC)。

PowerPC 处理器有非常强的嵌入式表现,因为它具有优异的性能、较低的能量损耗以及较低的散热量。

除了象串行和以太网控制器那样的集成 I/O,该嵌入式处理器与“台式机”CPU 存在非常显著的区别。

PowerPC桥_存储器控制器FPGA验证平台的设计

PowerPC桥_存储器控制器FPGA验证平台的设计

同时 , 以最快的速度发现可能存在逻辑功能和时序上 的问题。 Pow erPC 桥 /存储 器控制 芯片逻 辑的 FPGA 逻辑 功能验证平台 , 可以从三个层面实现对于待测逻辑代 码的功能验证 , 其具体模型如图 1 所示。
2 验证需求
由于待测逻辑 代码的功 能设计 方面参 考了 M o toro la公司有着很广泛应用的通用 P ow erPC 桥 /存 储器 控 制 芯 片 M PC107 。 该 芯 片 除 了 具 备 MPC6XX, M PC7XX, MPC74XX 处理器 到 PC I 总线的接口 外, 还 提供了一个高性能的存储器控制器, 两处理器的支持 , 两通道 DMA 控制器, 一个中断控制器 , 一路 I O 消息 控制器, 一路 I C 接口, 一个时钟锁相环电路等。 根据实际工程需要 , 待测逻辑裁 减了原 M PC107 部分功能, 但主要 性能指 标和 寄存 器配 置上依 然和 M PC107 保持一致。其具体指标如下 : 1)提供处理器接口功能 ; 提供 66 MH z 工作频率的 60X 处理 器 接 口, 支 持 一 级 地 址 流 水, 单 拍 ( sing le
收稿日期 : 2008 06 10
作者简介 : 麻晓博 ( 1981 - ) , 男, 陕西西安人 , 助理工程师 , 研究方向为计算机应用。
108
航空计算技术
第 38 卷
第 6期
4) 提供嵌入式可编程中断控制器 ( EP IC) 功能; 提 供 5 个外部中断源资源或一个可配置优先级的 16 个 中断源 , 所有中断源均可编程配置为沿中断或电平中 断 , 提供 4个 31位可用作系统定时和产生中断周期的 定时器。 FPGA 内部功能划分如图 2所示。
摘 要 : 针对 Pow erPC 桥 /存储器控制器功 能逻辑 的验证 需求 , 采用 软硬件 协同 测试 的方法 构建 基
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

PowerPC栈帧分析1 .PowerPC寄存器的使用规则通用寄存器的用途:r0 在函数开始(function prologs)时使用。

r1 堆栈指针,相当于ia32架构中的esp寄存器,idapro把这个寄存器反汇编标识为sp。

r2 内容表(toc)指针,idapro把这个寄存器反汇编标识为rtoc。

系统调用时,它包含系统调用号(这个好像跟系统有关吧)。

r3 作为第一个参数和返回值。

r4-r10 函数或系统调用开始的参数。

r11 用在指针的调用和当作一些语言的环境指针。

r12 它用在异常处理和glink(动态连接器)代码。

r13 保留作为系统线程ID。

r14-r31 作为本地变量,非易失性。

专用寄存器的用途:lr 链接寄存器,它用来存放函数调用结束处的返回地址。

ctr 计数寄存器,它用来当作循环计数器,会随特定转移操作而递减。

xer 定点异常寄存器,存放整数运算操作的进位以及溢出信息。

msr 机器状态寄存器,用来配置微处理器的设定。

cr 条件寄存器,它分成8个4位字段,cr0-cr7,它反映了某个算法操作的结果并且提供条件分支的机制。

2.栈帧的使用规则PowerPC寄存器没有专用的Pop,Push指令来执行堆栈操作,所以PowerPC构架使用存储器访问指令stwu,lwzu来代替Push和Pop指令。

PowerPC处理器使用GPR1来将这个堆栈段构成一个单向链表,这个单链表的每一个数据成员,我们称之为堆栈帧(Stack Frame),每一个函数负责维护自己的堆栈帧。

PowerPC体系结构中栈的增长方向是从高地址到低地址,堆的增长方式是从低地址到搞地址,当两者相遇时就会产生溢出。

堆栈帧的格式如下:各部分名词解释:函数参数域(Function Parameter Area):这个区域的大小是可选的,即如果如果调用函数传递给被调用函数的参数少于六个时,用GPR4至GPR10这个六个寄存器就可以了,被调用函数的栈帧中就不需要这个区域;但如果传递的参数多于六个时就需要这个区域。

局部变量域(Local Variables Area):通上所示,如果临时寄存器的数量不足以提供给被调用函数的临时变量使用时,就会使用这个域。

CR寄存器:即使修改了CR寄存器的某一个段CRx(x=0至7),都有保存这个CR寄存器的内容。

通用寄存器GPR:当需要保存GPR寄存器中的一个寄存器器GPRn时,就需要把从GPRn到GPR31的值都保存到堆栈帧中。

浮点寄存器FPR:使用规则共GPR寄存器。

3. PowerPC的汇编指令和栈操作PowerPC寄存器没有专用的push和pop指令来执行堆栈操作,所以PowerPC构架使用存储器访问指令stwu、lwzu来代替push和pop指令。

4.函数执行时栈帧的建立与消亡过程函数栈的建立与消亡过程如下图所示:4.1函数栈的建立与消亡过程说明如前所属,PowerPC体系结构中栈的增长方向是从高地址到低地址,故形成过程可以概括为如下几点:1)调用函数r1指向栈顶(SP),用间接寻址方式分配一定大小栈空间;2)r31指向栈顶,以r31为基值将参数压入栈内;3)进入被调函数,跳转到被调函数的SP处;4)被调函数同样进行栈分配及参数压栈操作;5)被调函数执行完毕之后,跳转LR,返回到被调用处的下一条指令,继续后续操作(此时的SP即为调用函数的SP)4.2举例说明栈操作过程以下以一个简单的函数调用,说明PowerPC栈的操作过程。

函数例子如下:int calltest2( int a){int t1=5;int t2 = 6;int result =0;char * p =0;*p =a;}int calltest1( int a){int t1=3;int t2 = 4;int result =0;result = calltest2( t2);t1 =3;}void calltest( ){int t1=7;int t2 = 9;int result =0;result = calltest1( t1);t1 =3;}利用反汇编工具,生成汇编代码及分析如下:int calltest2( int a){Calltest2栈帧建立分析:stwu r1,-48(r1):分配48字节的栈帧,r1指向栈顶;(powerpc省略了EBP,所以一上来即进行一次间接寻址)stw r31,44(r1):保存r31的原值,以后恢复;or r31,r1,r1:让r31指向栈顶r1(r31=r1 or r31)stw r3,8(r31):第一个形参0x401d4f0 calltest2: stwu r1,-48(r1)0x401d4f4 +0x004: stw r31,44(r1)0x401d4fc +0x00c: stw r3,8(r31)局部变量赋值:li r0 5(t1,t2.result)int t1=5;0x401d500 +0x010: li r0,0x5 # 50x401d504 +0x014: stw r0,12(r31)int t2 = 6;0x401d508 +0x018: li r0,0x6 # 60x401d50c +0x01c: stw r0,16(r31)int result =0;0x401d510 +0x020: li r0,0x0 # 00x401d514 +0x024: stw r0,20(r31)char * p =0;0x401d518 +0x028: li r0,0x0 # 00x401d51c +0x02c: stw r0,24(r31)加载函数调用参数到r9*p =a;0x401d520 +0x030: lwz r9,24(r31)0x401d524 +0x034: lbz r0,11(r31)保存r9到r00x401d528 +0x038: stb r0,0(r9)}r11=r1,r31=r11-4=r1-4,恢复r31的值0x401d52c +0x03c: lwz r11,0(r1)0x401d530 +0x040: lwz r31,-4(r11)0x401d534 +0x044: or r1,r11,r11blr:跳转到LR地址,返回calltest1中调用calltest2的下一条指令地址0x401d57c的继续指向0x401d538 +0x048: blrint calltest1( int a){0x401d53c calltest1: stwu r1,-48(r1)将LR内容存入r0(存在函数调用时需要用到LR,用来存放函数调用结束处的返回地址)0x401d540 +0x004: mfspr r0,LR0x401d544 +0x008: stw r31,44(r1)0x401d548 +0x00c: stw r0,52(r1)0x401d54c +0x010: or r31,r1,r10x401d550 +0x014: stw r3,8(r31)局部变量赋值(t1,t2,result)int t1=3;0x401d558 +0x01c: stw r0,12(r31)int t2 = 4;0x401d55c +0x020: li r0,0x4 # 40x401d560 +0x024: stw r0,16(r31)int result =0;0x401d564 +0x028: li r0,0x0 # 00x401d568 +0x02c: stw r0,20(r31)函数调用result = calltest2( t2);0x401d56c +0x030: lwz r3,16(r31)0x401d570 +0x034: bl 0x401d4f0 # calltest2 0x401d574 +0x038: or r0,r3,r30x401d578 +0x03c: stw r0,20(r31)t1 =3;0x401d57c +0x040: li r0,0x3 # 30x401d580 +0x044: stw r0,12(r31)}0x401d584 +0x048: lwz r11,0(r1)0x401d588 +0x04c: lwz r0,4(r11)0x401d58c +0x050: mtspr LR,r00x401d590 +0x054: lwz r31,-4(r11)0x401d594 +0x058: or r1,r11,r11返回calltest函数的下一条指令地址0x401d5d8的继续指向0x401d598 +0x05c: blrvoid calltest( ){0x401d59c calltest: stwu r1,-48(r1)0x401d5a0 +0x004: mfspr r0,LR0x401d5a4 +0x008: stw r31,44(r1)0x401d5a8 +0x00c: stw r0,52(r1)0x401d5ac +0x010: or r31,r1,r1int t1=7;0x401d5b0 +0x014: li r0,0x7 # 70x401d5b4 +0x018: stw r0,8(r31)int t2 = 9;0x401d5b8 +0x01c: li r0,0x9 # 90x401d5bc +0x020: stw r0,12(r31)int result =0;0x401d5c0 +0x024: li r0,0x0 # 00x401d5c4 +0x028: stw r0,16(r31)调用函数calltrst1:将t1(r31+8)加载到r3中,然后跳转到calltest1地址处(0x401d53c)result = calltest1( t1);0x401d5c8 +0x02c: lwz r3,8(r31)0x401d5cc +0x030: bl 0x401d53c # calltest10x401d5d0 +0x034: or r0,r3,r3保存result返回值0x401d5d4 +0x038: stw r0,16(r31)调用完成,开始后续指令操作t1 =3;0x401d5d8 +0x03c: li r0,0x3 # 30x401d5dc +0x040: stw r0,8(r31)}0x401d5e0 +0x044: lwz r11,0(r1)0x401d5e4 +0x048: lwz r0,4(r11)0x401d5e8 +0x04c: mtspr LR,r00x401d5ec +0x050: lwz r31,-4(r11)0x401d5f0 +0x054: or r1,r11,r110x401d5f4 +0x058: blr下面利用断点调试跟踪栈内存执行过程1)在进入calltest但未执行任何指令(参数还未赋值)时,查看寄存器及内存分布如下:r0 = c7cbd8 r1/sp = a8ce6c0 r2 = 0 r3 = 0r4 = 0 r5 = 0 r6 = 0 r7 = 0r8 = 0 r9 = 0 r10 = 0 r11 = a8ce738r12 = 401d59c r13 = 0 r14 = 0 r15 = 0r16 = 0 r17 = 0 r18 = 0 r19 = 0r20 = 0 r21 = 0 r22 = 0 r23 = 0r24 = 0 r25 = 0 r26 = 0 r27 = 0r28 = 0 r29 = 0 r30 = 0 r31 = a8ce6c0msr = b030 lr = c7cbd8 ctr = 0 pc = 401d5b0cr = 0 xer = 0 mq = eeeeeeee内存空间为此时sp=0xa8ce6c0,r31指向r1,pc=0x401d5b02)执行到result=0(局部变量赋值完成,但没有调用caltest1)在紧跟SP之后,SP+8即为局部变量存储区,此时此时sp=0xa8ce6c03)再执行result=calltest(t1),跳进calltest1之后但未进行任何操作r0 = 401d5d0 r1/sp = a8ce690 r2 = 0 r3 = 7r4 = 0 r5 = 0 r6 = 0 r7 = 0r8 = 0 r9 = 0 r10 = 0 r11 = a8ce738r12 = 401d59c r13 = 0 r14 = 0 r15 = 0r16 = 0 r17 = 0 r18 = 0 r19 = 0r20 = 0 r21 = 0 r22 = 0 r23 = 0r24 = 0 r25 = 0 r26 = 0 r27 = 0r28 = 0 r29 = 0 r30 = 0 r31 = a8ce690msr = b030 lr = 401d5d0 ctr = 0 pc = 401d554cr = 0 xer = 0 mq = 0此时SP=0Xa8ce690,相对于原SP。

相关文档
最新文档