ImageVerifierCode 换一换
格式:DOC , 页数:8 ,大小:486KB ,
资源ID:3966078      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bingdoc.com/d-3966078.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(PowerPC栈帧分析Word下载.doc)为本站会员(wj)主动上传,冰点文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰点文库(发送邮件至service@bingdoc.com或直接QQ联系客服),我们立即给予删除!

PowerPC栈帧分析Word下载.doc

1、各部分名词解释:函数参数域(Function Parameter Area):这个区域的大小是可选的,即如果如果调用函数传递给被调用函数的参数少于六个时,用GPR4至GPR10这个六个寄存器就可以了,被调用函数的栈帧中就不需要这个区域;但如果传递的参数多于六个时就需要这个区域。局部变量域(Local Variables Area):通上所示,如果临时寄存器的数量不足以提供给被调用函数的临时变量使用时,就会使用这个域。CR寄存器:即使修改了CR寄存器的某一个段CRx(x=0至7),都有保存这个CR寄存器的内容。通用寄存器GPR:当需要保存GPR寄存器中的一个寄存器器GPRn时,就需要把从GPRn

2、到GPR31的值都保存到堆栈帧中。浮点寄存器FPR:使用规则共GPR寄存器。3.PowerPC的汇编指令和栈操作 PowerPC寄存器没有专用的push和pop指令来执行堆栈操作,所以PowerPC构架使用存储器访问指令stwu、lwzu来代替push和pop指令。4.函数执行时栈帧的建立与消亡过程函数栈的建立与消亡过程如下图所示:4.1函数栈的建立与消亡过程说明如前所属,PowerPC体系结构中栈的增长方向是从高地址到低地址,故形成过程可以概括为如下几点:1) 调用函数r1指向栈顶(SP),用间接寻址方式分配一定大小栈空间;2) r31指向栈顶,以r31为基值将参数压入栈内;3) 进入被调函

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)

4、; t1 =3;void calltest( ) int t1=7; int t2 = 9; result = calltest1( t1);利用反汇编工具,生成汇编代码及分析如下: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)0x401d4f

5、4 +0x004: stw r31,44(r1)0x401d4f8 +0x008: or r31,r1,r10x401d4fc +0x00c: stw r3,8(r31)局部变量赋值:li r0 5(t1,t2.result)0x401d500 +0x010: li r0,0x5 # 50x401d504 +0x014: stw r0,12(r31)0x401d508 +0x018: li r0,0x6 # 60x401d50c +0x01c: stw r0,16(r31)0x401d510 +0x020: li r0,0x0 # 00x401d514 +0x024: stw r0,20(r3

6、1)0x401d518 +0x028:0x401d51c +0x02c: stw r0,24(r31)加载函数调用参数到r90x401d520 +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地址,返

7、回calltest1中调用calltest2的下一条指令地址0x401d57c的继续指向0x401d538 +0x048: blr 0x401d53c calltest1:将LR内容存入r0(存在函数调用时需要用到LR,用来存放函数调用结束处的返回地址)0x401d540 +0x004: mfspr r0,LR0x401d544 +0x008:0x401d548 +0x00c: stw r0,52(r1)0x401d54c +0x010:0x401d550 +0x014:局部变量赋值(t1,t2,result)0x401d554 +0x018: li r0,0x3 # 30x401d558 +

8、0x01c:0x401d55c +0x020: li r0,0x4 # 40x401d560 +0x024:0x401d564 +0x028:0x401d568 +0x02c:函数调用0x401d56c +0x030: lwz r3,16(r31)0x401d570 +0x034: bl 0x401d4f0 # calltest20x401d574 +0x038: or r0,r3,r30x401d578 +0x03c:0x401d57c +0x040:0x401d580 +0x044:0x401d584 +0x048:0x401d588 +0x04c: lwz r0,4(r11)0x401d

9、58c +0x050: mtspr LR,r00x401d590 +0x054:0x401d594 +0x058:返回calltest函数的下一条指令地址0x401d5d8的继续指向0x401d598 +0x05c: blr 0x401d59c calltest: stwu r1,-48(r1)0x401d5a0 +0x004:0x401d5a4 +0x008:0x401d5a8 +0x00c:0x401d5ac +0x010:0x401d5b0 +0x014: li r0,0x7 # 70x401d5b4 +0x018: stw r0,8(r31)0x401d5b8 +0x01c: li r

10、0,0x9 # 90x401d5bc +0x020:0x401d5c0 +0x024:0x401d5c4 +0x028:调用函数calltrst1:将t1(r31+8)加载到r3中,然后跳转到calltest1地址处(0x401d53c)0x401d5c8 +0x02c: lwz r3,8(r31)0x401d5cc +0x030: bl 0x401d53c # calltest10x401d5d0 +0x034:保存result返回值0x401d5d4 +0x038:调用完成,开始后续指令操作0x401d5d8 +0x03c:0x401d5dc +0x040:0x401d5e0 +0x044

11、:0x401d5e4 +0x048:0x401d5e8 +0x04c:0x401d5ec +0x050:0x401d5f0 +0x054:0x401d5f4 +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

12、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=0

13、xa8ce6c03)再执行result=calltest(t1),跳进calltest1之后但未进行任何操作r0 = 401d5d0 r1/sp = a8ce690 r2 = 0 r3 = 7r28 = 0 r29 = 0 r30 = 0 r31 = a8ce690msr = b030 lr = 401d5d0 ctr = 0 pc = 401d554cr = 0 xer = 0 mq = 0此时SP=0Xa8ce690,相对于原SP。正好移动48字节(即calltest栈空间)。内存分布为执行函数到result=calltest2对于有函数参数的函数,SP+8之后存储函数参数,之后紧跟局部变

14、量。综上所述,函数栈帧是以SP为基准,采用间接寻址方式申请一段栈空间。对于没有函数参数的函数,SP+8即为局部变量存储区。对于带有函数参数的函数,SP+8为函数参数存储区,之后为局部变量存储区。被调函数(calltest1)的SP为调用函数(calltest)SP减去调用函数申请的空间。上例中SP1=0xa8ce6c0;SP2=0xa8ce690;SP3=0xa8ce660问题:x86有两个寄存器,esp,ebp,ppc只用一个寄存器是怎么实现定位堆栈位置的?分析:栈是单端伸缩的表,因此,从原理上说,只要有一个栈顶指针就可以操作堆栈了。X86里的EBP起辅助作用,使栈在函数调用中的应用更方便,更高效。栈底是固定不变的,因此只要存一个数来指示栈底。对大多数CPU内置的硬件栈来说,栈底都是全1(可寻址空间的最高地址)。当栈空时,你还要做弹出,状态寄存器的溢出位也可以用来指示栈溢出。因此,甚至根本不需要保存栈底。一个栈指针寄存器完全够用了,实际上大部分架构都用一个寄存器。x86上ebp也不是必须的,你在编译的时候加上-fomit-frame-pointer参数,ebp就不用了,只用esp。cpu不需要知道,操作系统知道就可以了。溢出后会产生page fault,操作系统只需要在这个时候判断访问的时候是非法地址就可以产生segfault终止程序。汇编指令参考:

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2