Я пытаюсь изменить код быстрой сортировки C на код сборки ARM.
Во-первых, я прошу прощения за мой длинный вопрос.
на всякий случай, я написал целые коды.
, но только часть, которая делаетПроблема в функции рекурсивной части.Я почти выполнил эту работу, за исключением части рекурсии funcion.
Я также попытался преобразовать C-коды в сборку ARM с помощью кросс-компилятора gcc, чтобы посмотреть, как работает компилятор.Но есть еще несколько вещей, которые я не могу понять хорошо.
Это код C.
void quicksort_c(int array[8],int first,int last)
{
int i, j, pivot, temp;
if(first < last)
{
pivot = first;
i = first;
j = last;
while(i < j)
{
while(array[i] <= array[pivot] && i < last)
{
i++;
}
while(array[j] > array[pivot])
{
j--;
}
if(i < j)
{
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
temp = array[pivot];
array[pivot] = array[j];
array[j] = temp;
quicksort_c(array, first, j-1);
quicksort_c(array, j+1, last);
}
}
и это код сборки руки, который я написал с нуля.
quicksort
STMFD sp!, {r0-r8,lr}
quicksort_recursion
CMP r1, r2 ;// if(first < last)
BGE out_of_if
outer_if
MOV r5, r1 ;// pivot = first
MOV r3, r1 ;// i = first;
MOV r4, r2 ;// j = last;
outer_while_loop
CMP r3, r4 ;// while(i < j)
BGE end_of_outer_while
outer_while
inner_while_1_loop
;//while(array[i] <= array[pivot] && i < last)
LDR r7, [r0, r3, lsl #2] ;//r7 = array[i]
LDR r8, [r0, r5, lsl #2] ;//r8 = array[pivot]
CMP r7, r8 ;//array[i] <= array[pivot]
BGT inner_while_2_loop
CMP r3, r2 ;// i < last
BGE inner_while_2_loop
inner_while_1
ADD r3, #1 ;//i++
B inner_while_1_loop
inner_while_2_loop
;//whlie(array[j] > array[pivot])
LDR r7, [r0, r4, lsl #2] ;// r7 = array[j]
LDR r8, [r0, r5, lsl #2] ;//r8 = array[pivot]
CMP r7, r8 ;// (array[j] > array[pivot])
BLE inner_if_cmp
inner_while_2
SUB r4, #1
B inner_while_2_loop
inner_if_cmp
CMP r3, r4;// if(i < j)
BGE outer_while_loop
inner_if
LDR r7, [r0, r3, lsl #2] ;// r7 = array[i]
MOV r6, r7 ;// temp = array[i]
LDR r8, [r0, r4, lsl #2] ;// r8 = array[j]
STR r8, [r0, r3, lsl #2] ;// array[i] = array[j]
STR r6, [r0, r4, lsl #2] ;// array[j] = temp;
B outer_while_loop
end_of_outer_while
LDR r7, [r0, r5, lsl #2] ;// r7 = array[pivot]
MOV r6, r7 ;// temp = array[pivot]
LDR r8, [r0, r4, lsl #2] ;// r8 = array[j]
STR r8, [r0, r5, lsl #2] ;// array[pivot] = array[j]
STR r6, [r0, r4, lsl #2] ;// array[j] = temp
;;//quicksort(array,first,j-1)
STMFD sp!, {r0-r8,lr}
SUBS r2, r4, #1
BL quicksort_recursion
;//LDMFD sp!, {r0-r8,pc}
;//quicksort(array, j+1, last)
STMFD sp!, {r0-r8,lr}
ADDS r1, r4, #1
BL quicksort_recursion
;//LDMFD sp!, {r0-r8,pc}
out_of_if
end_function
LDMFD sp!, {r0-r8,pc}
END
и вот как я использую регистр
r0: array pointer
r1: first index
r2: last index
r3: i
r4: j
r5: pivot
r6: temp
r7: array[?] value
r8: array[?] value
Я подтвердил, что все части, кроме рекурсии моего кода, работают хорошо.
Сначала я делал рекурсию таким способом.
;;//quicksort(array,first,j-1)
SUBS r2, r4, #1
BL quicksort
;//quicksort(array, j+1, last)
ADDS r1, r4, #1
BL quicksort
, но этот код толькорекурсия первой функции.
ex)
Массив до быстрой сортировки: 5 1 4 7 8 3 6
Массив после быстрой сортировки: 1 2 4 3 5 8 7 6
Я думаю, что этопотому что после вызова функции она не возвращается туда, где она разветвляется.поэтому я добавил push и pop до и после вызова функции следующим образом.
;;//quicksort(array,first,j-1)
STMFD sp!, {r0-r8,lr}
SUBS r2, r4, #1
BL quicksort_recursion
;//quicksort(array, j+1, last)
STMFD sp!, {r0-r8,lr}
ADDS r1, r4, #1
BL quicksort_recursion
Но этот код попадает в бесконечный цикл.
согласно скомпилированному коду gcc,
quicksort_linux
cmp r1, r2
blt L16
bx lr
L16
push {r4, r5, r6, r7, r8, r9, r10, lr}
mov r10, r1
add ip, r0, r1, lsl #2
mov r5, r2
mov r4, r1
L3
lsls r3, r4, #2
add lr, r0, r3
ldr r7, [r0, r4, lsl #2]
ldr r6, [ip]
cmp r2, r4
ite le
movle r8, #0
movgt r8, #1
cmp r7, r6
it gt
movgt r8, #0
adds r3, r3, #4
add r3, r3, r0
cmp r8, #0
beq L9
L4
adds r4, r4, #1
mov lr, r3
ldr r7, [r3], #4
cmp r2, r4
ite le
movle r1, #0
movgt r1, #1
cmp r7, r6
it gt
movgt r1, #0
cmp r1, #0
bne L4
L9
lsls r3, r5, #2
add r9, r0, r3
ldr r1, [r0, r5, lsl #2]
cmp r1, r6
ble L5
subs r3, r3, #4
add r3, r3, r0
L6
subs r5, r5, #1
mov r9, r3
ldr r1, [r3], #-4
cmp r1, r6
bgt L6
L5
cmp r4, r5
bge L7
str r1, [lr]
str r7, [r9]
b L3
L7
mov r7, r2
mov r1, r10
mov r4, r0
ldr r3, [r0, r5, lsl #2]
str r3, [r0, r10, lsl #2]
str r6, [r0, r5, lsl #2]
subs r2, r5, #1
bl quicksort_linux
mov r2, r7
adds r1, r5, #1
mov r0, r4
bl quicksort_linux
pop {r4, r5, r6, r7, r8, r9, r10, pc}
END
Кажется, что они не делают push или pop до или после ветвления, но это работает.
Итак, вопрос в
1. В чем проблема моего кода рекурсии функции?
2.Как я могу это исправить?
3.Как может скомпилированный код gcc работать без каких-либо push и pop до и после рекурсии функции?