NASM环境下冒泡排序代码运行异常的原因排查求助
问题分析与修复方案
你的代码核心问题是字节数组和双字访问不匹配,具体问题和修复步骤如下:
1. 数组访问方式错误
你定义的arr是db(字节类型,每个元素占1字节),但代码中用esi*4计算偏移量,这是按双字(4字节)访问内存,导致一次读取4个连续字节的内容。比如第一个元素10(0xA)加上后面三个字节12、5、3,组合成0x03050C0A(十进制50662410),这就是你调试时看到的错误值。
修复:所有数组访问的偏移量改为arr + esi(每个元素占1字节,esi自增1对应下一个元素),无需乘4。
2. 排序操作的寄存器类型错误
当前用eax、ebx(32位寄存器)存储字节元素,会读取多余字节,交换时还会覆盖相邻元素。应该用8位寄存器al、bl操作单个字节。
3. 打印循环的逻辑错误
原打印循环中,mov eax, [arr + esi*4]只在循环开始执行一次,后续循环未重新读取当前esi对应的元素;且栈清理的计算逻辑有误。
修正后的完整代码
section .data arr db 10, 12, 5, 3, 18, 9, 15, 7, 11, 21 len equ 10 msg db '%d, ', 0 section .text extern printf global main main: mov ebp, esp; for correct debugging mov ecx, len dec ecx outerloop: mov esi, 0 mov edx, ecx innerloop: ; 读取当前字节和下一个字节到8位寄存器 mov al, [arr + esi] mov bl, [arr + esi + 1] cmp al, bl jge movingon ; 交换两个字节元素 mov [arr + esi], bl mov [arr + esi + 1], al movingon: inc esi dec edx jnz innerloop dec ecx jnz outerloop printloop: mov ecx, len mov esi, 0 print: ; 将字节零扩展到32位寄存器,避免符号位或垃圾值问题 movzx eax, byte [arr + esi] push eax push msg call printf ; 即时清理printf的栈参数(每次调用压入两个4字节参数) add esp, 8 inc esi dec ecx jnz print ret
额外说明
- 用
movzx将字节零扩展到32位寄存器eax,确保printf的%d能正确解析无符号字节值,避免符号扩展或高位垃圾值导致的打印错误。 - 每次调用
printf后即时清理栈,比最后一次性清理更清晰,也能避免计算错误。
内容的提问来源于stack exchange,提问作者avchoice
相关产品推荐
相关产品推荐

