gdb tui 安装_GDB 单步调试汇编

之前在看汇编的时候一直是肉眼看GCC -S的结果,缺点是很不直观,无法实时的看到寄存器的值,所以研究了下如何用GDB调试汇编。当然,写这篇文章更重要的一个目的是半年没有写博客了,博客要长草了。^_^

调试汇编的需求有几点:

  • 能够单步进行汇编调试。
  • 能够实时看到寄存器值的变化。
  • 能够看到源代码和对应汇编的关系。

下面分享下用GDB实现上面的3点需求:

单步进行汇编调试

使用si和ni。与s与n的区别在于:s与n是C语言级别的单步调试,si与ni是汇编级别的单步调试。

能够实时看到寄存器值的变化。

使用gdb时增加-tui选项,打开gdb后运行layout regs命令。注意最好加上-tui,否则很大可能会出现花屏现象。

6a66046586311bdf250bb3c0fba51cc6.png

能够看到源代码和对应汇编的关系

在gdb中运行set disassemble-next-line on,表示自动反汇编后面要执行的代码。

e2890e3497ccf4d3325feb675dad52d7.png

可以清晰的看出int c=sum(x,y);与下面红框内的汇编指令成对应关系。

如果大家不想用这么原始的方式,可以给GDB安装插件或者使用emacs达到上面的目的,推荐两篇文章:

  • GDB 从裸奔到穿戴整齐
  • GDB实用插件(peda, gef, gdbinit)全解

最后以一个小例子结束:

int sum(int x,int y){return x+y;
}int main(){int x=10;int y=20;int c=sum(x,y);return 0;
}

gcc版本4.4.7,默认的优化选项。

我们单步调试下这段代码对应的汇编:

设置断点

注意如果想要把断点设置在汇编指令层次函数的开头,应该使用b *fun而不是b func,这里我们把断点设置在b *main

分配栈帧

0x0000000000400489 <main+0>:	 55	push   %rbp
0x000000000040048a <main+1>:	 48 89 e5	mov    %rsp,%rbp
0x000000000040048d <main+4>:	 48 83 ec 10	sub    $0x10,%rsp

%rbp和%rsp表示的是当前栈帧的栈底和栈顶。其中%rbp是被调用者需要保存的寄存器。sub $0x10,%rsp表示为main函数分配栈帧空间。
注意这里分配了16字节的栈空间,会有4字节用不上,我个人猜测跟gcc汇编产生的cfi_def_cfa_offset 16有关,这个没有深究。

int x=10

0x0000000000400491 <main+8>:	 c7 45 f4 0a 00	00 00	movl   $0xa,-0xc(%rbp)

将x的值放到栈中

int y=20

0x0000000000400498 <main+15>:         c7 45 f8 14 00	00 00	movl   $0x14,-0x8(%rbp)

将y的值放到栈中

sum函数调用

0x000000000040049f <main+22>:         8b 55 f8	mov    -0x8(%rbp),%edx0x00000000004004a2 <main+25>:         8b 45 f4	mov    -0xc(%rbp),%eax0x00000000004004a5 <main+28>:         89 d6	mov    %edx,%esi0x00000000004004a7 <main+30>:         89 c7	mov    %eax,%edi0x00000000004004a9 <main+32>:         e8 c6 ff ff ff	callq  0x400474	<sum>

将x与y分别赋值到%esi和%edi中,其中%edi和%esi被规定用来传递函数的第一个和第二个参数。(一个疑问是为什么不能直接mov -0x8(%rbp),%esi呢?)
callq会将下一条指令的地址压入栈中,并跳到sum函数的第一条指令。

进入sum函数

0x0000000000400474 <sum+0>:	 55	push   %rbp
0x0000000000400475 <sum+1>:	 48 89 e5	mov    %rsp,%rbp
0x0000000000400478 <sum+4>:	 89 7d fc	mov    %edi,-0x4(%rbp)
0x000000000040047b <sum+7>:	 89 75 f8	mov    %esi,-0x8(%rbp)

同main函数一样,首先将%rbp保存,然后从%edi和%esi中取出函数参数。

求和

0x000000000040047e <sum+10>:	 8b 45 f8	mov    -0x8(%rbp),%eax
0x0000000000400481 <sum+13>:	 8b 55 fc	mov    -0x4(%rbp),%edx
0x0000000000400484 <sum+16>:	 8d 04 02	lea    (%rdx,%rax,1),%eax

将x和y相加,这里用到的是lea指令,关于lea指令介绍参考LEA instruction? ,这里不赘述了。
将返回值放到%eax中,%rax寄存器规定存放函数的返回值。像GO语言如果函数可以有多个返回值的话,返回值是放到栈中。

sum函数收尾

0x0000000000400487 <sum+19>:	 c9	leaveq
0x0000000000400488 <sum+20>:	 c3	retq

我们先看下现在的栈:

b98b318ca85a57e9e756abc6d9ae07ab.png


(这里不知道为什么没有sub xx,$rsp,我猜测是gcc发现这个最后一次函数调用,之后不会有栈的增长只会有栈的回退,所以用%rsp和%rbp的结果是一样的。简单验证了下,应该是这样)。
在函数结束时首先需要回收当前函数的栈帧、恢复保存过的寄存器、恢复%rip的值,即返回地址。

leaveq指令相当于:

mov  %rbp,%rsp     
pop %rbp

作用是释放(deallocate)当前函数的栈帧并恢复被保存的寄存器的值。由此我们也可以看出%rbp的作用:记住%rsp应该回退的位置,否则函数结束时%rsp不知道该回退到哪。

retq指令相当于:

pop %rip

将上面保存过的callq的下一条指令地址恢复到%rip中。

接收函数返回值

0x00000000004004ae <main+37>:         89 45 fc	mov    %eax,-0x4(%rbp)

将%eax的值放入到main函数的栈帧中。

return 0

0x00000000004004b1 <main+40>:         b8 00 00 00 00	mov    $0x0,%eax

同上面sum函数一样。

main函数收尾

0x00000000004004b6 <main+45>:         c9	leaveq
0x00000000004004b7 <main+46>:         c3	retq

如果上面%rsp和%rbp指向同一内存区域看起来不太直观的话,看下现在main函数即将结束时的栈空间:

a8ba652d633244dc16cf5f0a89583c3b.png

同上面sum函数的解释一样,不再赘述。

程序运行成功退出。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/563323.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java中的异常处理语句_Java中实现异常处理的基础知识

Java中实现异常处理的基础知识异常 (Exception)&#xff1a;发生于程序执行期间&#xff0c;表明出现了一个非法的运行状况。许多JDK中的方法在检测到非法情况时&#xff0c;都会抛出一个异常对象。例如&#xff1a;数组越界和被0除。源代码示例&#xff1a;packageyanzheng;//…

改变numpy的大小_Numpy入门详细教程

序言&#xff1a;python数据科学基础库主要是三剑客&#xff1a;numpy&#xff0c;pandas以及matplotlib&#xff0c;每个库都集成了大量的方法接口&#xff0c;配合使用功能强大。平时虽然一直在用&#xff0c;也看过很多教程&#xff0c;但纸上得来终觉浅&#xff0c;还是需要…

java消息失败重发_JMS消息在JMS侦听器中重新发送异常

Javadoc为 org.springframework.jms.listener.AbstractMessageListenerContainer 表示&#xff0c;如果“sessionAcknowledgeMode”设置为“CLIENT_ACKNOWLEDGE”&#xff1a;成功侦听器执行后自动确认消息;如果抛出异常&#xff0c;则无法重新发送 .我猜&#xff0c;“在抛出异…

九年级数学解方程50道_初中数学公式中考知识点总结,初三数学上册,九年级数学上册...

初中数学公式中考知识点总结&#xff0c;初三数学上册&#xff0c;九年级数学上册第二十一章 一元二次方程知识点&#xff1a;一元二次方程的解法1、直接开平方法利用平方根的定义直接开平方求一元二次方程的解的方法叫做直接开平方法&#xff0c;2、配方法配方法是一种重要的数…

java时间规划书_【计算机本科补全计划】Java学习笔记(九) Java日期时间

正文之前终于好像仿佛看完了菜鸟教程的Java课程&#xff0c;感觉自己收获颇丰&#xff01;很好&#xff0c;Java看完之后正愁如何开始进阶呢&#xff01;结果发现菜鸟还准备了Java实例这种好东西&#xff01;简直就是教程界的良心啊 &#xff01;&#xff01;&#xff01;没事&…

与40mhz信道不兼容设置_为什么面包板不适合高频电路

01为什么在面包板上玩射频&#xff1f;方便&#xff0c;当然还是方便。面包板是进行一些电子线路实验构建电路方便的平台。多用于普通数字电路和模拟电路。一旦涉及到高频电路&#xff0c;面面包就有很多方面不太适合了。那么到底哪方面不适合&#xff1f;对于高频信号在面包板…

mysql 主表存hash和子表的名字_【mysql】mysql分表和表分区详解

为什么要分表和分区&#xff1f;日常开发中我们经常会遇到大表的情况&#xff0c;所谓的大表是指存储了百万级乃至千万级条记录的表。这样的表过于庞大&#xff0c;导致数据库在查询和插入的时候耗时太长&#xff0c;性能低下&#xff0c;如果涉及联合查询的情况&#xff0c;性…

加载gif_搞笑gif:这啥情况啊?笑容加载不出来了?

这无故的小眼神&#xff0c;我也很无奈呀。。。猫和狗对峙&#xff0c;气势上一定不能输几个菜呀&#xff0c;喝成这样&#xff01;这啥情况啊&#xff1f;笑容加载不出来了&#xff1f;高手在民间&#xff01;小青年瞬间变老头&#xff01;丈母娘来家了&#xff0c;说下班就能…

马匹赛跑java_java模拟龟兔赛跑

通过使用 java 中 Jlabel,Jbutton,JtextArea,JcomboBox 等 swing 组件来实现图形用户界面,同 时通过设置布局,背景,字体等来丰富界面,最大程度的模拟龟兔赛跑的场景......2、模拟龟兔赛跑 要求: 用图形用户界面实现。 能设置比赛时间,马匹的数量等等。...3、2 目标与总体方案(1…

排序千万级数据_MySQL 对于千万级的大表要怎么优化?我写了6000字的深度解读...

千万级大表如何优化&#xff0c;这是一个很有技术含量的问题&#xff0c;通常我们的直觉思维都会跳转到拆分或者数据分区&#xff0c;在此我想做一些补充和梳理&#xff0c;想和大家做一些这方面的经验总结&#xff0c;也欢迎大家提出建议。从一开始脑海里开始也是火光四现&…

java读取rvt文件数据_Revit二次开发之隐藏API 独立进程读取rvt文件

在项目中需要读取rvt文件&#xff0c;但是因为该格式为非公开格式&#xff0c;其数据需要revit的支持&#xff0c;但批量读取不可能一个一个用revit软件去打开。不过该方法还是需要revit的依赖&#xff0c;速度比开软件快了知道多少1.1. 新建一个控制台项目1.2. 添加Revit API引…

vscode自动加前缀_详解VScode自动补全CSS3前缀插件以及配置无效的解决办法

1.在vscode中搜索Autoprofixer2.在安装完成之后要配置在需要添加前缀的css文件上&#xff0c;右键点击命令面板&#xff0c;输入Autoprefixer CSS就好啦ps: 如果想要兼容性最好的话&#xff0c;需要在设置配置文件setting.json里加上(打开设置->搜索autoprefixer->点击在…

java类快速构造_程序员有什么办法能快速梳理java知识点?有这八张图就够了

一图胜千言&#xff0c;下面图解均来自Program Creek 网站的Java教程&#xff0c;目前它们拥有最多的票选。如果图解没有阐明问题&#xff0c;那么你可以借助它的标题来一窥究竟。1、字符串不变性下面这张图展示了这段代码做了什么String s "abcd";s s.concat(&quo…

php数组foreach循环添加键值对_循环 - PHP二维数组根据键值对获取一组数组 (不使用foreach)...

问 题$user array(0 > array(id > 1,name > 张三,email > zhangsansina.com,),1 > array(id > 2,name > 李四,email > lisi163.com,),2 > array(id > 5,name > 王五,email > 10000qq.com,),......);比如我想获取当id2时,该数组的全部内容…

uos配置 java 环境变量_CentOS 7.3 环境配置java和tomcat开机启动

Centos7下添加开机自启动服务和脚本 https://blog.csdn.net/GMingZhou/article/details/78677953安装部分参考我的博文&#xff0c;仅参考他的开机启动部分CentOS 7环境配置tomcat7开机启动 https://blog.csdn.net/tiantang_1986/article/details/537049661.安装 jdk-8u5-lin…

react全局方法_前端面试题 ---react

高阶组件相关什么是高阶组件&#xff0c;它有哪些运用&#xff1f;高阶组件就是一个函数&#xff0c;接收一个组件&#xff0c;经过处理后返回后的新的组件&#xff1b;高阶组件&#xff0c;不是真正意义上的组件&#xff0c;其实是一种模式&#xff1b;可以对逻辑代码进行抽离…

java数据库表不存在_如果Java生产代码中不存在并在JUnit中确认,则创建数据库表...

Code-Apprentice2javasqljunitjdbc我正在用Java编写数据库程序,并且想要创建一个表(如果它还不存在).我从中了解DatabaseMetaData.getTables()了如何在Java中检测SQL表的存在&#xff1f;而我正在尝试使用它:private boolean tableExists() throws SQLException {System.out.pr…

get方法请求返回一个文件_一键转换多种文件格式,完全免费,总有一个方法适合你...

相信各位小伙伴平时办公的时候&#xff0c;肯定经常需要对多种文件格式进行转换&#xff0c;但是下面这些非常好用的转换方法&#xff0c;你用过吗&#xff1f;接下来就带各位一探究竟&#xff0c;希望可以帮到你哦&#xff01;一、迅捷PDF转换器在线版1、文档转换首先我们可以…

java 堆排序方式_幾種排序方式的java實現(02:希爾排序,歸並排序,堆排序)

/** 希爾排序&#xff1a;先取一個小於n的整數d1作為第一個增量&#xff0c;* 把文件的全部記錄分成(n除以d1)個組。所有距離為d1的倍數的記錄放在同一個組中。* 先在各組內進行直接插入排序&#xff1b;然后&#xff0c;取第二個增量d2* 直至所取的增量dt1(dtpublic classShel…

jacoco入门_Android jacoco 代码覆盖率测试入门

前言最近同事搞了一个基于 jacoco 统计 Android 代码覆盖率测试的功能,可以统计每天手工测试的代码覆盖率.抱着好奇的心态,自己也学习一下 jacoco,陆陆续续搞了三天终于有点结果了.本文介绍仅仅在源码中加入少量代码就可以完成代码覆盖率覆测试.代码配置build.gradle在 app 目录…