汇编语言实现有符号数的冒泡排序及其修进(附选择排序)

一、前言

在学习C语言的过程中,各类排序法,如冒泡排序、选择排序、快速排序等等都是大家熟知的知识。学习汇编语言的过程中,通过实现各类排序法,有助于我们更加熟悉汇编语言的特点,从而掌握汇编语言编程的基本步骤。

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

设备:个人电脑,windows系统下模拟dos环境

  硬盘:D盘 275.69GB(基本数据分区)状态良好

   64位操作系统,基于x64的处理器,windows系统为x64的处理器

   Dos系统:版本号dosbox0.74,汇编工具有masm,link,debug,edit

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

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

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

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

三、实验内容及步骤

未经优化的代码如下:

DATA SEGMENT

BUF DW 0,1,2

N=($-BUF)/2

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

LOOP1:MOV DX,CX

      MOV BX,0

LOOP2:MOV AX,BUF[BX]

      CMP AX,BUF[BX+2]

      JGE L

      XCHG AX,BUF[BX+2]

      MOV BUF[BX],AX

L:    ADD BX,2

      DEC CX

      JNE LOOP2

      MOV CX,DX

      LOOP LOOP1

      MOV AH,4CH

      INT 21H

CODE ENDS

     END START

基本思路不再赘述;

改进后的代码如下:

DATA SEGMENT

BUF DW 3,2,1,0

N=($-BUF)/2

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

LOOP1:

      MOV DX,CX

      MOV BX,0

      MOV SI, 0 ; 初始化标志位为0

LOOP2:

      MOV AX,BUF[BX]

      CMP AX,BUF[BX+2]

      JGE L

      XCHG AX,BUF[BX+2]

      MOV BUF[BX],AX

      MOV SI, 1 ; 标志位设为1,表示发生了交换

L:

      ADD BX,2

      DEC CX

      JNE LOOP2

      CMP SI, 0 ; 判断标志位是否为0

      JE FINISH ;如果标志位为0,说明数组已经排好序,可以直接退出

      MOV CX,DX

      LOOP LOOP1

FINISH:

      MOV AH,4CH

      INT 21H

CODE ENDS

END START

改进解释:

冒泡排序的问题在于,即使已经在中途排好了序,它还是会依照内外两层循环继续走下去,所以想要优化这个流程。我们需要在不再发生交换时提前结束循环。也即这个标志位初始应该为0,如果它在内层循环结束时依旧为0,那么数组已经排好序,无需继续循环,提高了效率。这里我使用了3,2,1,0作为检验,这是一个无需排序的数组,所以应当会在第一次遍历结束后直接退出

三、选择排序

具体原理不再赘述

DATA SEGMENT

BUF DW 0,1,2,3

N=($-BUF)/2

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

      MOV BX,-2

      MOV BP,0;记录第一个数的下标

LOOP1:MOV DI,CX;将计数器的值保存在DI中

      ADD BX,2

      MOV SI,0

LOOP2:MOV AX,BUF[BX]

      MOV DX,BUF[BX]

      CMP DX,BUF[BX+2];将当前数与下一个数比较

      JGE L

      MOV SI,BX

      INC SI

      INC SI ;记录下标

     

L:    ADD BX,2

      DEC CX

      JNE LOOP2

      MOV CX,DI;返回外层计数值,即循环次数

      MOV DX,BUF[SI]

      MOV BX,BUF[BP]

      MOV BUF[SI],BX

      MOV BUF[BP],DX;将最大数与第一个数交换

      INC BP

      INC BP

      MOV DX,0

      LOOP LOOP1

      MOV AH,4CH

      INT 21H

CODE ENDS

     END START

四、总结

我的代码水平并不高,即使实现了需要的功能,代码也十分冗余。汇编语言学习中遇到了很多困难,原因是这一门语言已经很老了,市面上的介绍也比较少,但是总算是也学会了一些皮毛。最终自己能够独立解决简单的编程问题,算是差强人意。代码仅供参考,若有不妥之处还请批评指正。(也请学弟学妹们先自己动手做一下,不要直接借鉴,对于期末考试也是有帮助的)

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
汇编语言符号冒泡排序是一种常见的排序算法,它通过比较相邻的元素并交换位置来实现排序。下面是一个简单的汇编语言符号冒泡排序的示例代码: ```assembly section .data array db 5, 2, 8, 1, 9 ; 待排序的组 length equ $ - array ; 组长度 section .text global _start _start: mov ecx, length ; 将组长度存入ecx寄存器 dec ecx ; ecx减1,用于内层循环比较次 outer_loop: mov ebx, 0 ; 用于标记是否发生交换的标志位 mov edi, 0 ; edi用于内层循环索引 inner_loop: mov al, [array + edi] ; 将当前元素加载到al寄存器 cmp al, [array + edi + 1]; 比较当前元素和下一个元素 jbe no_swap ; 如果当前元素小于等于下一个元素,则跳过交换 ; 交换当前元素和下一个元素 xchg al, [array + edi + 1] mov [array + edi], al mov ebx, 1 ; 设置交换标志位为1 no_swap: inc edi ; 内层循环索引加1 loop inner_loop ; 内层循环 cmp ebx, 0 ; 检查交换标志位是否为0 jne outer_loop ; 如果发生了交换,则继续外层循环 ; 排序完成,输出结果 mov edx, length ; 输出组长度 mov ecx, array ; 输出组地址 mov ebx, 1 ; 文件描述符(stdout) mov eax, 4 ; 系统调用号(write) int 0x80 ; 调用系统调用 exit: mov eax, 1 ; 系统调用号(exit) xor ebx, ebx ; 返回值(0) int 0x80 ; 调用系统调用 ``` 以上代码使用汇编语言实现了无符号冒泡排序算法。它通过两层循环,外层循环控制排序的轮,内层循环进行相邻元素的比较和交换。在每一轮内层循环结束后,检查是否发生了交换,如果没有交换则表示组已经有序,排序完成。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值