You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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函数的硬编码与逻辑漏洞

  1. 硬编码数组长度:你用cmp cx,4固定遍历次数,但数组长度是可变的,应该根据传入的子数组长度判断循环次数。
  2. 无效的局部变量:mov al, [bp-2]之后立刻被mov al, [di]覆盖,完全多余;局部变量[bp-4]也没实际作用,直接用寄存器存索引即可。
  3. 循环顺序错误: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函数的逻辑与栈问题

  1. 未传递子数组长度给FindMin:之前调用FindMin只传了起始地址,导致FindMin无法正确遍历剩余元素。
  2. 循环次数错误:选择排序只需循环数组长度-1次,原代码用总长度5循环,最后一次交换无意义。
  3. 地址计算混乱:原代码操作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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 18:20:28