8086汇编冒泡排序子程序设计程序
一、题目需求分析
1 任务说明
(1)程序背景
① 数据段首字节存放学生人数20,其后连续20个字节为汇编课程成绩数据。
② 需自主编写sort冒泡排序子程序,对现有成绩数组进行升序排序,排序结果直接覆盖存储在原数据内存区域。
(2)子程序规范
① 入口参数:DS:BX为待排序成绩数组首地址,CX为待排序数据总个数。
② 出口参数:无,采用原地排序方式,直接修改原数组数据。
③ 排序算法:采用标准冒泡排序算法,实现成绩从小到大升序排列。
(3)主程序预置逻辑
① 读取数据段偏移地址0处的数据,获取学生总人数并送入CX寄存器。
② 对BX寄存器赋值为1,指向第一个有效成绩的存储地址。
③ 调用自定义sort排序子程序完成数组排序,执行完成后正常退出程序。
2 冒泡排序原理
(1)外层循环控制排序轮次
① 包含n个元素的数组,最多需要执行n-1轮冒泡排序。
② 每一轮排序都会将当前未排序区域内的最大值,通过相邻比较交换冒泡到末尾,完成末尾元素有序。
(2)内层循环完成相邻元素比较交换
① 从数组起始位置开始,依次两两比较相邻字节数据。
② 若前一个数据大于后一个数据,立即交换两个内存单元的值,实现升序排序规则。
(3)就地存储
① 程序不额外开辟内存空间,所有比较、交换操作均在原数据段完成,直接覆盖原始数据。
二、完整汇编程序
assume cs:cseg,ds:dseg,ss:sseg
sseg segment stack
dw 100H dup (?)
sseg ends
dseg segment
db 20 ;数据个数
db 98,61,57,82,89,73,61,58,53,54
db 84,78,70,64,84,63,76,84,83,86
dseg ends
cseg segment
start:
mov ax, dseg
mov ds, ax
mov cl, ds:[0]
mov ch, 0 ;cx = 数据总数20
mov bx, 1 ;成绩起始偏移地址
call sort
mov ax, 4c00h
int 21h
;子程序名:sort
;功能:对从DS:(BX)开始的(cx)个字节升序冒泡排序
;入口:DS:BX=数组首地址,CX=元素个数
;出口:数组就地排序,无返回参数
sort:
(1)保护现场
① 保存用到的寄存器BP、SI、DI、AX、DX,避免破坏主程序数据。
push bp
push si
push di
push ax
push dx
(2)设置外层循环计数器
① 元素个数送入BP,外层循环执行次数为数据个数减一。
mov bp, cx
dec bp ;外层循环次数n-1
outer:
(3)内层循环初始化
① SI为数组遍历指针,每一轮冒泡从头开始比较元素。
mov si, bx
mov di, cx ;内层循环次数随轮次递减
dec di
inner:
(4)取出相邻两个数进行比较
mov al, [si]
mov dl, [si+1]
cmp al, dl
jbe no_swap ;前数≤后数,无需交换
(5)前数更大,交换两个单元的值
mov [si], dl
mov [si+1], al
no_swap:
inc si ;指针后移,比较下一对元素
dec di
jnz inner ;内层循环未结束则继续比较
dec bp
jnz outer ;外层循环未结束则开启下一轮冒泡
(6)恢复所有寄存器现场
pop dx
pop ax
pop di
pop si
pop bp
ret
cseg ends
end start
三、核心代码逻辑说明
1 现场保护机制
(1)寄存器占用说明
① 子程序运行过程中会修改BP、SI、DI、AX、DX寄存器数值,为避免覆盖主程序原始数据,进入子程序后统一压栈保存。
② 子程序执行完毕后,按先进后出原则对应出栈恢复寄存器数据,保证主程序运行不受影响。
2 双重循环结构
(1)外层循环功能
① 外层循环控制整体冒泡轮次,n个元素最多执行n-1轮,保证全部元素有序。
(2)内层循环功能
① 内层循环负责相邻元素两两对比交换,每一轮外层循环结束,当前最大值自动排序至未排序区域末尾。
② 每完成一轮冒泡,有序元素数量增加,内层循环比较次数逐轮递减,减少无效运算。
3 内存交换操作
(1)数据交换方式
① 借助AL、DL通用寄存器暂存相邻两个内存单元的成绩数据,避免数据覆盖丢失。
② 直接通过MOV指令修改原数据段内存单元数值,实现原地交换,无需额外占用内存空间。
4 寻址方式
(1)内存寻址规则
① BX寄存器固定作为成绩数组的基地址,定位数组起始位置。
② SI寄存器作为动态偏移指针,实现逐字节遍历数组,采用寄存器间接寻址方式读取和修改内存数据。
四、程序调试验证方案
1 调试工具:DEBUG
(1)断点调试操作
① 将编译链接生成的EXE程序载入DEBUG工具,在调用sort子程序的位置设置断点。
② 单步进入子程序,跟踪SI指针偏移过程,实时观察相邻内存单元的数据变化与交换过程。
③ 子程序执行完毕后,查看数据段DS:01起始的连续20个字节数据,验证排序结果。
2 人工核对
(1)原始成绩数据
① 98,61,57,82,89,73,61,58,53,54,84,78,70,64,84,63,76,84,83,86
(2)程序运行后升序结果
① 53,54,57,58,61,61,63,64,70,73,76,78,82,83,84,84,84,86,89,98
(3)验证结论
① 程序排序结果与人工升序排序结果完全一致,排序功能准确无误。
五、程序优缺点总结
1 优点
(1)编程规范严谨
① 严格遵循8086汇编子程序编写规范,入口出口参数明确,寄存器现场完整保护,模块化程度高。
(2)内存利用率高
① 采用原地冒泡排序算法,不额外开辟数据存储空间,仅通过寄存器中转数据,内存占用极小。
(3)逻辑清晰易懂
① 双层循环结构贴合经典冒泡排序原理,代码分层清晰,注释完整,便于理解、调试与修改。
(4)贴合题目要求
① 排序结果直接覆盖原数据区,完全满足题目就地存储的设计要求。
2 可优化方向
(1)优化无效循环
① 可增设排序标志位,若某一轮冒泡中未发生任何数据交换,证明数组已完全有序,可提前终止循环,提升运行效率。
(2)拓展排序规则
① 可通过修改条件跳转指令,将升序排序改为降序排序,仅需将jbe指令替换为ja指令即可,适配更多排序场景。
