《计算机原理》实验报告——多重循环程序设计

一、实验目的及要求

1.在以BUF为首址的字存储区中存放有N个有符号数,现需将它们按大到小的顺序排列在BUF存储区中,试编写其程序。要求:

 i   N的数目自己定义,但不要超过20

 ii  要写出编程的思路并画出流程图

 iii 在程序中使用标志位进行程序的优化

2.请画出实验1.6:子程序结构的流程图

二、实验设备(环境)及要求

1.硬件:PC微机,计算机系统Windows

2.软件:DOS系统、EDIT.EXE、汇编MASM.EXE、连接LINK.EXE、调试DEBUG.EXE等应用程序,Windows自带记事本程序

三、实验内容与步骤

冒泡排序

1.冒泡排序程序思路

从第一个数开始依次对相邻两个数进行比较,如前面的数大于后面的数则不进行操作,如果后面的数大于前面的数则将两个数字交换位置。从第一个数开始遍历,若共有N个数字,第一遍需要比较(N-1)次,后面每一遍比较的次数逐次递减,直到所有数字都按从大到小的顺序排列。在比较的过程中,如果有一遍比较时未发生数字的位置交换,则证明所有数字已经按照从大到小的顺序排列,后面无需继续比较,可以直接跳出循环结束程序。程序框图如下。

2.准备被调试程序

DATA	SEGMENT
BUF     DW  12,10,-4,2,-6,-3,5,0,9
	    N = ($-BUF)/2
        FL DB ?  ;设置标志FL,用来判断一趟循环中是否发生位置交换
DATA	ENDS

STACK	SEGMENT STACK
	DB  200 DUP(0)
STACK	ENDS

CODE	SEGMENT
	ASSUME  CS:CODE,DS:DATA,SS:STACK
START:	MOV	AX,DATA
	MOV	DS,AX
	MOV	CX,N  ;装填计数初值
	DEC	CX  ;实际循环次数为N-1次
        MOV     DX,CX
        MOV     FL,0
LOOP1:  LEA     BX,BUF
        MOV     CX,DX
        MOV     FL,0  ;每次循环前将FL置0
LOOP2:	MOV	AX,BUF[BX]
	CMP	AX,BUF[BX+2]
	JGE	L  ;如果前面的数字大于等于后一个数字则不发生换位,直接跳转到L,若要实现无符号数的排序,可以将JGE换为JAE
	XCHG	AX,BUF[BX+2]  ;若前一个数小于后一个数则交换两个数字
	MOV	BUF[BX],AX
        MOV     FL,1  ;如果发生了数字换位就将FL置为1
L:	ADD	BX,2
	DEC	CX
	JNE	LOOP2  ;CX=0跳转LOOP2
	MOV	CX,DX
        CMP     FL,0
        JE      OVER  ;如果FL=0则未发生换位,可以直接跳出循环结束
        DEC     DX
        LOOP    LOOP1
OVER:   MOV     AH,4CH
	    INT	    21H  ;程序终止,返回DOS
CODE    ENDS
        END     START

3.进入DEBUG环境调试

(1)生成obj文件和可执行文件

(2)存储区初始状态

       通过-D可以看到存储的数据,依次存放12,10,-4,2,-6,-3,5,0,9

       如-6补码为1111 1111 1111 1010=FFFAH,存储时低字节存入低地址,高字节存入高地址,故存储时显示FA FF

(3)-U反汇编

     找到一趟循环结束的跳转指令IP=0042

(4)运行至断点

上图为一趟循环结束,最小值移动到最右边,即图中的FAFF(-6),后面的1为标志FL

(5)循环至程序终止

循环进行到倒数第二趟时所有数都已经按从大到小的顺序排列,未发生位置交换,故FL=0,跳出循环结束程序

4.对程序的分析

排序过程中需要遍历N-1次,每次遍历通过前后两个数字交换的方式将最小数移动到最右边,直至所有数字按照从大到小的顺序依次排列。冒泡排序的比较次数 = (n - 1) + (n - 2) + ... + 2 + 1,即:n * (n - 1) / 2,所以冒泡排序的时间复杂度为O(n2)

(二)选择排序

1.选择排序程序思路

从第一个数开始依次向后比较,找到最大的数存起来,在把这个数与最左端的数交换位置,然后对剩余未排序的数字重复此操作,每次都将未排序的数放到这些数中的最左端,最后可以实现数字从大到小排序。

2.准备被调试程序

DATA SEGMENT
	BUF DW 2,10,-4,-2,-6,-3,5,0,9
	N = ($-BUF)/2
DATA ENDS
STACK	SEGMENT STACK
	DB  200 DUP(0)
STACK	ENDS
CODE SEGMENT
	ASSUME CS:CODE,DS:DATA
START:
	MOV AX,DATA
	MOV DS,AX   ;导入数据段数据
	MOV CX,N    ;装填计数初值
	DEC CX        ;实际循环次数为N-1次
	MOV BX,OFFSET BUF  
LOOP2:
	MOV SI,BX   ;分别存入SI,DI
	MOV DI,BX
	PUSH CX
	MOV AX,[BX]   ;将初值存入AX
LOOP1:			;内层循环找出每一趟的最大值
	ADD SI,2      
	CMP AX,[SI]
	JGE NEXT    ;若(AX)>=[SI],则不进行操作,若要实现无符号数的排序,可以将JGE换为JAE
	MOV AX,[SI]   ;否则将较大的值先放入AX
	MOV DI,SI    
NEXT:
	LOOP LOOP1
	XCHG AX,[BX]  ;一趟比较过后,将AX中存放的最大值与最左端未被排序的数交换
	XCHG AX,[DI] 
	ADD BX,2
	POP CX
	LOOP LOOP2
EXIT:
	MOV AH,4CH
	INT 21H
CODE ENDS
	END START

3.进入DEBUG环境调试

(1)生成obj文件和可执行文件

(2)存储区初始状态

通过-D可以看到存储的数据,依次存放2,10,-4,-2,-6,-3,5,0,9

(3)-U反汇编

找到一趟比较结束的跳转指令IP=0028

(4)运行至断点

         上图为一趟比较结束后,找到的最大值被放到最左端,即图中的0A 00(10)

       上图为第二趟比较结束后,在后8个数字中找到的最大值09 00(9),被放到第二趟比较中的最左端,即第二个位置

       后面继续循环,重复此操作

(5)循环至程序终止

       外层循环进行到CX=0时循环终止,结束程序,从上图可以看出9和数字都已经按照从大到小的顺序排列,顺序依次为10,9,5,2,0,-2,-3,-4,-6

4.对程序的分析

每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到全部待排序的数据元素排完。

常见的选择排序可以分为直接选择排序、树形选择排序以及堆排序,这里使用的是直接选择排序。选择排序的交换操作介于0和(n - 1)次之间。选择排序的比较操作为n (n - 1)/ 2次之间。选择排序的赋值操作介于0和3 (n - 1)次之间。直接选择排序的时间复杂度为O(n2)

四、实验结果

1.冒泡排序

       对12,10,-4,2,-6,-3,5,0,9进行排序,结果如上图

2.选择排序

     对2,10,-4,-2,-6,-3,5,0,9进行排序,结果如上图

0A00(10) >0900(9) >0500(5) >0200(2) >0000(0) >FEFF(-2) >FDFF(-3) >FCFF(-4) >FAFF(-6)

3.实验1.6程序框图

见下图

五、分析与讨论

       编写程序之前首先要有一个大概的思路,然后通过画程序框图的方式将这个思路具体化,这里要考虑到寄存器的选用,哪个用作计数器,哪个用作指针。在刚开始绘制程序框图的时候我忽略了一个问题,就是执行loop循环的时候会先将(CX)-1,再判断(CX)是否等于0,这是一个需要注意的地方。

       第二步就是根据程序框图编写程序。首先可以直接套用汇编程序的框架,然后将需要用到的数据和变量填在数据段,代码段的编写根据程序框图完成。在这一步我遇到的问题是寄存器的选用,如果将数据定义为一个字,就应该选用AX等寄存器,而不能使用AL,在指针移位时也要使用+2的指令,而不能使用INC指令。在对照程序框图进行编成的过程中还要注意上面提到的LOOP的问题,如果跳转使用LOOP指令,则前面无需进行DEC CX。

       在对程序进行静态检查后,可以进行上机调试。首先masm和link生成obj和exe文件,在这个过程中可以检查到一些错误,如下图所示。若masm报错,需要对程序进行检查修改,如果link出现没有堆栈段,也可以正常运行。

       在调试的过程中需要配合使用-u,-g和-d,-u可以找到我们想要跳转指令的偏移地址,-g+IP可以直接直接跳转到该条指令,-d可以随时查看数据的存储状态。注意在使用-d时要在后面加0000,才能从0000单元开始显示,否则找不到排序数字存储的区域,出现如下图情况。

     通过编写和修改两种排序程序,我掌握了编写汇编语言程序的基本方法,并且能够熟练使用DOS操作系统的各项指令,通过debug对程序进行动态调试并修改错误。对比两种排序方式,可以发现选择排序的交换次数远少于冒泡排序,由于交换所需CPU时间比比较所需的CPU时间多,所以在数字个数N较小时,选择排序比冒泡排序快。

  • 14
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值