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

ARM模式下适配uint16_t无符号半字的Stupid Sort汇编代码问题排查

问题解答

1. LDRH后!符号的作用

!是ARM汇编的预索引回写标记,以你写的LDRH R2,[R0,#2]!为例,执行逻辑是:

  • 先计算有效地址:R0 + 2
  • 从该地址加载16位半字到R2寄存器,自动零扩展到32位
  • 最后把计算出的有效地址R0 + 2写回R0寄存器,等价于额外执行了一次ADD R0,R0,#2

2. 现有代码的bug排查

你修改的代码存在两个核心错误导致排序异常:

(1)跳转指令不符合无符号数比较逻辑

原来针对int32_t的BLE跳转是有符号数小于等于跳转,不能用于uint16_t无符号数比较,大于0x7FFF的无符号数会被识别为负数,导致比较逻辑完全错误。需要替换为无符号小于等于跳转指令BLS。

(2)交换数据的地址计算错误

执行完带!的LDRH指令后,R0已经被更新为a[i+1]的地址,你现在写的STRH R2,[R0,#2]会把值写到a[i+2]的位置,直接破坏了后续元素的值。正确的交换逻辑应该是写入a[i](地址为R0 - 2)和a[i+1](地址为R0)。


3. 修正后的完整代码

sort:   SUB     R1,R1,#1        // n = n - 1
        ADD     R12,R0,#2       // 数组首地址+2,用于判断i是否为0
        ADD     R1,R0,R1,LSL#1  // 计算数组最后一个元素的地址,每个元素占2字节
L1:     LDRH    R3,[R0]         // 加载a[i]到R3,自动零扩展
        LDRH    R2,[R0,#2]!     // 加载a[i+1]到R2,R0自增2变为a[i+1]的地址
        CMP     R3,R2           // 比较a[i]和a[i+1]
        BLS     L2              // 无符号小于等于则不需要交换,跳转到L2
        STRH    R2,[R0,#-2]     // 交换:把R2(原a[i+1])写入a[i]的位置(R0-2)
        STRH    R3,[R0]         // 把R3(原a[i])写入a[i+1]的位置(R0)
        CMP     R0,R12          // 判断i是否为0
        SUBHI   R0,R0,#4        // 若i>0,R0回退4字节回到a[i-1]的位置,等价于i--
L2:     CMP     R0,R1           // 判断是否到达数组末尾
        BLT     L1              // 未到末尾则继续循环
        BX      LR

4. 其他疑问解答

  • R3、R2的加载顺序不需要交换:R3加载的是a[i],R2加载的是a[i+1],比较R3 > R2时交换的逻辑完全正确,无需调整。
  • LDRH默认是零扩展加载,刚好符合uint16_t无符号半字的加载需求,不需要额外处理高位。

内容的提问来源于stack exchange,提问作者chaikataaaaa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 21:36:01