子程序与模块化程序设计.docx
- 文档编号:4901110
- 上传时间:2022-12-11
- 格式:DOCX
- 页数:15
- 大小:34.22KB
子程序与模块化程序设计.docx
《子程序与模块化程序设计.docx》由会员分享,可在线阅读,更多相关《子程序与模块化程序设计.docx(15页珍藏版)》请在冰豆网上搜索。
子程序与模块化程序设计
课程实验报告
课程名称:
汇编语言程序设计
实验名称:
实验地点:
南一楼804室
指导教师:
李专
专业班级:
学号:
姓名:
同组学生:
报告日期:
成绩:
计算机科学与技术学院
目录
1实验目的与要求1
2实验内容1
3实验过程2
3.1实验目的2
3.1.1设计思想2
3.1.2源程序代码2
3.2实验目的6
3.2.1设计思想6
3.2.2源程序代码6
3.3实验结果12
4实验体会12
1实验目的与要求
(1)掌握子程序参数传递的3种方式,特别是利用堆栈传递参数的方法;
(2)掌握模块化程序设计的方法;
(3)进一步熟悉TD的使用,并加深对常用DOS功能调用的理解;
2实验内容
任务:
编写程序实现类似C语言函数scanf()和printf()的功能:
先从键盘输入一个N1进制的有符号字符串,再以N2进制的形式显示出来,N1和N2由键盘输入。
例如:
InputN1:
16↙
InputN2:
10↙
Inputstring:
-7FFF↙
Output:
-32767(屏幕显示)
提示:
首先需要一个子程序将N1进制的字符串转换为二进制数,然后还需要一个子程序将二进制数转换为N2进制的字符串。
要求:
(1)用子程序scanfAsm实现将N1进制的字符串转换为二进制的有符号数:
子程序参数:
DS:
[SI]指向字符串的首地址(可能有正负号,字符串以0结尾)
BASE=N1(BASE是由主程序在数据段中用DB定义的变量)
(AX)=转换结果
(2)用子程序printAsm实现将二进制有符号数转换为N2进制的字符串,调用printAsm的方法如下:
PUSH需要转换的二进制数
PUSHN2;将二进制数转换为该数制的字符串
PUSH缓冲区段地址;转换结果保存在该缓冲区中
PUSH缓冲区偏移地址
CALLFARPTRprintAsm
ADDSP,8
(3)主程序、子程序scanfAsm、子程序printAsm分别定义在模块mainIO.asm、scanfAsm.asm、printAsm.asm中;
(4)画出2个子程序流程图,给出寄存器、存储单元的分配方法;
(5)对于每种数制,至少输入正负数字符串各一个进行测试。
3实验过程
3.1实验目的
用子程序scanfAsm实现将N1进制的字符串转换为二进制的有符号数
3.1.1设计思想
用一个check函数检查输入的字符串中是否存在非法的字符,如果全部通过,则通过一个循环将其转换为二进制的字符,保存在ax中。
3.1.2源程序代码
.386
datasegmentuse16
tip1db'InputError!
'
rfdb0ah,0dh,'$'
markdb?
basedw?
dataends
stacksegmentuse16stack
db20dup(?
)
stackends
;check,寄存器传参,判断输入字符是否符和进制数
;cl为进制,ch为字符,
;正确时,返回ch为实际数,
;错误时,输出tip1,并返回dos
codesegmentuse16
assumecs:
code,ds:
data,ss:
stack
checkprocfar
subch,'0'
cmpch,10
jgel1;不是数字字符跳转
l4:
;比较ch是否在0-cl
cmpch,0
jgel2
jmpexit2;输入字符小于0
l2:
cmpch,cl
jgel3
jmpexit1
l3:
;输入字符大于进制数
jmpexit2
l1:
;输入字符为字母时
subch,'A'-'0'
;判断是否为字母
cmpch,0
jgel6
jmpexit2;不为字母
l6:
cmpch,26;26个大写字母
jgel5;输入字符不是大写字母
addch,10;'A'代表10
jmpl4
l5:
;判断字符是否为小写字母
subch,'a'-'A'
cmpch,0
jgel7
jmpexit2
l7:
cmpch,26
jll8
jmpexit2
l8:
addch,10
jmpl4
exit1:
;正确时调用
ret
exit2:
;错误时调用
movax,data
movds,ax
leadx,tip1
movah,9
int21h
popcx;清除栈ip
movah,4ch
int21h
checkendp
publiccheck
;scanfAsm,堆栈传参,入栈顺序,ds,si,wordptrbase
;DS:
[si],指向字符串首地址,可有正负号,字符串以0结尾
;Base=n1(db)
;输出ax为转换结果
scanfAsmprocfar
pushbp
movbp,sp
pushsi
pushcx
pushbx
pushds
pushes
movax,data
movds,ax
;获取参数
movcx,[bp+6]
movsi,[bp+8]
movax,[bp+10]
moves,ax
xorax,ax
movbase,cx
movmark,0;用于判断是否为负数
;获取第一个字符,判断是否为符号
;不是符号则继续,是符号则跳过
movch,byteptres:
[si]
cmpch,'-'
jnesl1
incsi
movmark,1
jmpsl3
sl1:
cmpch,'+'
jnesl3
incsi
sl3:
;循环转换
movch,byteptres:
[si]
cmpch,0
jnesl4
jmpsl5
sl4:
callfarptrcheck
movsxbx,ch
imulbase
addax,bx
incsi
jmpsl3
sl5:
cmpmark,1
jnesl2
negax
sl2:
popes
popds
popbx
popcx
popsi
popbp
ret
scanfAsmendp
publicscanfAsm
codeends
end
3.2实验目的
用子程序printAsm实现将二进制有符号数转换为N2进制的字符串
3.2.1设计思想
先通过一个一个循环,将余数逆序保存在一个缓存区中,然后顺序替换目标缓存区的值。
3.2.2源程序代码
.386
numequ20
datasegmentuse16
tabdb'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
bufdbnumdup(?
),'$'
basedw?
dataends
stacksegmentuse16stack
db20dup(?
)
stackends
codesegmentuse16
assumecs:
code,ds:
data,ss:
stack
;调用方法如下
;PUSH需要转换的二进制数
;PUSHN2;将二进制数转换为该数制的字符串
;PUSH缓冲区段地址;转换结果保存在该缓冲区中
;PUSH缓冲区偏移地址
;CALLFARPTRprintAsm
;ADDSP,8
printAsmprocfar
pushbp
movbp,sp
pushax
pushbx
pushes
pushsi
pushdx
pushds
pushdi
movax,data
movds,ax
movsi,[bp+6]
movax,[bp+8]
moves,ax
movbx,[bp+10]
movbase,bx
movax,[bp+12]
xordx,dx
movdi,num-1
;判断是否为负数,是时输出一个负号
cmpax,0
jgel1
negax
movbyteptres:
[si],'-'
incsi
l1:
;循环输出字符
xordx,dx
divbase
movbx,dx
movdl,tab[bx]
;movbyteptres:
[si],dl
movbuf[di],dl
decdi
cmpax,0
jeexit
jmpl1
exit:
movdl,buf[di+1]
movbyteptres:
[si],dl
incdi
incsi
cmpdl,'$'
jneexit
;movbyteptres:
[si],'$'
popdi
popds
popdx
popsi
popes
popbx
popax
popbp
ret
printAsmendp
publicprintAsm
codeends
End
mainIO.asm设计思想:
通过堆栈调用函数的形式调用scanfAsm和printAsm即可。
代码如下:
.386
extrncheck:
far
extrnscanfAsm:
far
extrnprintAsm:
far
datasegmentuse16
tip1db'InputN1:
$'
tip2db'InputN2:
$'
tip3db'InputString:
$'
tip4db'Output:
$'
rfdb0ah,0dh,'$'
n1db?
n2db?
tendw10
inStringdb10
lendb?
db10dup(?
)
outStringdb20dup(?
)
dataends
stacksegmentuse16stack
db200dup(?
)
stackends
codesegmentuse16
assumecs:
code,ds:
data,ss:
stack
start:
movax,data
movds,ax
leadx,tip1
movah,09h
int21h
leadx,inString
movah,0ah
int21h
leadx,rf
movah,09h
int21h
callston
movn1,al
leadx,tip2
movah,09h
int21h
leadx,inString
movah,0ah
int21h
leadx,rf
movah,09h
int21h
callston
movn2,al
leadx,tip3
movah,09h
int21h
leadx,inString
movah,0ah
int21h
leadx,rf
movah,09h
int21h
xorbx,bx
movbl,inString+1
movbyteptrinString[bx+2],0
;调用scanfAsm
pushds
leadx,inString+2
pushdx
movsxcx,n1
pushcx
callfarptrscanfAsm
addsp,6
;调用printAsm
;movax,8001h
;movn2,10
pushax
movsxbx,n2
pushbx
pushds
leabx,outString
pushbx
callfarptrprintAsm
addsp,8
;输出字符串
leadx,tip4
movah,9h
int21h
leadx,outString
int21h
movah,4ch
int21h
;将输入字符串转为数字,保存在ax中
stonproc
movcl,10
xorbx,bx
xordx,dx
xorax,ax
L1:
cmpbl,len
jlcon
jmpexit1
con:
movch,inString[bx+2]
callfarptrcheck
imulten
movsxdx,ch
addax,dx
incbx
jmpL1
exit1:
ret
stonendp
codeends
endstart
3.3实验结果
4实验体会
通过此次试验使我对于汇编语言子程序的编写和调用有了更加清晰的认识,对子程序在内存中物理过程更加清楚。
根据在模块化程序设计思想,我们在编写程序的过程中应当考虑到其他人对我们所编写的子程序的合理调用。
这就涉及到主程序对子程序的调用方式问题。
这个过程通常有两种方法:
一种是直接include加asm文件,这种方法会将asm文件中的所有内容整合成一个asm文件,一般用于宏定义。
另外一种是更常用的public声明和extrn调用,,这种方法写到程序可以在第一步masm编译时,单独编译并通过,但必须在link中将所有的obj文件链接到一起,而且子程序可以有自己的data和stack,用第二种方法时要注意文件尾要加end,但只有入口标签才能接在end后面。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 子程序 模块化 程序设计