《汇编语言》第2章 寄存器——实验1 查看CPU和内存,用机器指令和汇编 指令编程

本篇介绍第2章的实验1 查看CPU和内存,用机器指令和汇编 指令编程 实验环境Window10 + DOSBox 0.74

1、实验工具

DOSBox是window环境下模拟DOS环境的软件,这里用来在DOS环境下调试学习汇编指令,其中debug是一个功能强大的调试工具,使用它可以查看CPU各种寄存器中的内容,内存的情况和在机器码级跟踪程序的运行。

2.debug的功能。

Debug的命令有很多,共有20多个,以下这6个命令是和汇编学习密切相关的。

⑴ 用Debug的R命令查看、看变CPU寄存器的内容
⑵ 用Debug的D命令查看内存中的内容;
⑶ 用Debug的E命令改写内存中的内容
⑷ 用Debug的U命令将内存中的机器指令翻译成汇编指令
⑸ 用Debug的T命令执行一条机器指令;
⑹ 用Debug的A命令以汇编指令的格式在内存中写入一条机器指令。

3、进入Debug实验环境

安装好DOSBox,双击桌面图标,弹出命令行窗口,如下所以

挂载到d盘的debug目录 mount c: d:\debug

然后输入命令c: 

输入debug进入汇编模式

(4)用R命令查看、改变CPU寄存器的内容。
我们已经知道了AX、BX、CX、DX、CS、IP这6个寄存器,现在看一下它们之中的内容,如图2.31所示。其他寄存器如SP、BP、SI、DI、DS、ES、SS、标志寄存器等我们先不理会。

注意CS和IP的值,CS=073F,IP=0100,也就是说,内存073F:0100处的指令为CPU当前要读取、执行的指令。在所有寄存器的下方,Debug还列出了CS:IP所指向的内存单元处所存放的机器码,并将它翻译为汇编指令。可以看到,CS:IP所指向的内存单元为073F:0100,此处存放的机器码为00 00,对应的汇编指令为ADD [BX+SI],AL(这条指令的含义我们还不知道,先不必深究。)
Debug输出的右下角还有一个信息:"DS:0000=CD",我们以后会进行说明。

还可以用r命令来改变寄存器中的内容,如图2.32所示

 若要修改一个寄存器中的值,比如AX中的值,可用r命令后加寄存器名来进行,输入"r ax"后按Enter键,将出现“”作为输入提示,在后面输入要写入的数据后按Enter键,即完成了对AX中内容的修改,若想看一下修改的结果,可再用R命令查看,如图2.32所示。

 在图2.33中,一进入debug,用r命令查看,CS:IP指向073F:0100,此处存放的机器码为0000, 对应的汇编指令是ADD [BX+SI], AL;
接着,用r命令将CS修改为0200, CS:IP指向0200:0100,此处存放的机器码为59,对应的汇编指令
POP CX
接着用r命令将IP修改为0101,则CS:IP指向0200:0101,此处存放的机器码为3BD9,对应的汇编指令是CMP BX,CX

(5)用Debug的D命令查看内存中的内容
用Debug的d命令,可以查看内存中的内容,d命令的格式较多,这里只介绍在本次实验中用的到的格式。如果我们想知道内存2000H处的内容,可以用“d 段地址:偏移地址”的格式来查睦,如图2.34所示。

 要查看内存2000H处的内容,首先将这个地址表示为段地址:偏移地址的格式,可以是0200:0,然后用
d 0200:0”列出0200:0处的内容。
使用"d 段地址:偏移地址"的格式,debug将列出从指定内存单元开始的128个内存单元的内容。图2.34中,在使用
d 0200:0后,debug列出了0200:0~0200:7F中的内容。
使用d命令,debug将输出3部分内容(如图2.34所示)。
⑴ 左边是每行的起始地址。
⑵ 中间是从指定地址开始的128个内存单元的内容,用十六进制的格式输出,每行的输出从16的整数倍的地址开始,最多输出16个单元的内容。从图中,我们可以知道,内存0200:0单元中的内容是17H,内存0200:1单元中的内容是FEH,内存0200:0~0200:F中的内容都在第一行;内存0200:10中的内容是ADH,内存0200:11中的内容是8BH,内存0200:10~0200:1F中的内容都在第二行。注意在每行的中间有一个"-",它将每行的输出分为两部分,这样便于查看。比如,要想从图中找出0200:6B单元中内容,可以从0200:60找到行,“-”前面是0200:60~0200:67的8个单元,后面是0200:68~0200:6F的8个单元,这样我们就可以从0200:68单元向后数3个单元,找到0200:6B单元,可以看到0200:6B中的内容为B0H
⑶右边是每个内存单元中的数据对应的可显示的ASCII码字符。比如,内存单元0200:0、0200:1、0200:2中存放的数据是17H,FEH,74H,它对应的ASCII字符分别为. . t ;内存单元0200:0和0200:1中的数据17H,FEH,它没有对应可显示的 ASCII字符,debug就用“.“来代替。
注意,我们看到的内存中的内容,在不同的计算机中是不一样的,也可能每次用debug看到的内容都不相同,因为我们用debug看到的都是原来的内存中的内容,这些内容受随时都有可能变化的系统环境的影响。当然,我们也可以改变内存、寄存器中的内容。

我们使用d 0200:9查看0200:9处的内容,debug将怎样输出呢?如图2.35所示

 debug从0200:9开始显示,一直到0200:88,一共是128个字节。第一行中的0200:0~0200:8单元中的内容不显示。
在一进入debug后,用d命令直接查看,将列出debug预设的地址处的内容,如图2.36所示

 在使用“d 段地址:偏移地址”之后,接着使用d命令,可列出后续的内容,如图2.37所示

也可以指定d命令的查看范围,此时采用"d 段地址:起偏移地址 结尾偏移地址"的格式。比如要看0200:~0200:9中的内容,可以用"d 0200:0 9"实现,如图2.38所示

 如果我们就想查看内存单元2000H中的内容,可以用图2.39中的任何一种方法看到,因为图中的所有“段地址:偏移地址”都表示2000H这一物理地址。

(6)用debug的e命令改写内存中的内容
可以使用E命令来改写内存中的内容,比如,要将内存073F:0100~073F:0109单元中的内容分别写为0、1、2、3、4、5、6、7、8、9,可以用"e 起始地址 数据 数据 数据 ......"的格式来进行,如图2.40所示

 图2.40中,先用D命令查看073F:0100~073F:010f单元的内容,再用E命令修改从073F:0100开始的10个单元的内容,最后用D命令查看073F:0100~073F:010f中内容的变化。

也可以采用提问的方式来一个一个地改写内存中的内容,如图2.41所示。

如图2.41中,可以用E命令以提问的方式来逐个地修改从某一地址开始的内存单元中的内容,以从073F:0100单元开始为例,步骤如下: 

⑴ 输入e 073F:0110,按Enter键
⑵ debug显示起始地址073F:0100,和第一单元(即073F:0100单元)的原始内容:E3,然后光标停在“.”的后面提示输入想要写入的数据,此时可以有两个选择:其一为输入数据(这里输入的是23),然后按空格键,即用输入的数据改写录前的内存单元 ;其二为不输入数据,直接控空格键,则不对当前内存单元进行改写。
⑶ 当前单元处理完成后(不论是改写或没有改写,只要按了空格键,就表示处理完成),debug将接着显示下一个内存单元的原始内容,并提示进行修改。
⑷ 所有希望改写的内存 单元改写完毕后,按Enter键,E命令操作结束。

可以用e命令向内存中写入字符,比如,用E命令从内存073F:0100开始写入数值1、字符“a”、数据2、字符“b”、数据3、字符“c”,可采用2.42中所示的方法进行。

 从图2.42中可以看出,debug对e命令的执行结果是,向073F:0100、073F:0102、073F:0104单元中写数值1、2、3,向073F:0101、073F:0103、073F:0105单元中写入字符“a”、“b”、“c”的ASCII值:61H、62H、63H。

也可以用e命令向内存中写入字符串,比如,用e命令从人存073F:0100开始写入:数值1、字符串“a+b”,数据2、字符串“c++”、字符3、字符串“IBM”,如图2.43所示。

 (7)用E命令向内存中写入机器码,用U命令查看内存中机器码的含义,用T命令执行内存中的机器码。

如何向内存中写入机器码呢?我们知道,机器码也是数据,当然可以用E命令将机器码写入内存。比如我们要从内存073F:0100单元开始写这样一段机器码:
机器码    对应的汇编指令
b80100    mov ax, 0001
b90200    mov cx, 0002
01c8    add ax, cx
可用如图2.44中所示的方法进行。

 如何查看写入的或内存中原有的机器码所对应的汇编指令呢?可以使用U命令。比如可以用U命令将从073F:0100开始的内存单元中的内容翻译为汇编指令,并显示出来,如图2.45所示。

 图2.45中,首先用E命令向从073F:0100开始的内存单元中写入8个字节的机器码;然后用D命令查看内存073F:0100~073F:011f中的数据(从数据的角度看一下写入的内容);最后用U命令查看从073F:0100开始的内存单元中的机指令和它们所对应的汇编指令。

U命令的显示输出分为3部分,每一条机器指令的地址、机器指令、机器指令所对应的汇编指令。我们可以看到:
073F:0100处存放的是写入的机器码b8 01 00所组成的机器指令,对应的汇编指令是mov ax,1;
073F:0103处存放的是写入的机器码b9 02 00所组成的机器指令,对应的汇编指令是mov cx,2;
073F:0106处存放的是写入的机器码01 c8所组成的机器指令,对应的汇编指令是add ax,cx;
073F:0108处存放的是写入的机器码33 49 42所组成的机器指令,对应的汇编指令是xor cs,[bx+di+42];
由此,我们可以再一次看到内存中的数据和代码没有任何区别,关键在于如何解释。
如何执行我们写入的机器指令呢?使用debug的T命令可以执行一条或多和指令,简单地使用T命令,可以执行CS:IP指缶的指写,如图2.46所示。

 图2.46中,首先用E命令向从073F:0100开始的内存单元中写入了8个字节的机器码;然后用R命令查看CPU中寄存器的状态,可以看到,CS=073FH、IP=0102H,指向内存073F:0102;若要用T命令控制CPU执行我们写到073F:0100的指令,必须先让CS:IP指向073F:0100;接着用R命令修改IP中的内容,使CS:IP指向073F:0100。
完成上面的步骤后,就可以使用T命令来执行我们写入的指令了(此时,CS:IP指向我们的指令所在的内存单元)。执行T命令后,CPU执行CS:IP指向的指令,则073F:0100处的指令b8 01 00(mov ax,1)得到执行,指令执行后,debug显示输出CPU中寄存器的状态。
注意,指令执行后,AX中的内容被改写为1,IP改变为IP+3(因为mov ax,0001的指令长度为3个字节),CS:IP指向下一条指令。
接着图2.46,我们可以继续使用T命令执行下面的指令,如图2.47所示。

 在图2.47中,用T命令继续执行后面的指令,注意每条指令执行后,CPU相关寄存器内容的变化。

(8)用debug的A命令以汇编指令的形式在内存中写入机器指令

前面我们使用E命令写入机器指令,这样做很不方便,最好能直接以汇编指令的形式写入指令。为此,debug提供了A命令。A命令的使用方法如图2.48所示。

 图2.48首先用A命令,以汇编语言向从073F:0100开始的内存单元中写入了几条指令,然后用D命令查看A命令的执行结果。可以看到,在使用A命令写入指令时,我们输入的是汇编指令,Debug将这些汇编指令翻译为对应的机器指令,将它们的机器码写入内存。
使用A命令写入汇编指令时,在给出的超始地址后直接按Enter键表示操作结束。
如图2.49中,简单地用A命令,从一个预设的地址开始输入指令。

                                        本次实验中需要用到的命令
查看、修改CPU中寄存器的内容:R命令
查看内存中的内容:D命令
修改内存中的内容:E命令(可以写入数据、指令,在内存中,它们实际上没有区别)
将内存中的内容解释为机器指令和对应的汇编指令:U命令
执行CS:IP指向的内存单元处的指令:T命令
以汇编指令的形式向内存中写入指令:A命令
在预备知识中,详细讲解了Debug的基本功能和用法。在汇编语言的学习中,Debug是一个经常用到的工具,在学习预备知识中,应该一边看书一边在机器上操作。
前面提到,我们的原则是:以后用到的,以后再说,所以在这里只讲了一些在本次实验中需要用到的命令的相关的使用方法。以后根据需要,我们会讲解其他的用法。

2.实验任务
(1)使用Debug,将下面的程序写入内存,逐条执行,观察每条指充执行后CPU中相关寄存器中内容的变化。
机器码        汇编指令
b8 20 4e    mov ax,4E20H
05 16 14    add ax,1416H
bb 00 20    mov bx,2000H
01 d8        add ax,bx
89 c3        mov bx,ax
01 d8        add ax,bx
b8 1a 00    mov ax,001AH
bb 26 00    mov bx,0026H
00 d8        add al,bl
00 dc        add ah,bl
00 c7        add bh,al
b4 00        mov ah,0
00 d8        add al,bl
04 9c        add al,9CH

用e命令将指令写入内存

用u命令 查看汇编指令

用T命令 执行指令

每执行一条命令,IP的值都在变化

用A命令将指令写入内存

 用u命令查看汇编指令

 用t命令执行指令

 

(2)将下面3条指令写入从2000:0开始的内存单元中,利用这3条指令计算2的8次方。
mov ax,1
add ax,ax
jmp 2000:0003

 执行指令

 连接执行t命令,当ax=0100时表示是十进制数256,即2的8次方

 (3)查看内存中的内容。
PC机主板上的ROM中写有一个生产日期,在内存FFF00H~FFFFFH的某向个单元中,请找到这个生产日期并试图改变它。
提示,如果读者对实验的结果感到疑惑,请仔细阅读第1章中的1.15节。

 从这上面看出我的主板是92年1月1日生产的???

原来这是win10的原因:debug是DOS、Windows都提供的实模式(8086方式)程序的调试工具,但在win10中系统已经没有了自带的debug,所以我这里安装的是DosBox软件来虚拟Dos环境,所以内存中的日期也是它虚拟出来的,自然不能作为参考了
修改试试

从实验上看,这里是修改不了的,这是ROM只读的。

(4)向内存从B8100H开始的单元中填写数据,如:
-e B810:0000 01 01 02 02 03 03 04 04
请读者先填写不同的数据,观察产生的现象,再改变填写的地址,观察产生的现象。
提示,如果读者对实验的结果感到疑惑,请仔细阅读第1章中的1.15节。

 这里修改后没有变化,原因是这个地址区域是ROM只读的,不能修改。

  • 4
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值