太原理工大学微机原理实验报告课案Word文档下载推荐.docx
《太原理工大学微机原理实验报告课案Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《太原理工大学微机原理实验报告课案Word文档下载推荐.docx(32页珍藏版)》请在冰豆网上搜索。
字符串显示功能
int21h;
DOS功能调用
movax,4c00h
返回DOS
.exit
end
三、结果与分析
年月
实验二内存数据的移动
一、实验要求与目的:
1、实验要求:
编写程序实现把数据段的字符串数据移动到附加段中。
2、实验目的:
通过项目学习汇编的数据传送指令和串处理类指令,巩固寻址方式,学习汇编程序设计。
二、实验内容:
把数据段中以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
输出字符串:
MOVDL,0AH
INT21H;
movdX,offsetdstring_2
INT21H;
输出字符串dstring_2
moval,'
moves:
[di-3],al;
将第二个'
改成'
以终止字符串的继续输出
MOVAX,ES
MOVDS,AX;
将附加段的段地址附给数据段
movdX,offsetsstring
显示字符串HELLO,WORLD!
注意不是!
MOVAX,4C00H
CODEENDS;
代码段结束
ENDstart;
程序结束
方案二:
采用字符串操作指令movsb,执行[di]=[si]。
Si与di自动地址改变方向,由std,cld控制。
Cx作为计数器,前面应用rep指令重复。
13个字节HELLO,WORLD!
sstringDB13DUP(?
);
附加段留13个字节空间
ASSUMECS:
MOVAX,DSEG;
MOVDS,AX;
MOVAX,ESEG
MOVES,AX;
将SSEG的段地址给es
LEASI,dstring;
LEADI,sstring;
MOVCX,13;
CX存放rep指令的重复次数
cld;
将DF位清零,则di与si自增
repmovsb;
执行[di]=[si]
MOVDS,AX;
方案三:
采用是cmp与ja跳转指令来实现数据的移动。
'
);
MOVAX,DSEG;
MOVDS,AX;
MOVES,AX;
LEASI,dstring;
LEADI,sstring;
MOVCX,13;
CX存放循环次数
MOVAL,[SI]
DECCX
CMPCX,0
JAS
MOVDS,AX;
INT21H;
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
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。
教师点评:
年月日
实验三分支程序结构
掌握分支结构程序设计的基本方法;
掌握无条件转移指令和条件转移指令的使用;
掌握分支结构程序设计的两种基本结构的使用。
通过分支程序的设计掌握结构化程序设计方法和常用算法设计。
编写程序实现:
在数据段中,有一个按从小到大顺序排列的无符号数组,其首地址存放在SI寄存器中,数组中的第一个单元存放着数组长度。
在key单元中有一个无符号数,要求在数组中查找是否存在[key]这个数,如找到,则使CF=0,并在DI中给出该单元在数组中的偏移地址;
如未找到,则使CF=1。
对于这个表格查找,可以使用顺序查找和折半查找的算法思想。
当然顺序查找程序简单,效率不高。
而折半查找程序复杂,效率高,但对查找数据要求有序。
本项目采用折半查找方式。
在一个长度为N的有序数组r中,查找元素k的折半查找算法可描述如下:
①初始化被查找数组的尾下标,low←1,high←n。
②若low>
high,则查找失败,CF=1,退出程序;
否则,计算中点mid←(low+high)/2。
③k与中点元素r[mid]比较。
若k=r[mid],则查找成功,结束程序;
若k<
r[mid],则转步骤④;
若k>
r[mid],则转步骤⑤。
④低半部分查找(lower),high←mid-1,返回步骤
(2),继续执行。
⑤高半部分查找(higher),low←mid+1,返回步骤
(2),继续执行
3、程序清单(简化段定义格式):
.modelsmall
.486
.stack
arraydb13,45,49,54,66,78,83,85,89,94,99,123,233,245
keydb40
cg1db'
find'
error1db'
failed'
sstringdb12dup(?
)
.code
.startup
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;
高半部分
jmpmain
lower:
addsi,0;
低半部分
decbx
error:
leadx,error1;
查找失败,lea取有效地址
movah,09h;
字符串显示
jmps;
直接退出
cg:
leadx,cg1;
查找成功
movah,09h;
int21h
stc;
cf置0
movdi,[bx+si];
di保存
s:
附完整段定义
ARRAYDB13,45,49,54,66,78,83,85,89,94,99,123,233,245
KEYDB45
CG1DB'
ERROR1DB'
CSEGSEGMENT
CSEG,DS:
DSEG
START:
MOVAX,DSEG
MOVDS,AX
MOVAL,KEY
LEASI,ARRAY
MOVBL,ARRAY
MOVBH,0
MAIN:
CMPBX,0
JLERROR
SHRBX,1
CMPAL,[BX+SI]
JAHIGHER
JBLOWER
JMPCG
HIGHER:
ADDSI,BX
JMPMAIN
LOWER:
ADDSI,0
DECBX
ERROR:
LEADX,ERROR1
MOVAH,09H
CLC
JMPEXIT
CG:
LEADX,CG1
STC
MOVDI,[BX+SI]
EXIT:
MOVAX,4C00H
CSEGENDS
ENDSTART
此程序在计算中值(mid←(low+high)/2)采用了一些技巧。
在程序思想的描述上,应该计算出高端地址(high)和低端地址(low),再计算中间地址(mid)。
实际上我们需要的是中间地址(mid),没有必要一定要计算出高端地址和低端地址。
bx+si表示的是中值地址,cmpal,[bx+si]这指令表示ax与中值进行比较。
本程序稍作修改,就可实现更广应用。
令key=45,输出结果如下:
完整段代码输出结果:
实验四循环程序结构
一、实验要求与目的
掌握循环结构程序设计的基本方法;
了解循环控制的方法(计数、条件和混合)。
通过循环程序的设计掌握结构化程序设计方法和循环控制方法的设计。
二、实验内容
1、项目要求:
编写程序实现1~100的累加和求算,结果送到SUM单元中。
如果循环次数是已知的,则采用计数控制方法。
这里计数法可以是正计数即从1计数到n(图4-1(a)所示);
也可以是倒计数法即从n计数到0(图4-1(b)所示)。
图4-1累加和流程图
方案一:
自减法,用的是LOOP循环中CX的自减。
.modelsmall;
注意点与m之间不能有空格
.data;
sumdw?
movax,@data
movds,ax;
初始化数据段
movax,0;
(ax)←0
movcx,100;
addax,cx;
求累加和
LOOPS
movsum,ax;
最终结果送到SUM
movah,4ch
int21h;
方案二(直观作死板)将结果显示在屏幕上
原理如下:
5050/1000=
商5
余数050
050/100=
商0
余数50
50/10=
余数0
0/1=
商加上30h即可得到相应数字的ASCII码,然后在调用DOS命令输出字符即可,汇编所有的字符输出都是ASCII码。
4,程序如下:
DATASEGMENT
STRINGDB'
1+2+3+4+5+...+99+100=$'
输出字符串,$为结束符
DATAENDS
STACKSEGMENT
DB16DUP(?
STACKENDS
CODE,DS:
DATA,SS:
STACK,ES:
DATA
START:
MOVAX,DATA
MOVDS,AX
movdx,offsetSTRING
movah,9
int21h;
输出字符串
movax,0
movbx,0
movcx,100;
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入栈
求ASCII值
movdl,al;
movah,2
int21H
POPAX
movaL,AH;
除10
MOVAH,0;
由于余数只存在AL寄存器中所以要将AH寄存器清0
movbL,10
divbL
PUSHAX
addal,30H;
除1
要将AH寄存器清0
movbL,1
MOVAX,4C00H
int21h
codeends
endstart
三、结果和分析
方案二输出结果:
方案二只适用于0-9999范围内,即最高加到140,如果要实现更高位位的话可以修改。
实验五子程序结构
掌握子程序指令,了解子程序结构和子程序设计的基本方法。
学习汇编的子程序结构和模块0。
化程序设计方法。
编写程序实现对一个无序排列的无符号数组排序。
数组的首地址存放在SI寄存器中,数组中的第一个单元存排序前后都存放着数组长度。
对于这个排序问题,我们可以采用基本排序算法(如冒泡排序,简单选择排序,插入排序等),也可以采用高级排序算法(如堆排序,归并排序,快速排序等)。
为了使程序简单,本项目采用基本排序的冒泡排序。
简单选择排序的基本思想:
对文件进行n-1趟排序,第i趟(i=1,2,...n-1)是在从i到n的n-i+1个记录中选择关键字最小(最大)的记录,并将它与第i个记录进行交换。
这里采用子程序结构,整个程序包括一个主程序和两个子程序,程序流程图如图5-1示。
这三个子程序是:
XZPX:
功能是对数组元素进行降序排序。
入口参数:
采用寄存器SI传递参数。
用了寄存器:
AX,BX,CX,DX
出口参数:
无。
DISPLAY:
功能是将数组元素输出在屏幕上显示。
DIGITAL_DISPLAY:
将数组元素中的数字显示在屏幕上。
你也可以定义显示字符串然后调用DOS命令,显示字符。
入口参数:
调用的寄存器:
AX,BX,DX
ARRAYDB13,65,12,97,68,69,70,71,72,73,98,75,76,77
DATAENDS
MOVAX,DATA
MOVDS,AX
CALLDISPLAY;
显示原数字串
CALLXZPX;
大小排序
显示排序后的数字串
JMPEXIT;
退出程序
XZPXPROCNEAR
PUSHAX
PUSHBX
PUSHC