汇编实验三分支循环程序设计.docx

上传人:b****4 文档编号:4344202 上传时间:2022-11-30 格式:DOCX 页数:18 大小:273.29KB
下载 相关 举报
汇编实验三分支循环程序设计.docx_第1页
第1页 / 共18页
汇编实验三分支循环程序设计.docx_第2页
第2页 / 共18页
汇编实验三分支循环程序设计.docx_第3页
第3页 / 共18页
汇编实验三分支循环程序设计.docx_第4页
第4页 / 共18页
汇编实验三分支循环程序设计.docx_第5页
第5页 / 共18页
点击查看更多>>
下载资源
资源描述

汇编实验三分支循环程序设计.docx

《汇编实验三分支循环程序设计.docx》由会员分享,可在线阅读,更多相关《汇编实验三分支循环程序设计.docx(18页珍藏版)》请在冰豆网上搜索。

汇编实验三分支循环程序设计.docx

汇编实验三分支循环程序设计

福建农林大学东方学院信息工程类实验报告

系:

计算机系专业:

电子信息工程年级:

10

姓名:

学号:

1050302103实验课程:

汇编语言

实验室号:

_______实验设备号:

实验时间:

指导教师签字:

成绩:

实验三分支循环程序设计

1.实验目的和要求

1、学习调试程序,查找逻辑错误;

2、学习分支语句的编程和调试;

3、学习循环语句的编程和调试。

2.实验用的软硬件环境

实验的硬件环境是:

IBM—PC机及其兼容机

实验的软件环境是:

操作系统:

DOS2.0以上;调试程序:

DEBUG.COM;文本编程程序:

EDIT.EXE、WPS.EXE;宏汇编程序:

MASM.EXE(或ASM.EXE);连接装配程序:

LINK.EXE;交叉引用程序:

CREF.EXE(可有可无)。

3.实验内容及实验数据记录

1.有10个数,统计正数的个数,存放在变量M中中。

经过汇编后,形成EXE文件。

在DEBUG中,先用G=0命令执行程序,用D命令查看M单元的内容,会发现结果不正确。

用单步执行命令T=0,单步执行程序,查找程序中的逻辑错误,注意每一次循环中AL寄存器中值的变化是否正确。

(AL寄存器中存放正数的个数)

DSEGSEGMENT

MSGDB4,-2,-6,0,5,67,8,-3,5,6

MDB?

DSEGENDS

CSEGSEGMENT

ASSUMECS:

CSEG,DS:

DSEG

START:

MOVAX,DSEG

MOVDS,AX

MOVCX,10

MOVAL,0

LEASI,MSG

L1:

MOVBL,[SI]

CMPBL,0

JBENEXT

INCAL

NEXT:

INCSI

LOOPL1

MOVM,AL

MOVAL,0

MOVAH,4CH

INT21H

CSEGENDS

ENDSTART

 

2.数据段中是一组无符号数,将最小数存放在M单元中。

按上题方法查找一处逻辑错误。

DSEGSEGMENT

MSGDB13,15,7,25,24

MDB?

DSEGENDS

CSEGSEGMENT

ASSUMECS:

CSEG,DS:

DSEG

START:

MOVAX,DSEG

MOVDS,AX

MOVCX,4

MOVAL,MSG

MOVSI,OFFSETMSG+1

L1:

CMPAL,[SI]

JBNEXT

MOVAL,[SI]

NEXT:

LOOPL1

MOVM,AL

MOVAL,0

MOVAH,4CH

INT21H

CSEGENDS

ENDSTART

 

3.编程:

在首地址为BUF开始的内存单元中存有10个字节数,求其中0的个数,并将结果存于RESULT中。

4.编程:

,Ai,Bi为字节型无符号数,分别存于NUM1和NUM2开始的连续存储单元中,结果存于REST单元中。

4.操作方法及实验步骤

1)编辑代码,编译连接均可通过,亦能正常运行。

DSEGSEGMENT

MSGDB4,-2,-6,0,5,67,8,-3,5,6

MDB?

DSEGENDS

CSEGSEGMENT

ASSUMECS:

CSEG,DS:

DSEG

START:

MOVAX,DSEG

MOVDS,AX

MOVCX,10

MOVAL,0

LEASI,MSG

L1:

MOVBL,[SI]

CMPBL,0

JBENEXT

INCAL

NEXT:

INCSI

LOOPL1

MOVM,AL

MOVAL,0

MOVAH,4CH

INT21H

CSEGENDS

ENDSTART

查看list文件得知M单元偏移量为000A,如图:

g命令运行后,d命令查看(d1415:

000A)得知M中值为09即是正数有9个,显然是不正确的如图

2)同一编辑如下代码进行编译连接运行均正常;

DSEGSEGMENT

MSGDB13,15,7,25,24

MDB?

DSEGENDS

CSEGSEGMENT

ASSUMECS:

CSEG,DS:

DSEG

START:

MOVAX,DSEG

MOVDS,AX

MOVCX,4

MOVAL,MSG

MOVSI,OFFSETMSG+1

L1:

CMPAL,[SI]

JBNEXT

MOVAL,[SI]

NEXT:

LOOPL1

MOVM,AL

MOVAL,0

MOVAH,4CH

INT21H

CSEGENDS

ENDSTART

由指令MSGDB13,15,7,25,24

MDB?

可计算0005为M的的偏移量。

如图,g命令运行后,d命令查看(d1415:

0005)知M中值为0DH=13即最小的数是13,显然不正确。

3)

3.1据题意有如下要求

a定义:

首地址BUF,结果RESULT

b数据:

10个字节数

c实现:

查找0的个数

3.2分析满足要求

满足a&b有:

BUFDB4,-2,-6,0,5,0,8,-3,5,0

RESULTDB?

实现c:

MOVCX,10;控制循环次数

MOVAL,0;AL用于存放临时个数,清零

CMMP:

CMP[SI],0;比较[SI]所指与0

JNENEXT;[SI]所指不等0跳入NEXT标号所指指令

INCAL;[SI]所指等于0,AL加1

NEXT:

INCSI;指针下一指向下一个即将比较的数

LOOPCMMP;循环比较直至CX=0;

 

3.4最初程序代码

DATASEGMENT;数据段DATA开始

BUFDB4,-2,-6,0,5,0,8,-3,5,0;分配字节空间首地址BUF

RESULTDB?

;存放结果

DATAENDS;数据段DATA结束

CODESEGMENT;代码段CODE开始

ASSUMEDS:

DATA,CS:

CODE;DATA,CODE对应挂钩DS,CS

START:

MOVAX,DATA;程序入口

MOVDS,AX;数据段装入

MOVCX,10;初始循环次数

MOVAL,0;AL用于存放0的个数,初始为0

CMMP:

CMP[SI],0;当前指针指向的数据与0比较

JNENEXT;所指数据不等于0跳至NEXT标号处指令

INCAL;相等则AL加1

NEXT:

INCSI;NEXT入口,指针加1下移指向下一个数

LOOPCMMP;进入循环CMMP,继续比较当前数

MOVRESULT,AL;将结果传送至RESULT中

MOVAL,0;AL清零

MOVAH,4CH

INT21H;调用dos返回dos界面功能

CODEENDS;代码段CODE开始

ENDSTART;程序结束

4)

4.1据题意有如下要求

a存在两组数据每组8个,均为无符号字节数

b每组数据分别以NUM1、NUM2为首地址,结果存放在REST中

c实现两组数据两两相乘后共8组数据,最终求总和

4.2分析处理满足要求

满足a&b:

NUM1DB1,2,3,4,5,6,7,8

NUM2DB8,7,6,5,4,3,2,1

RESTDW?

(由于结果可能很大故而开辟word空间)

实现c:

首先是进行两两相乘,可以分别用一指针SI,DI同时自上而下取数进行相乘并将结果临时存放于AX,其次将下一次(当前)结果与AX中上一次结果相加,通过循环便可达到实现要求c中的功能,由于第一次结果的存放不再循环之内,可以将其单独列出,这样难免显得程序冗长,拖沓。

因此可以优化其,将AX先初始化为0,把第一次相乘也列入循环中。

问题便可以很好得到解决。

这里有一个问题就是简单的通过SI和DI来进行相乘时忽略了一个问题就是两个操作数不能同时为内存单元的数,因此必须借助于寄存器临时存储其中一个数。

而AL在每一次乘法操作时均被作为隐含操作数而用到因而可直接由AL来存放其中一个数,而存放和的AX这里应由其他寄存器暂代之如BX。

所以优化上图后如下:

DI

4.3根据以上设想设计流程图:

(loop的错误理解导致了这里循环的控制上有问题,其中的注

(1)应该放在注

(2)之后loop之前)

4.4最初程序代码(错误)

DATASEGMENT;数据段DATA开始

NUM1DB1,2,3,4,5,6,7,8;第一组数分配字节空间首地址NUM1

NUM2DB8,7,6,5,4,3,2,1;第二组数分配字节空间首地址NUM2

RESTDW?

;存放结果

DATAENDS;数据段DATA结束

CODESEGMENT;代码段CODE开始

ASSUMEDS:

DATA,CS:

CODE;DATA,CODE对应挂钩DS,CS

START:

MOVAX,DATA;程序入口

MOVDS,AX;数据段装入

MOVAX,0;AX清零

MOVBX,0;BX清零

LEASI,NUM1;将NUM1首地址传送给SI

LEADI,NUM2;将NUM2首地址传送给DI

NEXT:

ADDBX,AX;BX<—AX+BX

MOVAL,[SI];将[SI]所指单元数据传送给AL

MUL[DI];[DI]所指单元数据与AL相乘结果存放在AX

INCSI;指针SI下移,指向NUM1下一个数

INCDI;指针DI下移,指向NUM2下一个数

LOOPNEXT;循环跳至NEXT标号处直至CX自减至0

MOVAH,4CH

INT21H;调用dos返回dos界面功能

CODEENDS;代码段CODE开始

ENDSTART;程序结束

5.调试过程

1)

1.1单步调试程序跟踪找到程序的错误。

如图:

第一次调入[si]=04到BL并进行BL与0比较指令由当前的1416:

0013执行后执行0015指令并没有立即跳至0017指令INCAl可知第一次比较得与正确处理执行正数个数加一,指针下移操作

1.2进入循环继续跟踪

调入BL第二个数[si]=-2=FEH,再一次比较0此时符合条件JBE中的below即小于应该跳过0015指令执行0017指令INCSI,可从跟踪结果看到0015指令INCAl依然被执行了,结果当然是正数个数AL=2多加了1不符合实际,如图:

由此已经找到了出错位置即在此无需继续跟踪。

1.3分析并修改错误

我们知道-2显然符合“小于(below)或者等于(equal)零”的条件,为什么程序却判断-2比零大呢,可知因该句条件并没错语法上也正确,现在唯一的问题给忽略了就是符号了,我们知道数据的存储方式是补码形式,-2的补码为FE而程序条件是BE是对无符号数的操作FE自然是大于0了,由此我们改该指令为有符号操作即JLENEXT或者JNGNEXT,重新编译连接并运行程序最终得正确结果6。

2)

2.1单步调试找到错误

t单步跟踪得到如图在执行调入第一个数到AL后并比较[SI]如图[SI]是01即指向数15,由代码可知此时符合JMP条件B(below)跳转至0014指令(段内)

LOOPL1即进入循环进行下一次比较CMPAL[SI],这里可以看到[SI]依旧是01仍指向15,并没有下移,由此可知程序出错在于[SI]未能下移指向下一个即将要比较的数。

从代码上看也容易得知程序至终都未曾移动[SI]指向。

2.2分析并改错

结合程序代码和题目要求,为了找到最小的数并把他存放在M中,程序基本完成了比较部分和存放功能,唯一的错误是在[SI]的移动未实现,可知在进入循环L1,CMP比较之前因该找到下一个比较的数,而无论比较结果如何下移[SI]操作均需要执行到,因此在NEXT:

里LOOPL1之前添加INC[SI]实现指针自加功能。

具体如下:

……

NEXT:

INCSI

LOOPL1

……

3)

3.1编译以上代码出错提示未能通过,出错如下:

提示11行中操作数未指定大小,查看代码知[SI]为内存单元数据,必须指定大

小是byte还是word。

3.2修改其为:

CMPBYTEPTR[SI],0重新编译,

如图已能顺利通过编译并连接。

3.3进入debug环境

u命令反汇编得知数据段地址076A,RESULT偏移量000A如图

4)

4.1编译最初代码未能通过提示如下图:

4.2分析并改错

第10行超出内存范围,查看代码为:

可知指令并没错,错误在于注释中的“;”应该为“;”后面的随之修改后,重新编译,依然存在错误如图提示未指定操作数大小:

我们知道在数据传送指令中有目的操作数若是内存单元数据和源操作数是立即数时必须指定大小,而若有一是寄存器数据是可无需指定。

疏忽了在单操作数的乘除指令也同样必须指定大小使之位数一致。

为什么出现这样情况可想而知因为乘除指令的隐含操作数所在寄存器可能是AL或AX,其选择决定于源操作数的位数。

因此修改原指令为“MULBYTEPTR[DI]”。

继续重新编译终于顺利通过编译并连接如图:

4.3debug调试检查结果

g运行程序,要进行d查看时才发现忘了将结果传送给REST,在原代码LOOP指令后添加指令:

MOVRESTBX,重新回到编译阶段,继续编译,还好正常通过了。

完成以上操作后,u反汇编得到数据段首地址076A和REST偏移量0010后,d076a:

0010查看REST中内容为6A8C=(6A为高地址所在)如图:

通过计算器计算得120对比之得知结果不正确。

4.4再次分析并改错

结合流程图仔细浏览推敲程序,基本上并没问题,最终结果如此大,一个可能便是加上了不必要即定义段之外的数据,首先想到的是所用寄存器的初始化问题,检查之均无误(还是漏了检查CX);其次是一个严重的问题,可能是循环超出了范围(在初始化了CX后,由循环控制理解错误导致),核实代码果真是这样,在第一次执行到NEXT指令时不是由LOOP跳转过来的而此时SI和DI均已经指向了各自数据段首,在执行第一次LOOP时SI,DI执行了加1操作,CX这才减1,而CX减至1时,SI和DI均已指向了最后一个数,最后结果便是加上了[0008]*[0011]的值。

T单步跟踪验证如下:

看来还是没仔细的检查,CX=45竟忘了初始化为8了。

流程图有了,可代码中却遗漏了。

所以之前的猜想可能是错的,先修改之(在MOVAX,0之前添上指令MOVCX,8)。

重新编译连接运行,查看一下结果是70相比正确结果少了8。

 

T命令跟踪之:

如上图,第一组乘积8正确加到BX;可以推断是最后一组乘积遗漏了。

 

跟踪发现至CX=1时,LOOP并没有执行到如下图,看来是自己理解错了,LOOP是先执行CX自减操作,再判断CX是否为零才执行跳转与否的。

因此可以有两种修改方法,一是将CX初始为9,这样避免大幅度修改代码。

而修改代码也不难,错误的原因是ADDBX,AX放在了AL*[DI]前导致少加了一次。

直接将其移到MUL[DI]之后便可。

这里选择后者虽然修改前面的流程图麻烦,给自己个教训,好下次别在这“想当然”的地方再摔倒。

 

6.实验结果

以下均已在debug环境中。

1)g运行程序,d1415:

000A查看M内容为06即有6个是正数正确,如图

2)g运行程序,d1415:

0005查看M内容为07即最小数是7正确,如图

3)g运行程序,d076a:

000a查看RESULT内容为03即有3个数为0正确,如图

4)修改后重复以上步骤得到最终结果为78H=120答案正确如下图:

7.总结,质疑,建议,问题讨论

通过此次实验才发现自己有多么的不足,题目并不难甚至可以说是很简单。

可就这么简单的几道题由于自己对一些指令没有深透的理解,给自己找了不少苦头,一二题很容易跟踪就可以找到出错位置分析修改之。

至于第三题中未能一次编译通过是自己形而上学没有牢记操作数位数一致的指令规则。

一个晚上大半时间是死在了最后一题上。

先是又一次犯了第三题中同样的错误,原因是自己并没有真正深入理解操作数位数一致的规则,因单操作数而忽略了它,光是记住还是不行,该错误的再次出现让我深刻理解了该规则,希望以后仍铭记。

后是CX忘了初始化,忘了,添上了就没话说,竟然一直自以为是的认为已经初始化过了而把自己引向了另一个方向,胡乱猜了一大堆可能性,引自己到了另一胡同里。

直到debug调试T跟踪后才发现,竟是简单的CX未初始化,而LOOP的理解错误的的确确给自己添了不少麻烦,不过通过T跟踪很快就发现了。

此次实验虽然磕磕绊绊的,但很大程度上提升了我的分析问题解决问题的能力,更重要的是让我的思维更开放了,如最后一题的羁绊,虽然猜想错误了,但让我在以后同类的问题中有了个预先的警示。

并且深入问题后让我发现,一个问题牵扯出了没有发生但该注意的其他问题,如在最后一题我所犯错误的修改上,第一中改法可以(调试过),是因为在该题中0011所指向的也是数据,并且在该数据段内。

而如果REST在其他地方定义的话,或者说0010已经是该数据段结尾了,那么第一种改法很可能就会是错的了。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 解决方案 > 学习计划

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

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