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

STM32 ARM汇编向数据区数组写值全零问题求解

STM32 ARM汇编冒泡排序问题修复

你遇到的数组初始值全0、排序不生效是两个核心问题导致的,直接按以下方案修改即可。


问题1:自定义数据段未被正确初始化

你当前代码把数组ARR定义在了名为A的自定义DATA段中,STM32的默认启动文件、链接脚本只会自动处理标准段的内存分配与初始值拷贝:

  • 只读代码段默认识别|.text|
  • 带初始值的可读写数据段默认识别|.data|
  • 零初始化数据段默认识别|.bss|

自定义命名的段如果没有手动修改链接脚本配置,不会被分配到正确的SRAM地址,也不会把你写的初始值1,3,2,4从Flash拷贝到RAM,读内存自然全为0。

问题2:交换逻辑的内存访问错误

你写的交换代码存在原则性错误:

LDR R1,[R0];   // 执行后R1存的是ARR[i]的数值,不是内存地址
STR R2,[R1];   // 把数值当地址写,属于非法内存访问,根本不会修改原数组
STR R3,[R0];

ARM汇编的STR指令方括号内必须是合法内存地址,你这里把从数组里读出来的数值当成地址写入,要么直接触发HardFault,要么写到了和数组无关的内存区域,排序逻辑完全不生效。


修正后可运行代码

AREA   |.text|, CODE, READONLY
    EXPORT __main 

__main
    MOV R5,#3                ; 外层循环次数 = 数组长度-1
    LDR R0,=ARR              ; 加载数组首地址

__LOOP1
    CMP R5,#0
    BEQ __done               ; 外层循环计数为0,排序完成
    MOV R6,R5                ; 每轮内层循环比较次数 = 当前外层剩余计数
    LDR R0,=ARR              ; 内层循环开始前重置指针到数组首地址
__INNER_LOOP
    CMP R6,#0
    BEQ __OUTER_UPDATE       ; 内层循环跑完,更新外层计数
    LDR R1,[R0]              ; 读取ARR[i]
    LDR R2,[R0,#4]           ; 读取ARR[i+1]
    CMP R1,R2
    BLE __NO_SWAP            ; 前值<=后值,顺序正确无需交换
    STR R2,[R0]              ; 交换两个相邻元素
    STR R1,[R0,#4]
__NO_SWAP        
    SUBS R6,#1
    ADDS R0,#4               ; 指针后移4字节(一个字长度)
    B __INNER_LOOP
__OUTER_UPDATE
    SUBS R5,#1
    B __LOOP1
__done
    B __done                 ; 排序完成后死循环,防止程序跑飞

    AREA  |.data|, DATA, READWRITE
ARR DCD  1,3,2,4 

    END

验证说明

代码烧录后进入调试模式,暂停在__done位置时查看ARR对应的内存地址,可看到数组已被正确排序为1,2,3,4,初始值可以正常读取,不会再出现全0问题。

内容的提问来源于stack exchange,提问作者Wong Chung sze

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 21:45:38