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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 12:30:05