汇编语言实验指导书.docx
《汇编语言实验指导书.docx》由会员分享,可在线阅读,更多相关《汇编语言实验指导书.docx(31页珍藏版)》请在冰点文库上搜索。
汇编语言实验指导书
目录
实验一查看CPU和内存,用机器指令和汇编指令编程1
实验二用机器指令和汇编指令编程4
实验三汇编语言程序的调试与运行6
实验四[bx]和loop指令的联合使用8
实验五编写、调试具有多个段的程序10
实验六不同寻址方式的灵活应用14
实验七寻址方式在结构化数据访问中的应用15
实验八转移指令的原理17
实验九编写子程序18
实验十编写子程序21
实验十一编写0号中断的处理程序22
实验十二编写、应用中断例程23
实验十三访问CMOSRAM25
实验十四安装新的int9中断例程26
实验十五编写包含多个功能子程序的中断例程27
实验十六编写包含多个功能子程序的中断例程28
实验一查看CPU和内存,用机器指令和汇编指令编程
一.实验目的:
掌握DEBUG的基本命令及其功能
二.实验内容:
1.预备知识:
Debug的使用
(1)什么是Debug?
Debug是DOS、Windows都提供的实模式(8086方式)程序的调试工具。
使用它,可以查看CPU各种寄存器中的内容、内存的情况和在机器码级跟踪程序的运行。
(2)我们用到的Debug功能
●用Debug的R命令查看、改变CPU寄存器的内容;
●用Debug的D命令查看内存中的内容;
●用Debug的E命令改写内存中的内容;
●用Debug的U命令将内存中的机器指令翻译成汇编指令;
●用Debug的T命令执行一条机器指令;
●用Debug的A命令以汇编指令的格式在内存中写入一条机器指令。
(3)进入Debug
Debug是在DOS方式下使用的程序。
我们在进入Debug前,应先进入到DOS方式。
用以下方式可以进入DOS:
①重新启动计算机,进入DOS方式,此时进入的是实模式的DOS。
②在Windows中进入DOS方式,此时进入的是虚拟8086模式的DOS。
(4)用R命令查看、改变CPU寄存器的内容
1)显示CPU内部所有寄存器内容和标志位状态;格式为:
-R
2)显示和修改某个指定寄存器内容,格式为:
-R寄存器名
若要修改一个寄存器中的值,比如AX中的值,可用R命令后加寄存器名来进行,输入“rax”后按Enter键,将出现“:
”作为输入提示,在后面输入要写入的数据后按Enter键,即完成了对AX中内容的修改。
若想看一下修改的结果,可再用R命令查看
(5)用Debug的D命令查看内存中的内容
1)格式:
-d段地址:
偏移地址,Debug将列出从指定内存单元开始的128个内存单元的内容。
使用D命令,Debug将输出3部分内容,如图2.34所示。
中间是部分从指定地址开始的128个内存单元的内容,用十六进制的格式输出,每行的输出从16的整数倍的地址开始,最多输出16个单元的内容。
左边是每行的起始地址。
右边是每个内存单元中的数据对应的可显示的ASCII码字符。
2)格式:
-d段地址:
起始偏移地址结尾偏移地址,Debug将列出指定范围的内存单元的内容。
(6)用Debug的E命令改写内存中的内容,有两种格式:
1)格式:
-e起始地址数据数据数据……,如要将1000:
0开始的10个内存单元修改为0~9,可以用”-e1000:
00123456789”
2)格式:
-e起始地址,逐个单元相继地修改。
如:
-e1000:
10
1000:
00106D.061.172.26B.1c
输入e1000:
10,Debug显示起始地址1000:
0010,和1000:
0010单元的原始内容:
6D,然后光标停在“.”的后面提示输入想要写入数据,输入数据0,然后按空格键,即用输入的数据0改写了当前的内存单元。
当前单元处理完成后,Debug将接着显示下一个内存单元的原始内容,并提示读者进行修改,可以用同样的方法处理。
改写完毕后,按Enter键,E命令操作结束。
可以用E命令向内存中写入字符,比如:
用E命令从内存1000:
0开始写入:
数值1、字符“a”,数值2,字符“b”,数值3,字符“c”,可以用:
“-e1000:
01‘a’2‘b’3‘c’”
修改的结果是,向1000:
0、1000:
2、1000:
4单元中写入数值1、2、3,向1000:
1、1000:
3、1000:
5单元中写入字符“a”、“b”、“c”的ASCII码值:
61H、62H、63H。
也可以用E命令向内存中写入字符串,比如:
用E命令从内存1000:
0开始写入:
数值1、字符串“a+b”、数值2、字符串“c++”、字符3、字符串“IBM”。
可以用:
‘-e1000:
01“a+b”2“c++”3“IBM”’。
可以用E命令向内存中写入机器码
比如要从内存1000:
0单元开始写入这样一段机器码:
机器码对应的汇编指令
b80100movax,0001
b90200movcx,0002
01c8addax,cx
可用:
”-e1000:
0b80100b9020001c8”
(7)用U命令查看写入的或内存中原有的机器码所对应的汇编指令
1)-U段地址:
偏移地址
该命令从指定地址开始,反汇编32个字节,若地址省略,则从上一个U命令的最后一条指令的下一个单元开始显示32个字节。
2)-U地址范围
该命令对指定范围的内存单元进行反汇编
(8)使用T命令,可以执行CS:
IP指向的指令,格式:
-t,指令执行后,Debug显示输出CPU中寄存器的状态。
(9)用Debug的A命令以汇编指令的形式在内存中写入机器指令。
格式:
-A段地址:
偏移地址
该命令从指定地址开始允许输入汇编语句,把它们汇编成机器代码相继存放在从指定地址开始的存储器中。
三.实验任务
(1)使用Debug,将下面的程序段写入内存,逐条执行,观察每条指令执行后,CPU中相关寄存器中内容的变化。
机器码汇编指令
b8204emovax,4E20H
051614addax,1416H
bb0020movbx,2000H
01d8addax,bx
89c3movbx,ax
01d8addax,bx
b81a00movax,001AH
bb2600movbx,0026H
00d8addal,bl
00dcaddah,bl
00c7addbh,al
b400movah,0
00d8addal,bl
049caddal,9CH
提示:
可用E命令和A命令以两种方式将指令写入内存。
注意用T命令执行时,CS:
IP的指向。
(2)将下面3条指令写入从2000:
0开始的内存单元中,利用这3条指令计算2的8次方。
movax,1
addax,ax
jmp2000:
0003
(3)查看内存中的内容
PC机主板上的ROM中写有一个生产日期,在内存FFF00H~FFFFFH的某几个单元中,请找到这个生产日期并试图改变它。
(4)向内存从B8100H开始的单元中填写数据,如:
-eB810:
00000101020203030404
请读者:
先填写不同的数据,观察产生的现象;再改变填写的地址,观察产生的现象。
四.实验报告
写出在DEBUG状态下编写、运行程序的过程以及调试所中遇到的问题是如何解决的,并对调试过程中的问题进行分析,对执行结果进行分析。
实验二用机器指令和汇编指令编程
一.实验目的
掌握DEBUG的几个补充的命令及其功能
二.实验内容
1.预备知识:
Debug命令的补充
(1)在D命令中使用段寄存器
格式:
“d段寄存器:
偏移地址”,以段寄存器中的数据为段地址SA,列出从SA:
偏移地址开始的内存区间中的数据。
以下是4个例子:
①-rds
:
1000
-dds:
0;查看从1000:
0开始的内存区间中的内容
②-rds
:
1000
-dds:
1018;查看1000:
10~1000:
18中的内容
③-dcs:
0;查看当前代码段中的指令代码
④-dss:
0;查看当前栈段中的内容
(2)在E、A、U命令中使用段寄存器
在E、A、U这些可以带有内存单元地址的命令中,也可以同D命令一样,用段寄存器表示内存单元的段地址。
以下是3个例子:
①-rds
:
1000
-eds:
0112233445566;在从1000:
0开始的内存区间中写入数据
②-ucs:
0;以汇编指令的形式,显示当前代码段中的代码,0代码的偏移地址
③-rds
:
1000
-ads:
0;以汇编指令的形式,向从1000:
0开始的内存单元中写入指令
(3)下一条指令执行了吗?
在Debug中,用A命令写一段程序:
movax,2000
movss,ax
movsp,10;安排2000:
0000~2000:
000F为栈空间,初始化栈顶。
movax,3123
pushax
movax,3366
pushax;在栈中压入两个数据。
在用T命令单步执行movax,2000后,显示出当前CPU各个寄存器的状态和下一步要执行的指令:
movss,ax;在用T命令单步执行movss,ax后,下一条指令应该是movsp,10,却变成了movax,3123?
注意,在用T命令单步执行movss,ax前,ax=0000,ss=0b39,sp=ffee,而执行后ss=2000,sp=0010。
ss变为2000是正常的,这正是movss,ax的执行结果。
而能够将sp设为0010的只有指令movsp,10,看来,movsp,10一定是得到了执行。
在用T命令执行movss,ax的时候,它的下一条指令movsp,10也紧接着执行了。
整理一下我们分析的结果:
在用T命令执行movss,ax的时候,它的下一条指令movsp,10也紧接着执行了。
一般情况下,用T命令执行一条指令后,会停止继续执行,显示出当前CPU各个寄存器的状态和下一步要执行的指令,但T命令执行movss,ax的时候,没有做到这一点。
不单是movss,ax,对于如:
movss,bx,movss,[0],popss等指令都会发生上面的情况,这些指令有哪些共性呢?
它们都是修改栈段寄存器SS的指令。
结论:
Debug的T命令在执行修改寄存器SS的指令时,下一条指令也紧接着被执行。
三.实验任务
(1)使用Debug,将上面的程序段写入内存,逐条执行,根据指令执行后的实际运行情况填空。
movax,ffff
movds,ax
movax,2200
movss,ax
movsp,0100
movax,[0];ax=
addax,[2];ax=
movbx,[4];bx=
addbx,[6];bx=
pushax;sp=;修改的内存单元的地址是内容为
pushbx;sp=;修改的内存单元的地址是内容为
popax;sp=;ax=
popbx;sp=;bx=
push[4];sp=;修改的内存单元的地址是内容为
push[6];sp=;修改的内存单元的地址是内容为
(2)仔细观察下图中的实验过程,然后分析:
为什么2000:
0~2000:
f中的内容会发生改变?
用Debug进行实验的示例
四.实验报告
写出在DEBUG状态下编写、运行程序的过程以及调试所中遇到的问题是如何解决的,并对调试过程中的问题进行分析,对执行结果进行分析。
实验三汇编语言程序的调试与运行
一.实验目的
1.熟练掌握编写汇编语言原程序的基本框架
2.熟悉在PC机上编辑、汇编、连接、调试和运行汇编语言程序的过程。
二.实验内容
一个汇编语言程序从写出到最终执行的简要过程如下:
1)编辑
可以用任意的文本编辑器来编辑源程序,只要最终将其存储为纯文本文件即可。
一般保存为*.asm文件。
2)编译
上机过程中,我们采用微软的masm5.0汇编编译器,文件名为masm.exe。
我们的编译器在C:
\masm5目录下,可以按照下面的过程来进行源程序的编译,以C:
\1.asm为例:
进入DOS方式,进入C:
\masm5目录,运行masm.exe,首先显示一些版本信息,然后提示输入将要被编译的源程序文件名。
在输入源程序文件名时一定要指明路径,如果文件在当前路径下,只要输入文件名就可以,否则要输入全路径。
在此,我们输入C:
\1.asm.
输入源程序文件名后,程序继续提示我们输入要编译出的目标文件名,因为我们已经输入了源程序文件名为1.asm,则编译程序默认要输出的目标文件名为1.obj,所以我们可以不必另行指定文件名,直接按回车,编译程序将在当前目录下,生出1.obj文件。
我们也可以指定生成的目标文件所在的目录,如想在“C:
\windows\desktop”下生成目标文件1.obj,则可以输入“C:
\windows\desktop\1”
确定了目标文件名称后,编译程序提示输入列表文件名称和交叉引用文件名称,这些时编译器将源程序编译为目标文件过程中产生的中间结果,我们直接按回车键忽略。
对源程序编译结束,编译器输出的最后两行告诉我们源程序是否有警告错误和必须要改正的错误。
3)链接
对源程序进行编译得到目标文件后,需要对目标文件进行链接得到可执行文件。
我们使用微软的OverlayLinker3.6连接器,文件名为link.exe,假设连接器在C:
\masm5目录下,我们按照下面的过程来进行程序的链接,以C:
\masm5\1.obj为例
进入DOS方式,进入C:
\masm5目录,运行link.exe,首先显示一些版本信息,然后提示输入将要被连接的目标文件名。
此处我们输入”1”,按回车.程序继续提示我们输入要生成的可执行文件的名称,这是我们对一个程序进行连接要得到的最终结果。
这里我们不必另行指定文件名,直接按回车,链接程序将在当前目录下,生成1.exe文件。
确定了可执行文件的名称后,连接程序提示输入映像文件的名称和库文件的连接,我们直接按回车键忽略即可。
最后对目标文件的连接结束,连接程序输出的最后一行告诉我们源程序是否有错误。
如果尽出现一个警告错误:
“没有栈段”,我们可以不理会。
4)执行和调试
将生成的可执行文件执行:
C:
\masm5>1.exe,看不到任何结果,因为我们的程序没有向显示器输出信息。
为了观察程序的运行过程,使用Debug的相关命令来单步执行程序,查看每一条指令的运行结果。
进入C:
\masm5后,我们输入“Debug1.exe”,按Enter键,Debug将程序从1.exe中加载到内存,进行相关的初始化后设置CS:
IP指向程序的入口。
使用R命令查看各个寄存器的设置情况,使用U命令来查看我们写入的指令,使用T命令单步执行程序中的每一条指令,到达int21,使用P命令执行,执行后,显示“Programterminatednormally”,返回到Debug,表示程序正常结束。
注意:
在DOS中运行程序时,是Command将程序加载到内存,所以程序运行结束后返回到command中,而在这里是debug将程序加载到内存,所以程序运行结束后返回到debug中。
三.实验任务
1.将下面的程序保存为t1.asm文件,生成可执行文件t1.exe;
assumecs:
codesg
codesgsegment
movax,2000h
movss,ax
movsp,0
addsp,4
popax
popbx
pushax
pushbx
popax
popbx
movax,4c00h
int21h
codesgends
end
2.用Debug跟踪t1.exe的执行过程,写出每一步执行后相关寄存器中的内容
3.PSP的前两个字节是CD20,用Debug加载t1.exe,查看PSP的内容
四.实验报告
调试说明。
包括上机调试的情况、上机调试步骤、调试所遇到的问题是如何解决的,并对调试过程中的问题进行分析,对执行结果进行分析。
实验四[bx]和loop指令的联合使用
一.实验目的
1、熟练掌握编写汇编语言原程序的基本方法和基本框架。
2、掌握[bx]访问内存的方法和loop循环指令。
3、熟练使用DEBUG调试程序跟踪循环指令的执行。
二.实验内容
1.编程:
向内存0:
200~0:
23F依次传送数据0~63
2.编程:
向内存0:
200~0:
23F依次传送数据0~63,程序中只能使用9条指令(包括程序的2条返回语句)
3.下面程序的功能是将“movax,4c00h”之前的指令复制到内存0:
200处,补全程序。
上机调试,跟踪运行结果。
assumecs:
code
codesegment
movax,
movds,ax
movax,0020h
moves,ax
movbx,0
movcx,
s:
moval,[bx]
moves:
[bx],al
incbx
loops
movax,4c00h
int21h
codeends
end
三.编程提示
对于实验任务3,有如下说明:
因为题目的要求是把代码段内的指令当作数据,复制到目的地址。
所以要确定要复制的数据的位置和长度。
1.因为要复制的数据是代码段的一部分指令,那么要复制的数据的段地址就和代码段的段地址相同。
2.因为要复制的数据是代码段的一部分指令,所以要复制的数据的长度,就是要复制的指令的长度,可以先假设要复制8位[1h~0ffh]数据的字节数(如:
10h),把程序补全,以便通过编译。
将程序补充完整并将其编译、连接、运行,接着进行DEBUG,在DEBUG时我们可以算出该程序的长度。
然后得到正确的值后重新将程序补充完整。
四.实验要求
实验前要做好充分准备,包括汇编程序清单、调试步骤、调试方法,以及对程序结果的分析等
五.实验报告
1、程序说明。
说明程序的功能、结构。
2、调试说明。
包括上机调试的情况、上机调试步骤、调试所遇到的问题是如何解决的,并对调试过程中的问题进行分析,对执行结果进行分析。
3、写出源程序清单和执行结果
实验五编写、调试具有多个段的程序
一.实验目的
1、熟练掌握编写汇编语言源程序的基本方法和基本框架。
2、掌握编写具有多个段的程序。
二.实验内容
1.将下面的程序编译链接,用Debug加载、跟踪,然后回答问题:
assumecs:
code,ds:
data,ss:
stack
datasegment
dw0123H,0456H,0789H,0abcH,0defH,0fedH,0cbaH,0987H
dataends
stacksegment
dw0,0,0,0,0,0,0,0
stackends
codesegment
start:
movax,stack
movss,ax
movsp,16
movax,data
movds,ax
pushds:
[0]
pushds:
[2]
popds:
[2]
popds:
[0]
movax,4c00h
int21h
codeends
endstart
1CPU执行程序,程序返回前,data段中的数据为多少?
2CPU执行程序,程序返回前,cs=________、ss=________、ds=________.
3该程序加载后,code段的段地址为X,则data段的段地址为________,stack段的段地址为________。
2.将下面的程序编译连接,用Debug加载、跟踪,然后回答问题:
assumecs:
code,ds:
data,ss:
stack
datasegment
dw0123H,0456H
dataends
stacksegment
dw0,0
stackends
codesegment
start:
movax,stack
movss,ax
movsp,16
movax,data
movds,ax
pushds:
[0]
pushds:
[2]
popds:
[2]
popds:
[0]
movax,4c00h
int21h
codeends
endstart
1CPU执行程序,程序返回前,data段中的数据为多少?
2CPU执行程序,程序返回前,cs=________、ss=________、ds=________.
3该程序加载后,code段的段地址为X,则data段的段地址为________,stack段的段地址为________。
4对于如下定义的段:
namesegment
………
nameends
如果段中的数据占N个字节,则程序加载后,该段实际占有的空间为________。
3.将下面的程序编译连接,用Debug加载、跟踪,然后回答问题:
assumecs:
code,ds:
data,ss:
stack
codesegment
start:
movax,stack
movss,ax
movsp,16
movax,data
movds,ax
pushds:
[0]
pushds:
[2]
popds:
[2]
popds:
[0]
movax,4c00h
int21h
codeends
datasegment
dw0123H,0456H
dataends
stacksegment
dw0,0
stackends
endstart
1CPU执行程序,程序返回前,data段中的数据为多少?
2CPU执行程序,程序返回前,cs=________、ss=________、ds=________.
3设程序加载后,code段的段地址为X,则data段的段地址为________,stack段的段地址为________。
4.若将1,2,3题中的最后一条伪指令“endstart“改为“end”,则那个程序仍然可以正确执行?
请说明原因。
5.程序如下,编写code段中的代码,将a段和b段中的数据依次相加,将结果存到c段中。
assumecs:
code
asegment
db1,2,3,4,5,6,7,8
aends
bsegment
db1,2,3,4,5,6,7,8
bends
csegment
db0,0,0,0,0,0,0,0
cends
codesegment
start:
?
codeends
endstart
6.程序如下,编写code段中的代码,用push指令将a段中的word数据,逆序存储到b段中。
assumecscode
asegment
dw1,2,3,4,5,6,7,8
aends
bsegment
dw0,0,0,0,0,0,0,0
ben