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

开通VIP
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.zixin.com.cn/docdown/4762843.html】到电脑端继续下载(重复下载【60天内】不扣币)。

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

开通VIP折扣优惠下载文档

            查看会员权益                  [ 下载后找不到文档?]

填表反馈(24小时):  下载求助     关注领币    退款申请

开具发票请登录PC端进行申请

   平台协调中心        【在线客服】        免费申请共赢上传

权利声明

1、咨信平台为文档C2C交易模式,即用户上传的文档直接被用户下载,收益归上传人(含作者)所有;本站仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。所展示的作品文档包括内容和图片全部来源于网络用户和作者上传投稿,我们不确定上传用户享有完全著作权,根据《信息网络传播权保护条例》,如果侵犯了您的版权、权益或隐私,请联系我们,核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
2、文档的总页数、文档格式和文档大小以系统显示为准(内容中显示的页数不一定正确),网站客服只以系统显示的页数、文件格式、文档大小作为仲裁依据,个别因单元格分列造成显示页码不一将协商解决,平台无法对文档的真实性、完整性、权威性、准确性、专业性及其观点立场做任何保证或承诺,下载前须认真查看,确认无误后再购买,务必慎重购买;若有违法违纪将进行移交司法处理,若涉侵权平台将进行基本处罚并下架。
3、本站所有内容均由用户上传,付费前请自行鉴别,如您付费,意味着您已接受本站规则且自行承担风险,本站不进行额外附加服务,虚拟产品一经售出概不退款(未进行购买下载可退充值款),文档一经付费(服务费)、不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
4、如你看到网页展示的文档有www.zixin.com.cn水印,是因预览和防盗链等技术需要对页面进行转换压缩成图而已,我们并不对上传的文档进行任何编辑或修改,文档下载后都不会有水印标识(原文档上传前个别存留的除外),下载后原文更清晰;试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓;PPT和DOC文档可被视为“模板”,允许上传人保留章节、目录结构的情况下删减部份的内容;PDF文档不管是原文档转换或图片扫描而得,本站不作要求视为允许,下载前可先查看【教您几个在下载文档中可以更好的避免被坑】。
5、本文档所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用;网站提供的党政主题相关内容(国旗、国徽、党徽--等)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
6、文档遇到问题,请及时联系平台进行协调解决,联系【微信客服】、【QQ客服】,若有其他问题请点击或扫码反馈【服务填表】;文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“【版权申诉】”,意见反馈和侵权处理邮箱:1219186828@qq.com;也可以拔打客服电话:0574-28810668;投诉电话:18658249818。

注意事项

本文(Linux基本反汇编结构与GDB入门.doc)为本站上传会员【二***】主动上传,咨信网仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知咨信网(发送邮件至1219186828@qq.com、拔打电话4009-655-100或【 微信客服】、【 QQ客服】),核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载【60天内】不扣币。 服务填表

Linux基本反汇编结构与GDB入门.doc

1、Linux下的汇编与Windows汇编最大的不同就是第一个操作数是原操作数,第二个是目的操作数,而Windows下却是相反。 1、 基本操作指令 简单的操作数类型说明,一般有三种, (1)立即数操作数,也就是常数值。立即数的书写方式是“$”后面跟一个整数,比如$0x1F,这个会在后面的具体分析中见到很多。 (2)寄存器操作数,它表示某个寄存器的内容,用符号Ea来表示任意寄存器a,用引用R[Ea]来表示它的值,这是将寄存器集合看成一个数组R,用寄存器表示符作为索引。 (3)操作数是存储器引用,它会根据计算出来的地址(通常称为有效地址)访问某个存储器位置。用符号Mb[Addr]表示对

2、存储在存储器中从地址Addr开始的b字节值的引用。通常可以省略下标b。 图1表示有多种不同的寻址模式,一个立即数偏移Imm,一个基址寄存器Eb,一个变址或索引寄存器Ei和一个伸缩因子s。有效地址被计算为Imm+R[Eb]+R[Ei]*s,对于这中寻址方式,我们可以在数组或者结构体中进行对元素进行访问时会用到。 操作数类型 格式 操作数值 名称 立即数 $Imm Imm 立即数寻址 寄存器 Ea R[Ea] 寄存器寻址 寄存器 Imm M[Imm] 绝对寻址 寄存器 (Ea) M[R[Ea]] 间接寻址 寄存器 Imm

3、Eb) M[Imm+R[Eb]] (基址+偏移量)寻址 寄存器 (Eb,Ei) M[R[Eb]+R[Ei]] 变址寻址 寄存器 M[Imm+R[Eb]+R[Ei]] 寄存器 (,Ei, s) M[R[Ei] * s] 伸缩化的变址寻址 寄存器 Imm(,Ei, s) M[Imm+R[Ei] * s]] 伸缩化的变址寻址 寄存器 (Eb,Ei, s) M[R[Eb]+R[Ei] * s] 伸缩化的变址寻址 寄存器 Imm(Eb,Ei, s) M[Imm+R[Eb]+R[Ei] * s] 伸缩化的变址寻址

4、图1 操作数格式 注:操作数可以是立即数值、寄存器值或是来自存储器的值,伸缩因子必须是1、2、4、或者是8。 从上面的图我们就可以大致了解操作数的类型了。 在操作指令中,最频繁使用的指令是执行数据传送的指令。对于传送指令的两个操作数不能都指向存储器位置(我的理解是一般存储器存储的都是地址,不能够对地址和地址进行操作)。将一个值从一个存储器位置拷到另一个存储器位置需要两条指令——第一条指令将源值加载到寄存器中,第二条将该寄存器值写入到目的位置。下面给出源操作数和目的操作数的五种可能组合。 1、movl $0x4050, %eax 立即数——寄存器 2、movl %ebp

5、 %esp 寄存器——寄存器 3、movl (%edi, %ecx), %eax 存储器——寄存器 4、movl $-17, (%esp) 立即数——存储器 5、 movl %eax, -12(%ebp) 寄存器——存储器 注意这里的指令mov可能有不同的形式,不同平台的汇编一般是有些不一样的,但这并不会影响我们理解汇编,只要熟悉其细节之后就能够明白的。 指令 效果 描述 movl S, D D ←S 传送双字 movl S, D D ←S 传送字 movl S, D D ←S 传送字节

6、 movl S, D D ←符号扩展(S) 传送符号扩展的字节 movl S, D D ←零扩展(S) 传送零扩展的字节 pushl S R[%esp] ← R[%esp] – 4; M[R[%esp]] ← S 压栈 popl D D ← M[R[%esp]]; R[%esp] ← R[%esp] + 4 出栈 图2:数据传送指令 结合例子来进行讲解一下指令的具体操作,在这里将会正式接触到Linux下的GCC开发环境和GDB调试器,不过都是比较简单的应用。我的Linux操作系统是Ubuntu9.10,其它版本的差别应该不大,

7、 如果我们要编写一个程序,我们可以用Linux下自带的vi或vim编辑器, studyrush@studyrush-desktop:~/C$ vi exchange.c vi 后面加我们要创建的程序文件的名字,在这里是exchange.c studyrush@studyrush-desktop:~/C$ gcc -o exchange exchange.c gcc -o exchange exchange.c 或gcc exchange –o exchange这两者都可以对源文件进行编译,-o exchange 表示对我们要输出的文件名称,可能表达的不够准确,大家可以先熟悉一

8、下gcc编译器,应该就会明白的了。 studyrush@studyrush-desktop:~/C$ ./exchange 点加斜线再加输出文件名就表示运行程序,下面是运行的结果。 a = 3, b = 4 使用GDB可以参考附件里面的教程,这份教程写的很不错,看雪论坛本身也有,大家可以看这个贴( studyrush@studyrush-desktop:~/C$ gdb exchange 命令disas就表示反汇编(disassembly),后面再加上要显示的函数名,我们就可以看到函数对应的反汇编代码了。 (gdb) disas exchange Dump of assemb

9、ler code for function exchange: 0x080483c4 : push %ebp 0x080483c5 : mov %esp,%ebp 0x080483c7 : sub $0x10,%esp 0x080483ca : mov 0x8(%ebp),%eax 0x080483cd : mov (%eax),%eax 0x080483cf : mov %eax,-0x4(%ebp)

10、 0x080483d2 : mov 0x8(%ebp),%edx 0x080483d5 : mov 0xc(%ebp),%eax 0x080483d8 : mov %eax,(%edx) 0x080483da : mov -0x4(%ebp),%eax 0x080483dd : leave 0x080483de : ret End of assembler dump. 进一步来分析上面的反汇

11、编代码,这里的代码可能与前面的讲的指令操作有一些不同,因为这是很正常的,不同的操作系统应该有所差别,这也是汇编语言一般与平台有关,移植性并不好。 push %ebp mov %esp,%ebp sub $0x10,%esp 对有过反汇编的人对上面的代码肯定不会陌生,这里就是将ebp进栈,保存esp的值,并为局部变量预留空间。要记得源操作数与目的操作数的位置,前面有讲的。这里也一定程度对C语言中的指针使用进行了说明。看源代码可以知道。 mov 0x8(%ebp),%eax mov (%eax),%eax mov %eax,-0x4(%ebp)

12、 mov 0x8(%ebp),%eax 取得xp,其实是指针本身,即是地址,汇编表示即可为mov %ebp + 8, %eax,这里就是存储器——寄存器的操作方式。 mov (%eax),%eax 这里是取得指针指向的值,即*xp,(%eax)表示取%eax中的地址指向的值,比如 寄存器 值 地址 值 %eax 0x100 0x100 0xFF (%eax)的值就是0xFF了。 mov %eax,-0x4(%ebp) 这里是将值

13、赋给局部变量,局部变量是在ebp的上面的,表示其地址比ebp的地址要小。 mov 0x8(%ebp),%edx mov 0xc(%ebp),%eax mov %eax,(%edx) 这里与上面的分析类似,并没有出现局部变量,可以表明这里是函数参数在进行交换。这里的操作数方式是寄存器——存储器 mov -0x4(%ebp),%eax 通过寄存器eax将值返回,记住一般函数的返回值都是通过eax寄存器返回的。 0x080483dd : leave 0x080483de :

14、ret 函数返回 分析完反汇编代码之后有没有看出来函数调用是采用哪种调用约定呢?其实就是C调用方式(__cdecl)的方式。 //程序exchange.c,表示交换两个数。 #include #include int exchange(int *xp, int y) { int x = *xp; *xp = y; return (x); } int main() { int a = 4; int b = exchange(&a, 3); printf("a =

15、d, b = %d\n", a, b); return 0; } 通过上面的学习我们可以明白其实C语言中的指针本质上就是地址。抓住这一点我们对指针的理解就会更加明白。当然复杂的指针操作还是要在实践之中慢慢的掌握。 2、 算术和逻辑操作 加载有效地址(Load Effective Address)指令lea实际上是mov指令的变形,因为mov不能够直接对两个存储器操作数,,指令将有效地址写入到目的操作数(如寄存器)。举个例子: 如果寄存器%edx的值为x,那么指令lea 7(%edx, %edx, 4), %eax将设置寄存器%eax的值为5x+7,在

16、这里需要注意目的操作数必须是一个寄存器。 指令 效果 描述 leal S , D D ← &S 加载有效地址 incl D decl D negl D notl D D ← D + 1 D ← D-1 D ← -D D ← ~D 加 1 减 1 取负 取补 addl S , D subl S , D iImull S , D xorl S , D orl S , D and S , D D ← D + S D ← D - S D ←

17、D * S D ← D ^ S D ← D | S D ← D & S 加法 减法 乘法 异或 或 与 sall k , D shll k , D sarl k , D shrl k , D D ← D << k D ← D << k D ← D >> k D ← D >> k 算术左移 逻辑左移(等同于sal) 算术右移(符号位扩展) 逻辑右移 (0扩展) 图 3: 整数算术操作 注:后缀l表示对双字进行操作,还可以为w和b分别表示字和字节。 练习一下下面的移位操作指令 #inc

18、lude int shiftlr(int x, int n) { x <<= 2; x >>= n; return x; } int main() { int a = 4, b = 3; int ans = shiftlr(a, b); printf("%d\n", ans); return 0; } shiftlr函数反汇编代码: 0x080483c4 : push %ebp 0x080483c5 : mov %esp,%

19、ebp 0x080483c7 : shll $0x2,0x8(%ebp) 0x080483cb : mov 0xc(%ebp),%ecx 0x080483ce : sarl %cl,0x8(%ebp) 0x080483d1 : mov 0x8(%ebp),%eax 0x080483d4 : pop %ebp 0x080483d5 : ret 从上面的代码我们可以看到,移位量用单个字节编码,因为只允许进行0到31位

20、的移位。位移量可以是一个立即数,或者放在单字节寄存器元素%cl中。 指令 效果 描述 imull S mull S R[%edx] : R[%eax] ← S ×R[%eax] R[%edx] : R[%eax] ←S ×R[%eax] 有符号全64位乘法 无符号全64位乘法 cltd S R[%edx] :R[%eax] ←符号扩展(R[%eax] ) 转换为四字 Idivl S R[%edx] ← R[%edx] : R[%eax] mod S R[%edx] ← R[%edx

21、] : R[%eax] ÷ S 有符号除法 divl S R[%edx] ← R[%edx] R[%eax] mod S R[%edx] ← R[%edx] : R[%eax] ÷ S 无符号除法 图4:特殊的算术操作 给个例子和其相应的反汇编代码练习一下。 #include int main() { int a = 6, b = 3; unsigned int c = 10, d = 2; int ans1 = a / b; unsigned int ans2 = c * d;

22、 return 0; } 0x08048394 : lea 0x4(%esp),%ecx 0x08048398 : and $0xfffffff0,%esp 0x0804839b : pushl -0x4(%ecx) 0x0804839e : push %ebp 0x0804839f : mov %esp,%ebp 0x080483a1 : push %ecx 0x080483a2 : sub $0x28,%esp

23、0x080483a5 : movl $0x6,-0x8(%ebp) 0x080483ac : movl $0x3,-0xc(%ebp) 0x080483b3 : movl $0xa,-0x10(%ebp) 0x080483ba : movl $0x2,-0x14(%ebp) 0x080483c1 : mov -0x8(%ebp),%eax 0x080483c4 : mov %eax,-0x2c(%ebp) 0x080483c7 :

24、 mov -0x2c(%ebp),%edx 0x080483ca : mov %edx,%eax 0x080483cc : sar $0x1f,%edx 0x080483cf : idivl -0xc(%ebp) 0x080483d2 : mov %eax,-0x18(%ebp) 0x080483d5 : mov -0x10(%ebp),%eax 0x080483d8 : imul -0x14(%ebp),%eax 0x080483dc

25、: mov %eax,-0x1c(%ebp) 0x080483df : mov $0x0,%eax 0x080483e4 : add $0x28,%esp 0x080483e7 : pop %ecx 0x080483e8 : pop %ebp 0x080483e9 : lea -0x4(%ecx),%esp 0x080483ec : ret 2、 控制结构 CF:进位标志。最近的操作使最高位产生了进位,它

26、可用来检查无符号操作数的溢出。 ZF:零标志。最近的操作得出的结果为0。 SF:符号标志。最近的操作得到的结果为负数。 OF:溢出标志。最近的操作导致一个二进制补码溢出——正溢出或负溢出。 整型变量a、b和t,用add指令完成等价于C表达式 t = a + b的功能。会根据下面的表达式来设置条件码: CF:(unsigned t) < (unsigned a) 无符号溢出 ZF: (t == 0) 零 SF: (t < 0) 负数 OF: (a < 0 == b < 0) && (t < 0 != a < 0)

27、有符号溢出 lea指令不改变任何条件码,因为它是用来进行地址计算的。 指令 基于 描述 cmpb S2, S1 testb S2, S1 S1 – S2 S1 & S2 比较字节 测试字节 cmpw S2, S1 testw S2, S1 S1 – S2 S1 & S2 比较字 测试字 cmpl S2, S1 testl S2, S1 S1 – S2 S1 & S2 比较双字 测试双字 图 5: 比较指令 cmpb、cmpw、cmp

28、l指令根据它们的两个操作数之差来设置条件码。 testb、testw、testl指令会根据它们的两个操作数的与(AND)来设置零标志和负数标志。 指令 同义名 效果 设置条件 sete D setne D setz setnz D ← ZF D ← ~ZF 相等/零 不等/非零 sets D setns D D ← SF D ← ~SF 负数 非负数 setg D setge D setl D setle D setnle setnl setnge setng

29、 D ← ~(SF ^| OF) & ~ZF D ← ~(SF ^| OF) D ← SF ^| OF D ← (SF ^ OF) | ZF 大于(有符号 >) 大于等于(有符号 >=) 小于(有符号 <) 小于等于(有符号 <=) seta D setae D setb D setbe D setnbe segnb setnae setna D ← ~CF & ~ZF D ← ~CF D ← CF D ← CF | ZF 超过(无符号) 超过或相等(无符号 >=) 低于(无符号<) 低于或相等(无符号 <=)

30、 图 6: sett指令 每条指令根据条件码的某个组合,将一个字节设置为0或者1。有些指令有“同义名”,也就是,同一条机器指令有别的名字 结合上面的说明练习一下。 #include char ctest(int a, int b, int c) { char t1 = a < b; char t2 = b < (unsigned)a; char t3 = (short)c >= (short)a; char t4 = (char)a != (char)c; char t5 = c > b; ch

31、ar t6 = a > 0; int sum = t1 + t2 + t3 + t4 + t5 + t6; return sum; } int main() { int x = 5, y = 6, z = 7; int ans = ctest(x, y, z); printf("%d\n", ans); return 0; } (gdb) disas ctest 0x080483c4 : push %ebp 0x080483c5 : mov %esp,%ebp

32、 0x080483c7 : sub $0x10,%esp 0x080483ca : mov 0x8(%ebp),%eax 0x080483cd : cmp 0xc(%ebp),%eax 0x080483d0 : setl %al 0x080483d3 : mov %al,-0x1(%ebp) 0x080483d6 : mov 0xc(%ebp),%edx 0x080483d9 : mov

33、0x8(%ebp),%eax 0x080483dc : cmp %eax,%edx 0x080483de : setb %al 0x080483e1 : mov %al,-0x2(%ebp) 0x080483e4 : mov 0x10(%ebp),%eax 0x080483e7 : mov %eax,%edx 0x080483e9 : mov 0x8(%ebp),%eax 0x080483ec :

34、 cmp %ax,%dx 0x080483ef : setge %al 0x080483f2 : mov %al,-0x3(%ebp) 0x080483f5 : mov 0x8(%ebp),%eax 0x080483f8 : mov %eax,%edx 0x080483fa : mov 0x10(%ebp),%eax 0x080483fd : cmp %al,%dl 0x080483ff :

35、 setne %al 0x08048402 : mov %al,-0x4(%ebp) 0x08048405 : mov 0x10(%ebp),%eax 0x08048408 : cmp 0xc(%ebp),%eax 0x0804840b : setg %al 0x0804840e : mov %al,-0x5(%ebp) 0x08048411 : cmpl $0x0,0x8(%ebp) 0x08048415

36、est+81>: setg %al 0x08048418 : mov %al,-0x6(%ebp) 0x0804841b : movsbl -0x1(%ebp),%edx 0x0804841f : movsbl -0x2(%ebp),%eax 0x08048423 : add %eax,%edx 0x08048425 : movsbl -0x3(%ebp),%eax 0x08048429 : add %eax,%edx 0x0

37、804842b : movsbl -0x4(%ebp),%eax 0x0804842f : add %eax,%edx 0x08048431 : movsbl -0x5(%ebp),%eax 0x08048435 : add %eax,%edx 0x08048437 : movsbl -0x6(%ebp),%eax 0x0804843b : lea (%edx,%eax,1),%eax 0x0804843e :

38、 mov %eax,-0xc(%ebp) 0x08048441 : mov -0xc(%ebp),%eax 0x08048444 : leave 0x08048445 : ret 指令 同义名 跳转条件 描述 jmp Label jmp *Operand 1 1 直接跳转 间接跳转 je Label jne Label jz jnz ZF ~ZF 相等/零 不相等/非零 js Label jns Label SF ~S

39、F 负数 非负数 jg Label jge Label jl Label jle Label jnle jnl jnge jng ~(SF^OF) & ~ZF ~(SF^OF) SF^OF (SF^OF) | OF 大于(有符号 >) 大于或等于 (有符号 >=) 小于 (有符号 <) 小于或等于 (有符号 <=) ja Label jae Label jb Label jbe Label jnbe jnb jnae jna ~CF & ~ZF ~CF CF CF | ZF 超过 (无符

40、号 >) 超过或相等 (无符号 >=) 低于 (无符号 <) 低于或相等 (无符号 <=) 图 7: 条件跳转指令 jmp指令是无条件跳转,它可以是直接跳转,即跳转目标是作为指令的一部分编码的,也可以是间接跳转,即跳转目标是从寄存器或存储器位置中读出的。看下面的两条指令: jmp *%eax 用寄存器%eax中的值作为跳转目标。 jmp *(%eax) 以%eax中的值作为读地址,从存储器中读出跳转目标。 跳转指令有几种不同的编码,但是最常用的一些事PC相关的,也就是,它们会将目标指令的地址与紧跟在跳转指令后面那条指令的地址之间的差作为编码。这些地址偏

41、移量可以编码为一、二或四个字节。第二种编码方法是给出“绝对”地址,用四个字节直接指定目标。 下面给出具体的例子进行一些分析,动手实践是必须要的,在计算机这一块中编程能力还是第一位的,这个也关系到自己以后职业的定位和发展。大家勤加练习,我也正在努力中。 C中的if-else语句的通用形式是这样的: if (test-expr) thenstatement else else-statement 这里test-expr是一个整数表达式,它的取值为0(解释为“假”)或者为非0(解释为“真”),两个分支语句(then-statement和else-statement)只会执行一个

42、 #include #include using namespace std; int absdiff(int x, int y) { if (x < y) return y - x; else return x - y; } int main() { int m = 5, n = 6; int ans = 0; ans = absdiff(m, n); printf("%d\n", ans); return 0; }

43、 0x080485a4 <_Z7absdiffii+0>: push %ebp 0x080485a5 <_Z7absdiffii+1>: mov %esp,%ebp 0x080485a7 <_Z7absdiffii+3>: sub $0x4,%esp 0x080485aa <_Z7absdiffii+6>: mov 0x8(%ebp),%eax 0x080485ad <_Z7absdiffii+9>: cmp 0xc(%ebp),%eax 0x080485b0 <_Z7absdiffii+12>: jge 0x80485c1 <_Z7

44、absdiffii+29> 0x080485b2 <_Z7absdiffii+14>: mov 0x8(%ebp),%edx 0x080485b5 <_Z7absdiffii+17>: mov 0xc(%ebp),%eax 0x080485b8 <_Z7absdiffii+20>: mov %eax,%ecx 0x080485ba <_Z7absdiffii+22>: sub %edx,%ecx 0x080485bc <_Z7absdiffii+24>: mov %ecx,-0x4(%ebp) 0x080485bf <_Z7absdiffii+27>:

45、 jmp 0x80485ce <_Z7absdiffii+42> 0x080485c1 <_Z7absdiffii+29>: mov 0xc(%ebp),%edx 0x080485c4 <_Z7absdiffii+32>: mov 0x8(%ebp),%eax 0x080485c7 <_Z7absdiffii+35>: mov %eax,%ecx 0x080485c9 <_Z7absdiffii+37>: sub %edx,%ecx 0x080485cb <_Z7absdiffii+39>: mov %ecx,-0x4(%ebp) 0x08048

46、5ce <_Z7absdiffii+42>: mov -0x4(%ebp),%eax 0x080485d1 <_Z7absdiffii+45>: leave 0x080485d2 <_Z7absdiffii+46>: ret cmp 0xc(%ebp),%eax jge 0x80485c1 <_Z7absdiffii+29> mov 0x8(%ebp),%edx mov -0x4(%ebp),%eax 从上面的三句我们可以看出这里就是执行if条件语句了。也可以看出if条件语句反汇编后的一些特征,我们一般可以认为cmp+条件跳转指令

47、jmp跳转,就是if条件语句反汇编的代码。这对于我们在实际中分析代码需要快速识别一些特征反汇编代码很有帮助。也方便我们对于代码的整体结构有更好的认识,记住一些常用的特征代码结构是必要的,这些也可以从正面入手,再反面进行分析,从而可以提高快速分析汇编代码的能力。 mov 0x8(%ebp),%edx 取得x mov 0xc(%ebp),%eax 取得y mov %eax,%ecx 把y放入寄存器%ecx中 sub %edx,%ecx 得到x – y mov %ecx,-0x4(%ebp) mov -

48、0x4(%ebp),%eax 将结果放入%eax中返回 由于上面的跳转指令是jge即表示大于等于跳转,而if条件语句本身的比较是用<进行的,所以上面这段汇编代码是先进行else后面的语句体进行执行的。对代码进行分析即可以知道。另外一般函数的返回值都是用%eax寄存器返回的,看最后一句就可以知道了。 C语言提供了好几种循环结构,即while、for和do-while。汇编语言中并没有相应的指令存在,作为替代,将条件测试和跳转组合起来实现循环的效果。比较有趣的是,大多数汇编器根据一个循环的do-while形式来产生循环代码。 do-while循环 其通用形式是这样的:

49、 do body-statement while (test-expr); 循环的效果就是重复执行body-statement,对test-expr求值,如果求值的结果为非零,就继续循环。注意,body-statement至少执行一次。 看看下面举的例子来进行分析。 #include #include using namespace std; int fib_dw(int n) { int i = 0; int val = 0; int nval = 1; do { int t = val + nval; val = nval; nval = t; i++; } while ( i < n); return val; } int main() { int m = 5; int ans = 0; ans = fib_dw(m); printf("%d\n", ans); return 0; }

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服