Hu Zhenyu's Blog


访客计数:
net traffic statistics

about

在Windows下使用debug练习汇编编程

最近在学《微机原理》这门课,老师在课上讲了一大堆的汇编指令,听着脑袋都是晕的。如果能够实际的运行一下这些代码,或许对于理解这些指令有些帮助。有些同学可能也知道,使用C语言编程,需要一个编译器,不同平台的C语言都有不同的编译器,那么练习汇编的程序是不是也要去下载一个汇编器呢?确实,Windows平台下也有好几种汇编器:Borland公司的TASMMicrosoft公司的MASM,还有开源的NASM,不过,这些汇编器都有自带的一些伪指令和汇编程序的格式,如果一开始就使用他们,可能无法专注于汇编指令的学习,还要去学习怎么使用不同的汇编器。 其实,Windows平台下自带了一个简单的汇编器——debug。本来,debug是程序员用来除错的,不过,它也可以汇编一些简单的汇编指令。使用它可以完全不用考虑宏汇编的一些伪指令,专注于汇编指令的执行。

##debug的用法

debug是一个命令行程序,所以我们必须在命令提示符下使用,首先打开命令提示符(我一般使用运行命令输入cmd就可以了,你也可以进入开始菜单-附件-命令提示符 来运行它。)

命令提示符 (我以Windows XP为例,Win7 下面也是类似的) 输入 debug 回车 debug

这时,你可以看到一个以-开头的提示符,光标在这里闪,你可以输入一些 debug的命令了。

##常用的debug命令

  • ?
    直接敲入?号,可以查看debug的帮助,提供了一些可用命令的列表。
  • a addr
    a后面接地址,也就是说从地址addr处开始汇编一段小代码,如果不接地址,默认是汇编到 CS:0100这个地址,COM文件规定,必须从0100开始。
  • r reg
    显示单个寄存器或多个寄存器的内容,并提供修改的功能。例如:我输入r bx 就可以读出当前bx的内容,然后它会给一个:提示符,你可以输入新的值,或者是直接回车不修改内容。 如果reg为空则显示所有寄存器的内容和当前CS:IP地址处的汇编代码。
  • q
    退出,退出debug
  • u startaddr endaddr
    反汇编指令,反汇编从startaddr到 endaddr的代码。
  • g addr
    执行程序,后面可以加地址,就可以单步执行,如果没有接任何数,则是从 CS:IP 开始执行。

上面讲的是一些用的比较多的debug命令,更多的可以查找debug的帮助。

##开始用 debug 写汇编程序。

进入debug的提示符后,我们可以直接输入a命令,开始写我们的代码。

debug-a

从图中 可以看到 前面的数字就是你当前指令的地址CS:IP。 我们输入下面这段程序看看:

mov ah, 02
mov dl, 1
int 21h
int 20h

smile

运行结果如上图,打印出了一个笑脸。上面的代码是什么意思呢?下面 我一行一行的解释。

  1. mov ah, 02 将02 送到 ah,这里是为了调用后面的int 21的中断程序,02是DOS系统里面的打印函数的功能号,你只要知道这句是调用打印函数就可以了。
  2. mov dl, 1 将1 送到 dl寄存器,这个寄存器所存的数值将被打印出来。你将字符的ASCII码值送入dl,调用int 21h之后,这个字符就能打印出来了。 有一点要注意,debug里面的数字都是16进制的,但是在这里不要加h的后缀。
  3. int 21h 调用DOS系统的21号中断,这里的h后缀可加可不加。
  4. int 20h 返回DOS系统。这句在debug的环境里可加可不加。

下面,再来写一个打印出所有ASCII码的小程序,代码如下图:

ascii

大家可以自己运行看看结果。 我们还可以把它保存成一个.com的可执行文件。 首先使用debugname命令,将文件命名为ascii.com:(下面命令前面的短横代表debug里面的提示符,不必输入)

- n ascii.com

然后修改cx寄存器的值,这个寄存器里的值要修改为上面那个程序的大小,怎么看那个程序的大小呢? 看前面的地址,是从CS:0100CS:010F可知,程序的大小为FH 个字节,于是输入以下代码:

- r cx
: 0007

修改之后,使用w命令保存文件:

- w

执行后会显示Writing 0000F bytes 。在debug运行的目录下就会出现一个ascii.com文件,以后只要把它复制到其他地方执行,就能打印出所有ASCII码值了。

使用debug 练习书上的示例指令

下面用一个指令的示例来讲讲如果使用debug 练习这个指令。
交换指令 XCHG dest, src
交换指令可以实现字节的交换,也可以实现字的交换。代码实例如下:

- a
0ADC:0100  mov ax, 52
0ADC:0103  mov bx, 41
0ADC:0106  xchg ax, bx
0ADC:0108

接下 我们可以使用debug的r读取 ax和 bx的值

- r ax 
AX 0000
:
- r bx
BX 0000
:

接着使用g 单步运行:

- g 100
- g 103
- g 106
- g 108

单步运行过程中会打印出所有寄存器的值,你可以发现寄存器值的变化。

##写在最后

看了上面的之后,我相信你应该能使用debug练习各个8086汇编指令的运行,观察各种指令运行后的结果了。注意的是,debug里面只能直接执行8086的指令,无法使用宏汇编、伪代码。而且也只支持写一些简单的.com文件,学到后面还是要使用各种宏汇编器(比如MASMNASM .etc)。使用宏汇编器则需要了解那个汇编器特有的语法,如果定义段,如何定义宏,什么的。这些不同的汇编器都有不同的规定,而8086指令都是一样的(如果你是用Intel的语法,实际上在Linux系统中,8086经常使用一种AT&T的语法,与Intel的稍有不同)。

上一篇: ARM体系下的GCC内联汇编
下一篇: g-bios 一个中国人写的bootloader


知识共享许可协议

本站采用 知识共享署名-非商业性使用-相同方式共享3.0 中国大陆许可协议 进行许可,转载请注明出处。

推荐使用 chrome 浏览器浏览本站。