在EMU8086中借助recherchemax过程实现数组排序的问题排查
问题:使用recherchemax过程实现数组排序时内存移动操作异常
我尝试用recherchemax过程(用于查找数组最大值)实现数组排序,思路是每次找到最大值后将其放到正确位置,但发现相关内存移动指令无法正常工作,代码如下:
data segment tab db 30h,38h,35h,32h,37h,39h n dw 6 max db ? pos dw ? ends stack segment dw 128 dup(0) ends code segment recherchemax proc near mov di,0 mov al,byte ptr tab[di] mov max,al mov pos,di inc di etq: mov al,byte ptr tab[di] cmp al,max jbe negal mov max,al mov pos,di negal: cmp di,n jae fin inc di jmp etq fin: ret start: mov ax, data mov ds, ax mov es, ax mov cx,6 mov si,offset tab boucle: call recherchemax mov al,max add si,n mov bl, byte ptr [si] mov byte ptr [si],al mov si,0 add si,pos mov byte ptr [si],bl dec n loop boucle mov ax, 4c00h int 21h ends end start
问题原因及修复方案
1. 数组索引越界
原代码中add si,n会导致访问数组外的内存:si初始为tab的偏移地址,n初始值为6,而tab只有6个字节(下标0-5),offset tab + 6已经超出数组有效范围,会破坏未知内存区域的数据。
正确做法是定位到当前未排序部分的末尾,地址应为offset tab + n - 1。
2. 最大值查找的循环终止条件错误
recherchemax中cmp di,n后用jae fin,会导致最后一个元素(下标n-1)未被比较。应调整为inc di后再判断di是否小于n,确保遍历所有元素。
3. 交换逻辑冗余且错误
原交换逻辑绕路且因索引错误无法正确交换最大值和末尾元素,修复后直接定位两个位置的地址完成交换。
修复后的完整代码
data segment tab db 30h,38h,35h,32h,37h,39h n dw 6 pos dw ? ends stack segment dw 128 dup(0) ends code segment recherchemax proc near mov di,0 mov pos,di inc di etq: mov al,byte ptr tab[di] cmp al,byte ptr tab[pos] jbe negal mov pos,di negal: inc di cmp di,n jb etq fin: ret start: mov ax, data mov ds, ax mov es, ax mov cx,6 boucle: call recherchemax ; 定位未排序部分末尾地址 mov bx, offset tab add bx, n dec bx ; 交换最大值位置和末尾位置的元素 mov al, byte ptr tab[pos] mov dl, byte ptr [bx] mov byte ptr tab[pos], dl mov byte ptr [bx], al dec n loop boucle mov ax, 4c00h int 21h ends end start
额外优化
- 移除了不必要的
max变量,直接通过pos访问最大值元素,减少内存操作。 - 简化了查找最大值的逻辑,直接比较当前元素和已记录最大值位置的元素,更高效。
内容的提问来源于stack exchange,提问作者Zahra
相关产品推荐
相关产品推荐

