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
代码错误点分析
寄存器混淆导致非法内存访问
- 代码中
R7同时被用作存储下一个value值和目标数组地址:在inner_loop里LDR R7, [R0, R9, LSL #2]将value读入R7,但原本目标数组Failed_runs_ordered的地址存在R6中,后续no_swap和check段错误地用R7作为目标数组基地址,直接引发非法内存访问和段错误。
- 代码中
存储逻辑完全错误
no_swap段中连续执行STR R3, [R7, R8, LSL #2]和STR R5, [R7, R8, LSL #2],后者会覆盖前者写入的数据,且每次循环都写入同一位置,完全不符合将排序后的Day依次存入目标数组的需求。另外,存储操作不应该嵌套在排序的内层循环中,正确逻辑是完成整个数组排序后,再遍历提取Day值到目标数组。
只读区域写入错误
Failed_runs被放在READONLY的代码段中,排序时swap_elements里的STR操作尝试修改该数组,会触发内存访问权限错误,因为只读区域不允许写入。
注释与代码不一致
- 代码注释标注
R6 = valore successivo,但实际存储下一个value的是R7,容易导致逻辑混淆。
- 代码注释标注
修正建议
调整数据段权限
将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明确寄存器分工
固定R6作为Failed_runs_ordered的基地址,R7仅用作临时存储value值,避免寄存器混用。修正存储逻辑
完成冒泡排序后,单独遍历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修正比较逻辑注释
将; R6 = valore successivo改为; R7 = valore successivo,保持注释与代码一致。
内容的提问来源于stack exchange,提问作者Matteo Pagliarello
相关产品推荐
相关产品推荐

