ImageVerifierCode 换一换
格式:DOCX , 页数:15 ,大小:112.41KB ,
资源ID:5447073      下载积分:12 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/5447073.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(汇编实验四子程序设计.docx)为本站会员(b****3)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

汇编实验四子程序设计.docx

1、汇编实验四子程序设计福建农林大学东方学院信息工程类实验报告系: 计算机系 专业: 电子信息工程 年级: 10 姓名: 廖少冰 学号: 1050302103 实验课程: 汇编语言 实验室号:_ 实验设备号: 实验时间: 指导教师签字: 成绩: 实验四 子程序设计1实验目的和要求1、学习子程序的编写,主子程序的调用2、不同模块间程序的调用和调试2实验用的软硬件环境实验的硬件环境是:IBMPC机及其兼容机实验的软件环境是: 操作系统:DOS 2.0以上;调试程序:DEBUG.COM;文本编程程序:EDIT.EXE、WPS.EXE;宏汇编程序:MASM.EXE(或ASM .EXE);连接装配程序:LI

2、NK .EXE;交叉引用程序:CREF.EXE(可有可无)。3实验内容及实验数据记录1、数据段中的3个字符,调用子程序将其逐个显示出来。子程序的功能是显示一个字符。单步执行,观察IP的变化DATA SEGMENT MAG DB ABC DATA ENDS CODE SEGMENT ASSUME CS: CODE, DS: DATA START: MOV AX, DATA MOV DS, AX MOV SI, 0 MOV CX, 3 LL: MOV DL, MAGSI CALL MADD INC SI LOOP LL MOV AH, 4CH INT 21H MADD PROC MOV AH, 0

3、2H INT 21H RET MADD ENDP CODE ENDS END START2、阅读S31.ASM和S32.ASM两个模块中的程序,并分别汇编,然后连接成一个可执行文件S31.EXE。具体步骤如下: MASM S31.ASM(分别汇编) MASM S32.ASM LINK S31 S32 (将两个文件连接成为一个文件名为S31) S31.EXE (运行)3、编程:利用主程序调用子程序,比较BUF1和BUF2缓冲区中不相等的字符,并将不相等的字符显示出来。(也可以将找到的不相等字符逐个显示,用INT 21H的02功能调用)4、编程:子程序搜索指定字符缓冲区中是否有n,如果有用y替代。

4、调用子程序将BUF1,BUF2,BUF3中的n全部用y替代4操作方法及实验步骤 1-1)文本编辑程序保存V1.asm,编译并连接后debug调试V1.exe。跟踪如下u反汇编观察CALL指令所在程序段偏移量为000F而且Call到哪显而易见是0019即Mov AH,02与源程序一致而RET指令偏移量为001D但从中我们并不能得知其具体执行过程。 1-2)t单步跟踪,图为执行CALL指令前各个寄存器的状态及查看SS:IP(d0769:0000)即栈顶内容为零。BP始终都为0实际上直到目前都没用到该堆栈。 1-3)继续单步执行,此时IP指向下一条指令CALL 0019。即执行该指令,结果如下可看到

5、SP变为了FFFE可知执行该指令的同时堆栈处于忙碌的变更中。之后IP直接指向CALL 所指0019。d0769:fffe查看栈顶内容如下高向低读为0012由之前的反汇编得知0012正是INC SI指令的偏移量,而该指令位于Call指令的下一条。 1-4)由此我们推断RET指令的作用就是弹出栈顶内容至IP来使得程序接着运行执行CALL指令后的程序。同样T单步执行观察如下很明显执行RET后IP指向了0012。SP又指向了栈底。得以证实了CALL调用子程序是通过堆栈保护了现场进入子程序,之后再通过RET恢复到了原状态 2-1)单独阅读两个程序模块似乎毫无瓜葛,只知道S32.ASM模块中是实现的是二进

6、制数转化为十六进制数并在显示器上显示的功能。S31.ASM实现的是通过子程序TRAN的调用完成对主程序着中获取的两位非压缩BCD数的二进制转化。按题目要求分别会变S31.asm和S32.asm如下 2-2)分别编辑程序存为S31.asm和S32.asm文件。进入masm目录。汇编连接如下均正常通过。 2-3)运行程序S31.exe结果如下等待输入两位字符:输入两个字符1和2立即就跟出了000C,输入字符4和5跟出了002D,程序实现了将2位非压缩BCD码转化为了16进制数并打印输出到显示器。可见diso子程序虽然在另一个程序段中但在主程序中还是能被CALL唯一和在同一段内 的调用方式不同的是需

7、要指明是段内子程序,还是段外子程序。指令中的NEAR PTR或FAR PTR正是此作用。 3-1)分析题目要求容易得知,程序可分为两部分,一是控制数据缓冲区的数据获取,而自然就是数据处理了亦是题目要求中的子程序实现的功能。首先定义数据缓冲区有BUF1 DB MY NAME IS ZERO! LEN1 EQU $-BUF1 BUF2 DB YOU ARE MY GIRL,RIGHT? LEN2 EQU $-BUF2这里就有一个值得考虑的问题,就是缓冲区内的数据长度不等该怎么处理。对以等长直接下两指针即可方便循环控制。为方便起见,当然取短的不失为是好的选择,在与长的字符串中比较至短字符串长度LEN

8、1结束并输出不等字符后指针DI所指向字符余下部分直接输出。因此有如下示 输出BQ 3-2)因而如何取较短的一者作为循环条件及SI和DI的初始成了问题。比较可取的方法是先将LEN1假设为最短,传送给CX,同时将BUF1送AX,BUF2送BX。然后比较CX与LEN2,分支中处理数据交换。于是有MOV CX,LEN1 MOV AX,BUF1 MOV BX,BUF2 CMP CX,LEN2 JB L SUB CX,LEN1-LEN2 XCHG AX,BX L: MOV SI,AX MOV DI,BX问题得以解决。既然这样设计,则字符显示功能就应该分离出子程序另作为又一个子程序,方便主程序和比较字符的子

9、程序的调用。 3-3)于是有代码如下DATA SEGMENT BUF1 DB MY NAME IS ZERO! LEN1 EQU $-BUF1 ;计算BUF1长度 BUF2 DB YOU ARE MY GIRL,RIGHT? LEN2 EQU $-BUF2 ;计算BUF2长度 DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START: MOV AX,DATA MOV DS,AX MOV CX,LEN1 ;假设BUF1最短送入CX MOV AX,BUF1 ;AX存放短字符串首偏移/ MOV AX,OFFSET BUF1 MOV BX,BUF2 ;BX

10、存放长字符串首偏移/ MOV BX,OFFSET BUF2 ;MOV DH,LEN2-LEN1 ;下一个类似语句仅在分支中忽略了LEN2大于LEN1 CMP CX,LEN2 JB L SUB CX,LEN1-LEN2 MOV DX,CX ;暂时存放两字符串差/ MOV DH,CL XCHG AX,BX ;LEN2较短则交换数据 L: MOV SI,AX ;SI定位较短者 MOV DI,BX ;DI定位较长者 S: CALL CMPP ;调用子程序CMPP INC SI INC DI LOOP S ;比较字符未完成继续 Y: INC DI ;应该移至Call后才正确 MOV CX,DX ; MO

11、V CL,DH并移至Y之前 MOV AL,DI ;MOV DL,DI CALL SHOW ;较长字符串余下部分输出 CMPP PROC MOV AL,SI ;MOV DL,SI CMP AL,DI ;CMP DL,DI JE SKIP CALL SHOW ;字符不等调用子程序输出字符 MOV AL,DI ;MOV DL,DI INT 21H SKIP: RET CMPP ENDP SHOW PROC MOV AH,2 ;子程序调用dos的2号功能 INT 21H RET SHOW ENDP CODE ENDS END START 4-1)要求子程序首先检索字符缓冲区内的N,并用Y替代。首先是各

12、个缓冲区定义如下:DATA SEGMENT BUF1 DB MN name is ZERO! BUF2 DB NOU ARE MN GIRL,RIGHT? BUF3 DB no,you are MN Friend! LEN DB $DATA ENDS 4-2)由于各个缓冲区大小不一,所以各缓冲区大小的获取很重要,它将是每一轮循环的控制参数CX。可将它作为子程序的入口参数,来实现。而另一入口参数自然就是各缓冲区的首字符的偏移量SI。所以子程序实现:Displace PROC S: CMP SI,N JNE NEXT MOV SI,Y NEXT: INC SI LOOP S RET Displac

13、e NEDP 4-3)主程序实现入口参数的初始化过程,所以有BUF1的实现,其它如是: MOV CX,BUF2-BUF1 ;一直犯同样的错误 MOV SI,BUF1 ;CX初始化字符串长度,SI初始为字符串入口 CALL Displace ;调用Displace子程序 4-4)所以有最初代码如下为便于观察,处理后打印输出各字符串DATA SEGMENT BUF1 DB MY NAME IS ZERO! BUF2 DB NOU ARE MN GIRL,RIGHT? BUF3 DB NO,YOU ARE MY FRIEND! LEN DB $ DATA ENDS CODE SEGMENT ASSU

14、ME CS:CODE,DS:DATA START: MOV AX,DATA MOV DS,AX MOV CX,BUF2-BUF1 MOV SI,BUF1 CALL Displace MOV CX,BUF3-BUF2 MOV SI,BUF2 CALL Displace MOV CX,LEN-BUF3 MOV SI,BUF2 CALL Displace MOV AH,4CH INT 21H Displace PROC S: CMP SI,N JNE NEXT MOV SI,Y NEXT:MOV DL,SI CALL Show INC SI LOOP S RET Displace NEDPShow

15、PROC MOV AH,2 INT 21H RET Show EDNP 5实验数据处理和分析 3-1)编辑最初代码编译出错更正错误MOV AX,BUF1为 MOV AX,OFFSET BUF1 MOV BX,BUF2为 MOV BX,OFFSET BUF2及录入错字,正常通过编译。运行程序出错如下:显然忘了退出到dos界面是一个原因,但不是主要原因。检查程序发现对于较长字符串的余下部分的处理忘了循环。修正后出现如下错误:修改MOV 4CH 为MOV AH,4CH重新编译。运行结果仍旧如上不停打印字符,显然问题很大。 3-2)还是单步跟踪来找错,debug V3.exe进入debug环境调试V3

16、.exe。如图发现虽然调用了dos的2号输出字符功能,但把本该传送给DL的字符错传给了AL,更正之。并替换之前的DX的使用。终于输出如下结果,为了便已对比,为程序添加换行输出功能。 4-1)编辑程序代码,编译出错,安提示定位到错误处修改之。没引起注意,还是同样的错误, MOV CX,BUF2-BUF1 、MOV SI,BUF1 修改为 MOV CX,OFFSET BUF2-BUF1 、MOV SI,OFFSET BUF1 为了引以为戒,这以后干脆直接用LEA指令,以避免事后犯同样的错误。而Constant expected不知到是否和程序指令冲突了定义还是怎么,先修改之为LENTH。错误23和

17、25行均容易更正。指定内存大小BYTE PTR即可。 4-2)之后才发现程序段未下结束标记修改之,重新编译如下看来其它错误并非由以上引起。同时LENTH还是不行。所以猜想是后边的DB问题,恍然大悟,这里无须开辟空间,直接用伪指令EQU即可。修改后:LEN EQU $。重新编译。至于后面的问题是由于修改之前的初始化过程LEA又犯了其它错误,LEA 指令将地址载入目的操作数。可是操作数明明可以是表达式的,为什么提示当前模式非法呢。 4-3)暂时用原始方法修改回来:MOV CX,OFFSET BUF2-BUF1,其它同。可又出现了如下错误:17行中 MOV CX,LEN-BUF1提示操作数不在同一段

18、内或是常量,对比之前(上一题)的使用,我们忽略了这样一个问题,由于EQU并没在内存开辟新空间,为此将LEN视为常量,之前我们都是常量表达式出现,所以未出错。这里BUF1是地址即内存操作数,所以猜想问题可能处在此处。修改EQU 指令为LEN EQU $-BUF3,同时修改指令MOV CX,LEN-BUF3为MOV CX,LEN,问题应该可以解决。31和36是子程序的标识,想是违反了命名规则。修改为大写一试,错误并非由此引起。仔细观察子程序的定义,原来是ENDP错写成EDNP。修改之正常通过编译并连接运行。 4-4)经以上修改,最终完整程序代码如下DATA SEGMENT BUF1 DB MN n

19、ame is ZERO! BUF2 DB NOU ARE MN GIRL,RIGHT? BUF3 DB no,you are MN Friend! LEN EQU $-BUF3 DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START: MOV AX,DATA MOV DS,AX MOV CX,OFFSET BUF2-BUF1 LEA SI,BUF1 ;CX初始化BUF1长度,SI初始为BUF1入口 CALL RE ;调用子程序进行字符检索和替换 MOV CX,OFFSET BUF3-BUF2 LEA SI,BUF2 ;CX初始化BUF2长度,SI

20、初始为BUF2入口 CALL RE ;调用子程序进行字符检索和替换 MOV CX,LEN LEA SI,BUF3 ;CX初始化BUF3长度,SI初始为BUF3入口 CALL RE ;调用子程序进行字符检索和替换 MOV AH,4CH INT 21H ;退出到DOS界面 RE PROC S: CMP BYTE PTR SI,N ;检索字符N JNE NEXT MOV BYTE PTR SI,Y ;找到N则替换为Y NEXT: MOV DL,SI ;将每一个遍历字符传送给DL准备显示 CALL SHOW ;显示字符的子程序 INC SI LOOP S RET RE ENDP ;字符处理操作子程序

21、SHOW PROC MOV AH,2 INT 21H RET SHOW ENDP ;子程序调用DOS的2号显示功能 CODE ENDS END START 6. 实验结果3)对比字符串得知结果比较部分正确,但”RIGHT?“部分只有输出I。仔细检查代码发现在给CL赋值前CH并未初始化为0。在Y:前添加MOV CH,0;修改之,但不是问题所在,忽略了一个很大的问题就是由于CX是在分支里保存两串差值,导致了在LEN1小于LEN2时并没给CX第二次初始化为差值,所以有了该问题。因此在MOV BX,OFFSET BUF2后添加指令MOV DH,LEN2-LEN1,将MOV CL,DH提前出Y之上。修改

22、后最终还露了R,原因就是进入余下字符串前DI多加了1,将INC DI移动至CALL之后,重新编译运行的结果正确如下:4)运行程序输出正确结果,至此该程序实现了所设计的功能。7. 质疑,建议,问题讨论,总结在前几次实验的基础与学习中不断的吸取教训,此次实验完成的很顺利,设计的逻辑很少出现问题,唯一应该引起注意的是指令的语法规则在这次实验中是阻碍实验前行的一大障碍,粗心大意的编辑程序没有保持分析设计需求时的严谨态度,给自己添了原本不该出现的不少麻烦。总之几次实验下来,受益匪浅,不仅是巩固了理论知识,还很大程度上提升了我分析并解决问题的能力,更重要的是每一次实验中的羁绊让我对生活和学习的态度的着重要性有了新的认识。这将会是我人生中的一大财富。

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1