太原理工大学微机原理实验报告.docx
《太原理工大学微机原理实验报告.docx》由会员分享,可在线阅读,更多相关《太原理工大学微机原理实验报告.docx(29页珍藏版)》请在冰点文库上搜索。
太原理工大学微机原理实验报告
本科实验报告
课程名称:
微机原理与应用
实验项目:
实验地点:
专业班级:
机械##x班学号:
##########
学生:
##
指导教师:
2016年12月28日
实验一汇编语言程序开发环境与程序调试
一、实验要求和目的
1.熟悉在微机上编辑、汇编、连接、调试和运行汇编语言程序的过程,掌握PC环境下命令行方式的特点。
2.熟悉汇编过程中一些常见出错信息。
3.熟悉程序调试的方法,DOS命令窗口的debug的常用命令。
二、实验容
1、项目要求:
在屏幕上显示字符串‘Hello,world!
’。
2、程序设计思想:
运用DOS系统功能调用(INT21H)的9号功能。
DOS系统功能调用的9号功能是显示字符串,它调用的参数DS:
DX=串地址,且字符串以“$”完毕。
程序流程图如图1-1:
图1-1程序流程图
3、程序清单:
完整指令代码如下(简化段定义格式):
.modelsmall;定义程序的存储模式
.486;说明使用的80x86微处理器指令
.stack;定义堆栈段
.data;定义数据段
Stringdb'Hello,world!
','$'
.code;定义代码段
.startup;程序执行开始
Movax,segString;把String的段地址送ax
Movds,ax;ax送ds,ds取得string的段地址
movdx,offsetString;String的偏移地址送dx
movah,9;字符串显示功能
int21h;DOS功能调用
movax,4c00h
int21h;返回DOS
.exit
end
三、结果与分析
指导教师:
年月
实验二存数据的移动
一、实验要求与目的:
1、实验要求:
编写程序实现把数据段的字符串数据移动到附加段中。
2、实验目的:
通过项目学习汇编的数据传送指令和串处理类指令,巩固寻址方式,学习汇编程序设计。
二、实验容:
1、项目要求:
把数据段中以dstring地址标号为开始地址的“helloworld!
”字符串移动到附加段以sstring地址标号为开始地址中去。
2、设计思想:
从源串中取一个字符到AL中,然后把刚取到的字符放到目的串指定位置,重复这样的过程,把源串的字符取完为止。
程序流程如图2-1所示。
图2-1程序流程图
3、程序设计清单:
实现这样功能的程序方法很多,下面给出了实现这一功能的完整程序清单(完整段定义格式)。
方案一(无聊版):
采用的是loop指令,CX为循环次数,当CX为0时退出循环。
加入了换行指令。
用字符串常量’$’改变字符串,提前终止字符串的输出。
程序如下:
DSEGSEGMENT
dstringDB'HELLO,WORLD!
',33,33,'$';15个字节HELLO,WORLD!
!
!
dstring_1db'数据段的字符串:
','$';一定要加'$',表示一个字符串的完毕
dstring_2db'附加段的字符串:
','$';在屏幕上显示的字符串
DSEGENDS
ESEGSEGMENT
sstringDB15DUP(?
);附加段预留15个字节空间
ESEGENDS
CODESEGMENT
ASSUMECS:
CODE,DS:
DSEG,ES:
ESEG
start:
MOVAX,DSEG;程序开始执行的地方
MOVDS,AX;将DSEG的段地址给ds
MOVAX,ESEG
MOVES,AX;将SSEG的段地址给es
LEASI,dstring;将dstring的首地址给si
LEADI,sstring;将sstring的首地址给di
MOVCX,15;CX存放loop指令的循环次数
S:
MOVAL,[SI]
MOVES:
[DI],AL
INCDI
INCSI
LOOPS
movdX,offsetdstring_1
MOVAH,09h
INT21H;输出字符串‘数据段的字符串:
’
MOVDL,0AH;输出换行
MOVAH,02H
INT21H
movdX,offsetdstring
MOVAH,09h
INT21H;输出字符串:
HELLO,WORLD!
!
!
MOVDL,0AH
MOVAH,02H
INT21H;输出换行
movdX,offsetdstring_2
MOVAH,09h
INT21H;输出字符串dstring_2
MOVDL,0AH
MOVAH,02H
INT21H;输出换行
moval,'$'
moves:
[di-3],al;将第二个'!
'改成'$'以终止字符串的继续输出
MOVAX,ES
MOVDS,AX;将附加段的段地址附给数据段
movdX,offsetsstring
MOVAH,09h
INT21H;显示字符串HELLO,WORLD!
注意不是!
!
!
MOVAX,4C00H
INT21H;返回DOS
CODEENDS;代码段完毕
ENDstart;程序完毕
方案二:
采用字符串操作指令movsb,执行[di]=[si]。
Si与di自动地址改变方向,由std,cld控制。
Cx作为计数器,前面应用rep指令重复。
程序如下:
DSEGSEGMENT
dstringDB'HELLO,WORLD!
','$';13个字节HELLO,WORLD!
!
!
DSEGENDS
ESEGSEGMENT
sstringDB13DUP(?
);附加段留13个字节空间
ESEGENDS
CODESEGMENT
ASSUMECS:
CODE,DS:
DSEG,ES:
ESEG
start:
MOVAX,DSEG;程序开始执行的地方
MOVDS,AX;将DSEG的段地址给ds
MOVAX,ESEG
MOVES,AX;将SSEG的段地址给es
LEASI,dstring;将dstring的首地址给si
LEADI,sstring;将sstring的首地址给di
MOVCX,13;CX存放rep指令的重复次数
cld;将DF位清零,则di与si自增
repmovsb;执行[di]=[si]
MOVAX,ES
MOVDS,AX;将附加段的段地址附给数据段
movdX,offsetsstring
MOVAH,09h
INT21H;显示字符串HELLO,WORLD!
!
!
MOVAX,4C00H
INT21H;返回DOS
CODEENDS;代码段完毕
ENDstart;程序完毕
方案三:
采用是cmp与ja跳转指令来实现数据的移动。
程序如下:
DSEGSEGMENT
dstringDB'HELLO,WORLD!
','$';13个字节HELLO,WORLD!
!
!
DSEGENDS
ESEGSEGMENT
sstringDB15DUP(?
);附加段留13个字节空间
ESEGENDS
CODESEGMENT
ASSUMECS:
CODE,DS:
DSEG,ES:
ESEG
start:
MOVAX,DSEG;程序开始执行的地方
MOVDS,AX;将DSEG的段地址给ds
MOVAX,ESEG
MOVES,AX;将SSEG的段地址给es
LEASI,dstring;将dstring的首地址给si
LEADI,sstring;将sstring的首地址给di
MOVCX,13;CX存放循环次数
S:
MOVAL,[SI]
MOVES:
[DI],AL
INCDI
INCSI
DECCX
CMPCX,0
JAS
MOVAX,ES
MOVDS,AX;将附加段的段地址附给数据段
movdX,offsetsstring
MOVAH,09h
INT21H;显示字符串HELLO,WORLD!
MOVAX,4C00H
INT21H;返回DOS
CODEENDS;代码段完毕
ENDstart;程序完毕
附简化段定义格式如下:
.modelsmall;定义程序的存储模式
.486;说明使用的80X86微处理指令
.data;定义数据段开始
dstringdb'hello,world!
','$'
sstringdb13dup(0);使用的同一个数据段
.code;定义代码段
.startup;程序开始执行的地方
movax,segdstring;=movax,data
movds,ax;将dstring的段地址附给ds
moves,ax;为了使用movsb指令,由于两个字符串都在数据段,所以令es=ds
leasi,dstring
leadi,sstring
movcx,13;循环次数
cld
repmovsb
movdx,offsetsstring
movah,9
int21h
movax,4c00h
int21h
.exit
End
4、调试过程:
(在win7x32下调试的方案二)
第1步:
进入debug:
命令debug+file.exe。
第2步:
用r命令查看cpu寄存器容,这一步基本没用。
看注意点即可
注意:
此时并未给ds,es赋值,在ds,es赋值之前有ds=es,cs=ds+10h。
第3步:
用U命令查看汇编指令。
直接暴力输入g001a也可,但只适用本程序。
第四步:
用T命令执行一条机器指令。
这里了执行四次。
此时可以看到ds和es已经赋值了,此时来查看存的容。
注意cs没变。
第五步:
用d命令查看存的容。
即查看DS:
0和ES:
0输入d0bc6:
0和d0bc7:
0。
可以看出已经完成移动了。
三、结果与分析
没仔细去看为什么0bc6:
0010处也有hello,world。
我调试过了发现还有,猜测可能与ss的栈有关。
四、拓展
用q命令退出debug。
用p命令一次执行完循环。
用g+偏移地址(ip),可以直接执行到上一条指令,即此时IP=ip。
教师点评:
指导教师:
年月日
实验三分支程序结构
一、实验要求与目的:
1、实验要求:
掌握分支结构程序设计的基本方法;掌握无条件转移指令和条件转移指令的使用;掌握分支结构程序设计的两种基本结构的使用。
2、实验目的:
通过分支程序的设计掌握结构化程序设计方法和常用算法设计。
二、实验容:
1、项目要求:
编写程序实现:
在数据段中,有一个按从小到大顺序排列的无符号数组,其首地址存放在SI寄存器中,数组中的第一个单元存放着数组长度。
在key单元中有一个无符号数,要求在数组中查找是否存在[key]这个数,如找到,则使CF=0,并在DI中给出该单元在数组中的偏移地址;如未找到,则使CF=1。
2、设计思想:
对于这个表格查找,可以使用顺序查找和折半查找的算法思想。
当然顺序查找程序简单,效率不高。
而折半查找程序复杂,效率高,但对查找数据要求有序。
本项目采用折半查找方式。
在一个长度为N的有序数组r中,查找元素k的折半查找算法可描述如下:
①初始化被查找数组的尾下标,low←1,high←n。
②若low>high,则查找失败,CF=1,退出程序;否则,计算中点mid←(low+high)/2。
③k与中点元素r[mid]比较。
若k=r[mid],则查找成功,完毕程序;若kr[mid],则转步骤⑤。
④低半部分查找(lower),high←mid-1,返回步骤
(2),继续执行。
⑤高半部分查找(higher),low←mid+1,返回步骤
(2),继续执行
3、程序清单(简化段定义格式):
.modelsmall
.486
.stack
.data;定义数据段开始
arraydb13,45,49,54,66,78,83,85,89,94,99,123,233,245
keydb40
cg1db'find','$'
error1db'failed','$'
sstringdb12dup(?
)
.code
.startup
start:
movax,data;加载数据
movds,ax
moval,key;查找关键词送AL
leasi,array;把数组的首地址送SI
movbl,array;把数组元素个数送BL
movbh,0;把数组元素个数送BX
incsi
main:
cmpbx,0
jlerror;转到查找失败程序段
shrbx,1;bx除以2
cmpal,[bx+si];mid=bx+si
jahigher;若大于,则转到高半部分
jblower;若小于,则转到低半部分
jmpcg;转到查找成功,无条件转移指令
higher:
addsi,bx;高半部分
incsi
jmpmain
lower:
addsi,0;低半部分
decbx
jmpmain
error:
leadx,error1;查找失败,lea取有效地址
movah,09h;字符串显示
int21h
jmps;直接退出
cg:
leadx,cg1;查找成功
movah,09h;字符串显示
int21h
stc;cf置0
movdi,[bx+si];di保存
s:
.exit
End
附完整段定义
DSEGSEGMENT
ARRAYDB13,45,49,54,66,78,83,85,89,94,99,123,233,245
KEYDB45
CG1DB'find','$'
ERROR1DB'failed','$'
DSEGENDS
CSEGSEGMENT
ASSUMECS:
CSEG,DS:
DSEG
START:
MOVAX,DSEG
MOVDS,AX
MOVAL,KEY
LEASI,ARRAY
MOVBL,ARRAY
MOVBH,0
INCSI
MAIN:
CMPBX,0
JLERROR
SHRBX,1
CMPAL,[BX+SI]
JAHIGHER
LOWER
JMPCG
HIGHER:
ADDSI,BX
INCSI
JMPMAIN
LOWER:
ADDSI,0
DECBX
JMPMAIN
ERROR:
LEADX,ERROR1
MOVAH,09H
INT21H
CLC
JMPEXIT
CG:
LEADX,CG1
MOVAH,09H
INT21H
STC
MOVDI,[BX+SI]
JMPEXIT
EXIT:
MOVAX,4C00H
INT21H
CSEGENDS
ENDSTART
4、调试过程:
此程序在计算中值(mid←(low+high)/2)采用了一些技巧。
在程序思想的描述上,应该计算出高端地址(high)和低端地址(low),再计算中间地址(mid)。
实际上我们需要的是中间地址(mid),没有必要一定要计算出高端地址和低端地址。
bx+si表示的是中值地址,cmpal,[bx+si]这指令表示ax与中值进行比较。
本程序稍作修改,就可实现更广应用。
三、结果与分析
令key=45,输出结果如下:
完整段代码输出结果:
指导教师:
年月日
实验四循环程序结构
一、实验要求与目的
1、实验要求:
掌握循环结构程序设计的基本方法;了解循环控制的方法(计数、条件和混合)。
2、实验目的:
通过循环程序的设计掌握结构化程序设计方法和循环控制方法的设计。
二、实验容
1、项目要求:
编写程序实现1~100的累加和求算,结果送到SUM单元中。
2、设计思想:
如果循环次数是已知的,则采用计数控制方法。
这里计数法可以是正计数即从1计数到n(图4-1(a)所示);也可以是倒计数法即从n计数到0(图4-1(b)所示)。
图4-1累加和流程图
方案一:
自减法,用的是LOOP循环中CX的自减。
程序如下:
.modelsmall;注意点与m之间不能有空格
.486
.data;定义数据段开始
sumdw?
.code
.startup
movax,data
movds,ax;初始化数据段
movax,0;(ax)←0
movcx,100;循环次数
S:
addax,cx;求累加和
LOOPS
movsum,ax;最终结果送到SUM
movah,4ch
int21h;返回DOS
.exit
End
方案二(直观作死板)将结果显示在屏幕上
原理如下:
5050/1000= 商5 余数050
050/100= 商0 余数5050/10= 商5 余数00/1= 商0 余数0
商加上30h即可得到相应数字的ASCII码,然后在调用DOS命令输出字符即可,汇编所有的字符输出都是ASCII码。
4,程序如下:
DATASEGMENT
STRINGDB'1+2+3+4+5+...+99+100=$';输出字符串,$为完毕符
DATAENDS
STACKSEGMENT
DB16DUP(?
)
STACKENDS
CODESEGMENT
ASSUMECS:
CODE,DS:
DATA,SS:
STACK,ES:
DATA
START:
MOVAX,DATA
MOVDS,AX
movdx,offsetSTRING
movah,9
int21h;输出字符串
movax,0
movbx,0
movcx,100;循环次数
S:
incbx
ADDax,bx
LOOPS;实现从1加到100
MOVDX,0;除数1000要用16位寄存器存储,但5050用AX就可存储
MOVBX,1000;除1000
DIVBX
PUSHDX;余数在DX中,所以要将DX入栈
ADDAL,30H;商值加48转换成ASCII码
MOVDL,AL;DOS系统功能调用,显示
movah,02H
INT21H
POPDX;要将余数DX赋值给AX,以作下次除法
movAX,DX;除100
movBL,100
divBL
PUSHAX;余数在AX中,所以要将AX入栈
ADDAL,30H;求ASCII值
movdl,al;DOS系统功能调用,显示
movah,2
int21H
POPAX
movaL,AH;除10
MOVAH,0;由于余数只存在AL寄存器中所以要将AH寄存器清0
movbL,10
divbL
PUSHAX
addal,30H;求ASCII值
movdl,al;DOS系统功能调用,显示
movah,2
int21H
POPAX
movaL,AH;除1
MOVAH,0;要将AH寄存器清0
movbL,1
divbL
addal,30H;求ASCII值
movdl,al;DOS系统功能调用,显示
movah,2
int21H
MOVAX,4C00H
int21h
codeends
endstart
三、结果和分析
方案二输出结果:
方案二只适用于0-9999围,即最高加到140,如果要实现更高位位的话可以修改。
指导教师:
年月日
实验五子程序结构
一、实验要求与目的
1、实验要求:
掌握子程序指令,了解子程序结构和子程序设计的基本方法。
2、实验目的:
学习汇编的子程序结构和模块0。
化程序设计方法。
二、实验容
1、项目要求:
编写程序实现对一个无序排列的无符号数组排序。
数组的首地址存放在SI寄存器中,数组中的第一个单元存排序前后都存放着数组长度。
2、设计思想:
对于这个排序问题,我们可以采用基本排序算法(如冒泡排序,简单项选择择排序,插入排序等),也可以采用高级排序算法(如堆排序,归并排序,快速排序等)。
为了使程序简单,本项目采用基本排序的冒泡排序。
简单项选择择排序的基本思想:
对文件进行n-1趟排序,第i趟(i=1,2,...n-1)是在从i到n的n-i+1个记录中选择关键字最小(最大)的记录,并将它与第i个记录进行交换。
这里采用子程序结构,整个程序包括一个主程序和两个子程序,程序流程图如图5-1示。
这三个子程序是:
XZPX:
功能是对数组元素进行降序排序。
入口参数:
采用寄存器SI传递参数。
用了寄存器:
AX,BX,CX,DX
出口参数:
无。
DISPLAY:
功能是将数组元素输出在屏幕上显示。
入口参数:
采用寄存器SI传递参数。
出口参数:
无。
DIGITAL_DISPLAY:
将数组元素中的数字显示在屏幕上。
你也可以定义显示字符串然后调用DOS命令,显示字符。
入口参数:
采用寄存器SI传递参数。
调用的寄存器:
AX,BX,DX
出口参数:
无。
DATASEGMENT
ARRAYDB13,65,12,97,68,69,70,71,72,73,98,75,76,77
DATAENDS
CODESEGMENT
ASSUMECS:
CODE,DS:
DATA
START:
MOVAX,DATA
MOVDS,AX
LEASI,ARRAY
CALLDISPLAY;显示原数字串
CALLXZPX;大小排序
CALLDISPLAY;显示排序后的数字串
JMPEXIT;退出程序
XZPXPROCNEAR
PUSHAX
PUSHBX
PUSHCX
PUSHDX
PUSHSI
PUSHF
MOVCL,[SI];数组元素个数读入CL中
MOVCH,0;CX保存数组元素个数
DECCX
MOVBX,SI;BX指向数组的第一个元素,即数组的个数字节
INCBX;BX指向数组的第一个数字
MOVDX,0;DX用于循环计数
LOP1:
MOVSI,DX;DX送SI,用于定位,SI是用来循环比较的
MOVDI,DX;用于交换