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

ARM开发:冒泡排序后有序数组存储异常问题排查

ARM冒泡排序代码错误排查

我是ARM开发新手,现有一个以<Day, value>成对存储的无序数组Failed_runs,需按value值降序排序后,将Day值存入Failed_runs_ordered数组。自行实现的冒泡排序代码运行后出现内存段错误或空值,无法确认数据是否正确排序,请求排查代码中的存储逻辑或其他错误。

原始数组

Failed_runs     DCD     0x02, 50, 0x05, 30, 0x06, 100, 0x01, 58
                DCD     0x03, 40, 0x04, 90, 0x07, 25 

预期结果

Failed_runs_ordered     DCD 0x06,0x04,0x01, 0x02, 0x03, 0x05, 0x07

待排查代码

AREA    |.text|, CODE, READONLY , ALIGN=2 
               
                ; BOUNDARY 
                SPACE 4096          
Days            DCB     0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 

                
                SPACE 4096
Best_times      DCD     0x06, 1300, 0x03, 1700, 0x02, 1200, 0x04, 1900
                DCD     0x05, 1110, 0x01, 1670, 0x07, 1000 

                
                SPACE 4096
Failed_runs     DCD     0x02, 50, 0x05, 30, 0x06, 100, 0x01, 58
                DCD     0x03, 40, 0x04, 90, 0x07, 25 
                 
                        
Best_times_ordered      SPACE   32
                                       
Failed_runs_ordered    SPACE   32 
                           
                SPACE 4096      
Num_days        DCB     0x07 


; Reset Handler

Reset_Handler   PROC
                EXPORT  Reset_Handler             [WEAK]                                            
            
            LDR R1, =Best_times
            LDR R0, =Failed_runs      ; Punto di partenza dell'array Failed_runs
            LDR R6, =Failed_runs_ordered
            LDRB R2, Num_days         ; Carica il numero di giorni (7)

outer_loop
            MOV R8, #0                ; Inizializza l'indice interno
            MOV R11, #0 
inner_loop
            LDR R3, [R0, R8, LSL #2]  ; R3 = giorno corrente
            ADD R8, R8, #1           ; Avanza di 2 per passare al prossimo elemento
            LDR R4, [R0, R8, LSL #2]  ; R4 = valore corrente
            SUB R8, R8, #1            ; Torna indietro (ripristina R8)

            ADD R9, R8, #2            ; Calcola l'indice per il prossimo giorno
            LDR R5, [R0, R9, LSL #2]  ; R5 = giorno successivo
            ADD R9, R9, #1            ; Avanza R9 per caricare il prossimo valore
            LDR R7, [R0, R9, LSL #2]  ; R6 = valore successivo
            SUB R9, R9, #1            ; Torna indietro

            CMP R4, R6
            BGE no_swap               ; Se R4 >= R6, non fare lo swap

swap_elements
            STR R5, [R0, R8, LSL #2]  ; Scrivi giorno successivo nella posizione corrente
            ADD R8, R8, #1            ; Avanza per scrivere il valore
            STR R7, [R0, R8, LSL #2]  ; Scrivi valore successivo
            SUB R8, R8, #1            ; Torna indietro
            STR R3, [R0, R9, LSL #2]  ; Scrivi giorno corrente nella posizione successiva
            ADD R9, R9, #1            ; Avanza per scrivere il valore
            STR R4, [R0, R9, LSL #2]  ; Scrivi valore corrente
            SUB R9, R9, #1            ; Torna indietro

no_swap     
            STR R3, [R7, R8, LSL #2] 
            ADD R11,R11,#1; Scrivi giorno corrente in Failed_runs_ordered
            STR R5, [R7, R8, LSL #2] 
            
            ADD R8, R8, #2            ; Passa alla prossima coppia
            CMP R8, #12
            BLT inner_loop            ; Continua fino a completare la passata

            SUBS R2, R2, #1
            BNE outer_loop            ; Continua fino a quando tutto è ordinato

    
            MOV R8, #0
            
check       LDR R3, [R7, R8, LSL #2]  ; R3 = giorno corrente
            ADD R8, R8, #1
            CMP R8, #12
            BLT check   

代码错误点分析

  1. 寄存器混淆导致非法内存访问

    • 代码中R7同时被用作存储下一个value值和目标数组地址:在inner_loop里LDR R7, [R0, R9, LSL #2]将value读入R7,但原本目标数组Failed_runs_ordered的地址存在R6中,后续no_swap和check段错误地用R7作为目标数组基地址,直接引发非法内存访问和段错误。
  2. 存储逻辑完全错误

    • no_swap段中连续执行STR R3, [R7, R8, LSL #2]和STR R5, [R7, R8, LSL #2],后者会覆盖前者写入的数据,且每次循环都写入同一位置,完全不符合将排序后的Day依次存入目标数组的需求。另外,存储操作不应该嵌套在排序的内层循环中,正确逻辑是完成整个数组排序后,再遍历提取Day值到目标数组。
  3. 只读区域写入错误

    • Failed_runs被放在READONLY的代码段中,排序时swap_elements里的STR操作尝试修改该数组,会触发内存访问权限错误,因为只读区域不允许写入。
  4. 注释与代码不一致

    • 代码注释标注R6 = valore successivo,但实际存储下一个value的是R7,容易导致逻辑混淆。

修正建议

  1. 调整数据段权限
    将Failed_runs、Failed_runs_ordered等需要读写的数据移到DATA段,定义为READWRITE:

    AREA    |.data|, DATA, READWRITE, ALIGN=2
    Failed_runs     DCD     0x02, 50, 0x05, 30, 0x06, 100, 0x01, 58
                    DCD     0x03, 40, 0x04, 90, 0x07, 25 
    Failed_runs_ordered    SPACE   32 
    
  2. 明确寄存器分工
    固定R6作为Failed_runs_ordered的基地址,R7仅用作临时存储value值,避免寄存器混用。

  3. 修正存储逻辑
    完成冒泡排序后,单独遍历Failed_runs数组,将每个Day值依次写入Failed_runs_ordered,示例片段:

    ; 排序完成后提取Day值
    MOV R8, #0
    MOV R9, #0
    extract_loop
    LDR R3, [R0, R8, LSL #2]
    STR R3, [R6, R9, LSL #2]
    ADD R8, R8, #2
    ADD R9, R9, #1
    CMP R9, #7
    BLT extract_loop
    
  4. 修正比较逻辑注释
    将; R6 = valore successivo改为; R7 = valore successivo,保持注释与代码一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 06:37:32