概要
此次实验为汇编语言的第一次实验,难度不大,但是却是以后所有实验的基础,尤其是debug工具的使用,因此会花较大篇幅总结一下此次实验中涉及的debug用法,剩余部分会根据具体实验任务总结一下CPU、寄存器、内存的基础知识以及mov、add、jmp等指令的用法。
目录
-
debug的使用
-
实验任务
debug的使用
查看和改变CPU寄存器内容——R命令
-
- 查看格式①:—r<回车>
可以看到,此方法能够查看所有寄存器的值,如果只想查看某一寄存器的值也可采用下面的格式:
查看格式②:—r ??<回车> (??代表寄存器名)
用此种方法注意,当冒号出现后应继续按回车,否则将会改变当前寄存器的内容。
-
- 改变格式:—r ??<回车> (??代表寄存器名)
可以看出,此格式和上面查看的第二种格式相同,区别在于:查看在冒号出现后要敲回车,而改变需要在冒号后输入想要改为的值,示例如下:
ax成功从0000改为了13B1。
值得注意的是,在debug中命令和参数之间可以没有分割符(如空格),所以r ax,也可以写成rax,如下图所示:
查看和改变内存中的内容——D命令和E命令
D命令:查看内存中的内容
我们可以把内存想象成一系列排列整齐有序的盒子,要想查看某个或某段连续的盒子里装的是什么,我们需要知道起始盒子的具体位置以及其后待查看盒子的个数或者终点盒子的具体位置。由此我们衍生出两种思路:①地址范围法:起始位置+终点位置;②个数确定法:起始位置+待查看内存个数
对于位置的描述可以采用“段地址:偏移地址”的方式,对于个数的描述可以采用“L?”的方式(“?”表示个数,用十六进制表示),下面看一下具体实现:
· 查看格式①:—d 段地址:偏移地址1 偏移地址2<回车>
首先对d命令debug输出的内容简要说明一下,debug将输出三部分内容,左侧是每行的起始地址,中间部分是从指定地址开始的若干个内存单元的内容(每行的中间,即第8和第9之间有短线“-”相连,便于查 看),右边是每个内存单元中的数据对应的可显示的ASCII码字符(如果没有对应的可显示的ASCII码字符则输出“.”)。此格式可以查看从段地址:偏移地址1到段地址:偏移地址2(包含端点)之间的所有内存的内容。 查看格式②:—d 段地址:偏移地址 L?<回车>(?表示个数,十六进制表示) 此格式可以查看从给定地址开始的给定个数的内存单元的内容。以上是2种基本的查看方法,对于d命令还有许多简化的格式,如:
这几种格式中,和①②相比都有不同程度的缺省。其中缺少个数和终点地址的将输出从起始地址开始的连续128个内存的内容;缺少段地址的将以CS代替,段地址和偏移地址都缺少的将以CS:IP代替。下面分别给出这几种简化格式的示例:
这里我指定的地址是0100:0,于是debug就输出了从0100:0开始的128个内存的内容。 查看格式④: 可以看出,只给一个偏移地址,将输出从CS:偏移地址开始的128个内存的内容。 查看格式⑤: 输出了从CS:0010到CS:0020间的内存的内容。输出了从CS:0010开始的连续10个内存的内容,尤其注意L后面的数字是用16进制表示的。
d后不带任何参数将默认输出从CS:IP开始的连续128个内存的内容。
关于d命令还有一个点是,以上任何查看格式后,再次使用—d<回车>将会查看到承接上次查看的最后一个内存单元,显示接下来128个内存单元的内容。
E命令:改变内存中的内容
使用e命令改变内存中的内容主要有2种方式,具体如下:
改变格式①:—e 段地址:偏移地址 数据表<回车>
改变格式②:—e 段地址:偏移地址<回车>
第一种格式的功能是:从指定的地址开始用数据表给定的数据修改存储单元(数据表中的数据以空格间隔)。第二种格式的功能是以提问的方式逐个地修改从某一地址开始的内存单元的内容。下面看下具体实例:
可以看出,从0010:0开始的5个内存单元的内容已经成功被e命令改变了。同样地,这里的段地址也可省略,当段地址被省略时,段地址默认由CS充当。
改变格式②:
此格式的“.”用于提示输入想要写入的数据,当然也可以不输入数据,表示不对当前内存作改变,以空格作为处理结束的标志,之后会跳到下一个内存单元,进行同样的操作。当所有希望改变的内存都操作完成后按回车键结束e命令。
编写简单指令程序及调试的命令——A命令和T、P、G命令
-
编写简单指令程序——A命令
A命令可以用汇编指令的形式向内存中写入指令。(其实也可以用e命令以机器指令的方式向内存中写入指令,不过相对来说更麻烦)语法格式为:a 段地址:偏移地址<回车>
需要注意的是,每条指令后都要按回车,不输入指令按回车可以结束汇编。
(此段代码也同时作为下文调试命令的源代码)
-
调试命令——T、P、G命令
T命令和P命令都是单步执行命令,它们有2种语法格式:①t=偏移地址 或 p=偏移地址;②t 或 p;
第一种语法格式的功能是:从指定的偏移地址处单步执行程序;第二种语法格式的功能是:从CS:IP指向的指令开始单步执行程序 ;t命令和p命令的区别在于:单步执行程序时,如果遇到子程序或中断服务程序: 若使用t命令,则进入子程序或中断服务程序,继续单步执行; 若使用p命令,则把子程序或中断服务程序当做是一个整体执行。
G命令有3种语法格式:①g=偏移地址1 偏移地址2<回车>;②g=偏移地址<回车>;③g 偏移地址<回车>;④g<回车>;
格式①的功能是:运行代码段中偏移地址1到偏移地址2之间的程序;
格式②的功能是:从指定偏移地址开始执行程序,直到程序结束或遇到INT;
格式③的功能是:从当前偏移地址执行到指定偏移地址之前的指令 ;
格式④的功能是:从CS:IP指向的指令开始执行程序,直到程序结束或遇到INT;
如①的用法:
需要注意的是,汇编指令是到第二个偏移地址前结束,不包含第二个偏移地址这一内存单元。
反汇编命令——U命令
U命令可以将指定内存单元的机器指令反汇编成汇编指令;它有3种格式:①—u 段地址:偏移地址1 偏移地址2<回车>;②—u 地址<回车>:③—u<回车>;
以第一种格式为例:
向0100:0到0100:3的内存写入B80300的机器指令,使用u命令可以将它反汇编成汇编指令:MOV ax,0003;
格式②的功能是:从指定地址开始反汇编,默认连续反汇编32字节
格式③的功能是:从代码段当前偏移地址开始反汇编,默认连续反汇编32字节
实验任务
任务1——将程序段写入内存
总结:1.debug中数字默认为16进制,加上H反而会出错
2.加法运算时,如果运算结果超出寄存器能够表达的范围,最高位会被省略
任务2——计算2的8次方
总结:jmp指令可以修改CS和IP,此例中可以达到一个循环的作用,只是这个循环没有退出条件,是个死循环
任务3——查看主板ROM中的生产日期
找到的日期在ffff5-ffffc,为95年7月3日,试图用e命令修改其内容,发现不能被改变。原因是ROM为只读存储器,不能被修改。
任务4——向显卡写入数据
发现屏幕上出现了四个具有不同颜色不同形状的图案。说明每个图案是由2个字节数据控制的。改变填写的地址:
发现同样的图案在屏幕的另一个地方被显示出来。
修改下新地址的第一个字节数据的值:
发现第一个图案的形状改变了,而颜色不变。
修改下新地址的第二个字节数据的值:
发现第一个图案的眼神改变了,而形状不变。
总结:1.显卡也占据一段内存地址空间,即显存,向显存写入数据,这个数据就会被显卡输出到显示器上。
2.此例中的图案由2个字节数据控制,第一个自己控制图案的形状,第二个字节控制图案的颜色。