乐趣区

关于后端:手把手教你汇编-Debug

对于汇编的第一篇文章:
爱了爱了,这篇寄存器讲的有点意思

Hello 大家好,我是程序员 cxuan!咱们上篇文章理解了一下根本的寄存器,这篇文章咱们来进行实际操作一下。

原文链接:手把手教你汇编 Debug

咱们当前将会用到很多 Debug 命令,这里咱们先来相熟一下它们。

Debug 是什么

Debug 是 Windows / Dos 操作系统提供的一种性能。应用 Debug 能让咱们不便查看 CPU 各种寄存器的值、内存状况,不便咱们调试指令、跟踪程序的运行过程。

接下来咱们会用到很多 debug 命令,然而应用这些命令的前提是,你须要在电脑上装置一下 debug,Windows/Mac 都能够装置,获取链接我曾经给你找进去了。阿,遗记说了,咱们这里应用的是 Dos box来模仿汇编的操作环境。

传送门(Mac 和 Windows 都是):https://www.dosbox.com/downlo…

下载实现后关上 DosBox,关上之后是这样的。

此时咱们输出 debug 命令应该提醒的是

因为咱们还没有进行连贯和挂载,此时咱们执行

mount c D:\debug

执行这条命令时,你须要当初 D 盘下创立一个 debug 文件夹,而后咱们挂载到 debug 上面。

并且执行 C: 切换到 C 盘门路下。

此时咱们就能够执行 debug 命令了。

这里须要留神一点,我在 Windows 10 零碎下搭建 Debug 环境时,在挂载实现后输出 debug,还是提醒 Illegal command:debug,此时你须要再下载一个 debug.exe,贴心的我也把下载地址给你了。

下载地址:https://pan.baidu.com/s/177ar… 明码:3akd

须要下载外面的 debug.exe,而后把它放在你挂载的门路下,这里我挂载的门路时 D 盘下的 debug 文件夹。

搁置实现之后,再输出 debug 就能够了。


因为每次关上 Dosbox 都会执行下面这些命令,真的好烦,那怎么办呢?一个简略的方法是在 Dosbox 装置门路下找到

关上之后,在开端键入

就 OK 了,下次间接关上 Dosbox,会默认执行这三条命令,至此,就是我搭建 Dosbox 遇到的所有问题了。

Debug 实战

玩儿汇编得学会用 Debug,Debug 是一种 调试程序 ,通过 Debug 能让咱们可能看到内存值,跟踪堆栈状况,看到寄存器所暂存的内容等,同时也可能更好地帮忙咱们了解汇编代码,所以学会 Debug, 十分重要,这是一种不可或缺的入手能力。

上面咱们会用到几种 Debug 命令,这里先简略介绍下。

<img src=”https://tva1.sinaimg.cn/large/008i3skNly1gwiil6fj2qj31040rm76a.jpg” alt=”image-20211117222634775″ style=”zoom:50%;” />

Debug 命令有很多,不过罕用的个别就下面这几个。

好了,当初咱们间接进入正题,开始在 Dosbox 上正式进行 Debug 操作,首先关上 Dosbox。

嗯。。。。。。这个界面咱们关上很屡次了。

那我写个命令呢?好吧,没演示过,上面就来了!

Debug -r

亲,用 Debug -r 就能够查看和批改 CPU 寄存器内容了呢。

<img src=”https://tva1.sinaimg.cn/large/008i3skNly1gwij6myjunj30b30ayt99.jpg” alt=”image-20211117224711832″ style=”zoom:67%;” />

查看寄存器内容。

这里须要留神一下 -r 大小写的问题,Debug -r 是查看寄存器内容。而 -R 则是有效指令。

上图列进去了很多寄存器,你可能感觉无从下手,不要乱,咱们先从最根本的开始动手,也就是 CS 和 IP,CS(Code Segment)是代码段寄存器,个别也被称为段基址,能够认为是程序拜访的入口,CPU 须要从 CS 中找到从哪个地位开始取指执行,然而咱们还不晓得要取哪一段,这时候 IP 的作用就体现进去了,IP(Instruction Pointer)就是指令指针寄存器,也叫做偏移地址,它会通知咱们从段基址开始,取哪一段的地址。

能够应用段基址: 偏移地址来确定内存中的指定地址。

这里咱们只是简略聊一下这两个寄存器的概念,要理解这两个寄存器的具体作用,能够看笔者的上一篇文章

应用 -r 也可能批改寄存器的内容,如下所示

-r 个别的格局是 -r 寄存器,而后零碎会进行冒号提醒,前面就是你要批改的内容。

Debug -d

应用 -d 指令能够查看内存中的内容。

输入的内存值默认是依照 CS:IP 的地址开始的,因为 CS 的值默认是 073F,而 IP 默认是 0100,所以 -d 的内存值是 073F:0100。

-d 的格局很多,上面只介绍一下罕用的几种格局。

形似 -d 1000:0 这种 -d 段基址 偏移地址 的格局能够产生如下输入。

如上图所示,Debug 会列出指定内存单元中的的内容。上图中的每一个 00 都示意 8 位,如果是 4A,那么这八位开展来说就是 0010 1011。每一行有 16 个 8 位,所以形成了 128 位内存地址。

为什么都是 00 呢,因为内存单元的值没有被改写,说白了就是这块内存区域没有存值,如何改写咱们前面回收。

每一行的两头都有一个 -,这个是为了便于咱们浏览来设置的,- 号前后都有 8 个内存单元,这样便于查看。

右侧几个 …… 示意每个内存单元可显示的 ASCII 码字符,因为内存没有值,所以也没有对应的 ASCII 码。咱们能够数一下,每行有 16 个 .,这示意每一个 00 都对应了一个 ASCII 码。

咱们能够应用 -d 1000:9 这种 -d 段基址: 起始偏移地址 格局来显示从 1000 的第几位开始。

Debug 从 1000:9 开始,始终到 1000:88,一共是 128 个字节,第一行中的 1000:0 ~ 1000:8 中的内容没有显示。

还能够应用 -d 1000:0 9 这种 -d 段基址: 起始偏移地址 结尾偏移地址 的格局来输入。

还能够是应用 -d 偏移地址来在不指定段基址的状况下,查看内存值。

Debug -e

下面说的都是查看内存中指定地位或者区域的值,上面咱们要来改写一下内存值。

应用 -e 能够改写内存值,比方咱们想要改写 1000:0 ~ 1000:f 中的内容,能够应用 -e 1000:0 0 1 2 3 4 5 6 7 8 9 0 a b c d e f 这种形式,如下图所示。

这里须要留神下,在进行 -e 改写的时候,每个值两头都有一个空格,如果没有空格的话,会当做一个内存值来对待。

而后用 -d 1000:0 看到咱们刚改写的内存值。

还能够应用发问的形式来一一批改从某一地址开始的内存单元的内容。

还是用 1000:100 来举例子,输入 -e 1000:100 后按下回车键。

如上图所示,能够看到咱们先输出了一次 -e 1000:100 这个指令,而后按下了回车键。

留神,如果这里你按下了回车键,就相当于整个 -e 改写的过程曾经实现。

如果你想要持续改写前面内存中的值,你须要按下空格键。

咱们改写了 1000:100 之后的内存值,而后应用 -d 1000:100 查看咱们改写的内容是否失效。

-e 命令还能够反对写入字符,比方咱们能够向 1000:0 这个地位开始写入数值和字符,-e 1000:0 1 ‘a’ 2 ‘b’ e ‘c’。

如上图所示,当咱们向内存写入字符 ‘a’ ‘b’ ‘c’ 的时候,会主动转换为 ASCII 码进行存储,在最右侧能够找到刚刚写入的字符。

Debug -u

如何向内存中写入一段机器码呢?比方咱们想要在内存中写入一段机器码。

咱们能够应用 -e 来进行写入,向内存中写入 b8 01 00 b9 02 00 01 c8 这个机器码,如下所示

咱们应用 -e 写入之后,应用 -d 查看内存值,能够发现咱们刚刚写入的值,然而却看不到机器码,所以机器码该如何看呢?

别急,还有个 -u 命令,这个就是看机器码的,如下图所示,咱们应用 -u 命令显示咱们写入的机器码。

能够看到 1000:0000 ~ 1000:0006 这个内存地址使咱们写入的机器码,-u 这个命令就是将内存单元的内容翻译为汇编指令并显示。

-u 输入的后果分为三局部显示:

  • 最左侧是每一条机器指令的地址;
  • 两头是机器指令;
  • 最右侧是机器指令执行的汇编指令。

1000:0 处寄存的是写入的机器码 B8 01 00 组成的机器指令,对应的汇编指令是 MOV AX,0001。

1000:0003 处寄存的是写入的机器码 B9 02 00 组成的机器指令,对应的汇编指令是 MOV CX,0002。

1000:0006 处寄存的是写入的机器码 C1 C8 所组成的机器指令,对应的汇编指令是 add ax,cx。

Debug -t

下面介绍的一系列指令包含咱们下面提到的 Debug -e 机器码都是向内存中进行写入,那么如何执行这些指令呢?

咱们能够应用 Debug -t 来执行写入的指令。应用 Debug -t 能够执行由 CS:IP 指向的指令。

既然是 -t 可能执行从 CS:IP 指向的命令,所以咱们有必要将 CS:IP 指向 1000:0(因为咱们后面将指令写在了 1000:0 处)。

首先咱们须要执行 -r cs 1000,-r ip 0 把 CS:IP 赋值为 1000:0。

而后执行 -t 指令,下图是曾经执行过的指令截图。

能够看到,执行完 -t 指令之后,MOV AX,0001 这条指令被执行,以后 AX 寄存器的内容变为了 0001,这条汇编指令的意思就是把 0001 挪动到 AX 寄存器中。

继续执行 -t 之后,咱们能够看到寄存器的变动。

Debug -a

毕竟机器指令不是那么好懂,写入很不不便,所以有没有方法可能反对咱们间接写入汇编指令呢?还真有,Debug 提供了 -a 这种形式来实现汇编指令的写入。如下图所示

能够看到,咱们应用了 -a 命令来对 1000:0 进行写入,别离输出 mov ax,1 mov bx,2 mov cx,3 add ax,bx add ax,cx add ax,ax 指令,而后按回车进行确定执行。

咱们应用 -d 1000:0 f 能够看到从偏移地址 0 处开始的第 f 个内存指令(因为最大写入的地址只是 f)。

上图中的 1000:000F 为什么有值呢,因为咱们下面曾经执行过这个写入了。

另外,应用 -a 能够从一个预设的地址处开始输出指令。

总结

明天和大家聊了一下 Debug 的根本用法,次要包含

  • -r 查看、批改寄存器中的内容
  • -d 查看内存中的指令
  • -e 批改内存中的内容
  • -u 能够将内存中的内容解释为机器指令和对应的汇编指令
  • -t 执行 CS:IP 处的指令
  • -a 以汇编得模式向内存写入内容

汇编指令的选项有很多,下面介绍的这些属于常常用到的指令,这些指令要可能纯熟应用。

最初给大家举荐一下我本人的 Github,外面有十分多的硬核文章,相对会对你有帮忙。

退出移动版