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;还是需要…

九年级数学解方程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;对于高频信号在面包板…

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

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

排序千万级数据_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引…

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

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

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;可以对逻辑代码进行抽离…

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

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

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

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

uinty粒子系统子物体变大_Unity的粒子系统(一)基础篇

简介闲来无事&#xff0c;仔细的学习一下粒子系统&#xff0c;也当是给自己做个笔记方便之后进行回顾。引擎版本&#xff1a;Unity2018.3创建一个ParticleSystem创建方式&#xff1a;1、Hierarchy-->Effects-->ParticleSystem第一种创建方式创建结果2、gameObject-->A…

java定义返回码常量_码出规范(四)常量定义

01各位屏幕前的读者朋友大家早上中午晚上凌晨好&#xff0c;本文是《码出规范》专题的第四篇&#xff0c;文中参考阿里巴巴最新发布的《Java开发手册》&#xff0c;结合《springboot2.x独门秘籍》专题中的项目开发进度&#xff0c;学以致用&#xff0c;让你在开发中码出高效&am…

centos下载mysql_python数据分析之路——centos下载并配置mysql与navicat的使用

python数据分析之路——centos下载并配置mysql与navicat的使用在之前的文章中已经说明了如何购买并配置一台自己的服务器&#xff0c;那么在安装完anaconda之后&#xff0c;为了之后方便用Django进行网站开发与数据分析&#xff0c;需要对数据库进行配置&#xff0c;那么在数据…

mysql 解压缩安装_[mysql] MySQL解压缩安装步骤

以前装的MySQL出问题了&#xff0c;只好卸载了。又下载了一个mysql-5.6.24-win32.1432006610.zip。msi文件直接安装就行了。这里需要解压到指定目录&#xff0c;配置后可使用。环境变量配置&#xff1a;在 mysql根目录下修改 my-default.ini :# These are commonly set, remove…

mysql数据库如何创建表_mysql数据库如何创建数据表

mysql数据库创建数据表的方法是&#xff1a;可以通过CREATE TABLE语句来创建&#xff0c;基本语法&#xff1a;【CREATE TABLE ([表定义选项])[表选项][分区选项];】。要注意的是&#xff0c;创建数据表不能使用SQL语言中的关键字。在 MySQL 中&#xff0c;可以使用 CREATE TAB…

mysql 主从一致性_mysql 主从一致性保证

MySQL 主备的基本原理MySQL 主备切换流程.png主备同步流程图备库 B 跟主库 A 之间维持了一个长连接。主库 A 内部有一个线程&#xff0c;专门用于服务备库 B 的这个长连接。一个事务日志同步的完整过程是这样的&#xff1a;在备库 B 上通过 change master 命令&#xff0c;设置…

php study是什么,phpstudy与wamp区别的区别是什么?

phpstudyphpstudy是一个php运行环境的集成包&#xff0c;用户不需要去配置运行环境&#xff0c;就可以使用&#xff0c;phpstudy不仅是一款比较好用的php调试环境工具&#xff0c;并且还包括了开发工具和常用手册&#xff0c;对于新手是有很大帮助的。phpstudy集成最新的Apache…