8086 16位汇编数组排序异常:数组未修改疑似栈操作错误
问题定位与修复
核心问题:Swap函数未操作数组
你的Swap函数只是交换了bx和cx寄存器的值,完全没有对传入的数组元素地址进行读写——这就是数组毫无变化的根本原因。Swap的目标应该是交换内存中两个数组元素的内容,而不是仅操作寄存器。
修复后的Swap:
PROC swap push bp mov bp,sp ; [bp+6] = 第一个元素的内存地址,[bp+4] = 第二个元素的内存地址 mov si, [bp+6] mov di, [bp+4] ; 交换两个字节(数组为db类型,每个元素占1字节) mov al, [si] mov ah, [di] mov [si], ah mov [di], al mov sp, bp pop bp ret ENDP swap
FindMin函数的硬编码与逻辑漏洞
- 硬编码数组长度:你用
cmp cx,4固定遍历次数,但数组长度是可变的,应该根据传入的子数组长度判断循环次数。 - 无效的局部变量:
mov al, [bp-2]之后立刻被mov al, [di]覆盖,完全多余;局部变量[bp-4]也没实际作用,直接用寄存器存索引即可。 - 循环顺序错误:
inc cx和inc di的顺序导致第一次循环就跳过了初始元素的比较。
修复后的FindMin(接收子数组起始地址和长度,返回相对索引到min_in_array):
; 输入参数(栈中):子数组长度 → 子数组起始地址 ; 输出:min_in_array = 子数组内最小值的相对索引(从0开始) PROC findMin push bp mov bp, sp mov cx, [bp+6] ; 子数组长度 mov di, [bp+4] ; 子数组起始地址 mov al, [di] ; 初始化最小值为第一个元素 mov bx, 0 ; 初始化最小值索引为0 mov min_in_array, bx dec cx ; 已处理第一个元素,剩余cx-1个元素 jz fin_find ; 长度为1时直接返回 find_loop: inc di inc bx cmp al, [di] jbe next_find ; 当前最小值更小,跳过更新 mov al, [di] ; 更新最小值 mov min_in_array, bx ; 更新最小值索引 next_find: loop find_loop fin_find: pop bp ret ENDP findMin
SortArray函数的逻辑与栈问题
- 未传递子数组长度给FindMin:之前调用FindMin只传了起始地址,导致FindMin无法正确遍历剩余元素。
- 循环次数错误:选择排序只需循环
数组长度-1次,原代码用总长度5循环,最后一次交换无意义。 - 地址计算混乱:原代码操作di时逻辑绕错,应该直接基于数组起始地址计算交换位置。
修复后的SortArray:
PROC sortArray push bp mov bp, sp mov dx, 0 ; 当前排序的起始索引 mov cx, [bp+6] ; 数组总长度 dec cx ; 选择排序循环 size-1 次 sort_loop: mov di, [bp+4] ; 数组起始地址 add di, dx ; 当前子数组的起始地址 push cx ; 保存外层循环的计数器 push cx ; 传入子数组长度(剩余元素数 = 总长度 - dx) push di call findMin pop di pop cx ; 恢复外层循环计数器 ; 计算两个要交换的元素地址 mov si, [bp+4] add si, dx ; 起始位置地址 mov di, si add di, min_in_array ; 最小值位置地址 push si push di call swap pop di pop si inc dx loop sort_loop mov sp, bp pop bp ret ENDP sortArray
主函数的小修正
原数组注释写的should get 1,2,3,6,9,但数组里没有2,修正为正确的预期结果;另外主函数里手动pop bx两次是多余的,函数返回后栈已经平衡:
org 100h jmp start array db 1,9,3,6,3 ; 排序后应为 1,3,3,6,9 min_in_array dw ? start: lea si, array push 5 push si call sortArray mov ah, 0 int 16h ret
内容的提问来源于stack exchange,提问作者PandaMan
相关产品推荐
相关产品推荐

