Разница между cmp и деланием sub затем cmp с 0 - PullRequest
0 голосов
/ 28 мая 2018

Ниже приведены два идентичных ассемблерных кода, написанных для быстрой сортировки.Разница лишь в том, что в первом вычитание выполняется, а затем результат сравнивается с нулем, а во втором - просто сравнение.По какой-то причине первый фрагмент кода выполняет сортировку правильно, а второй - нет.Я провел некоторое исследование по этому вопросу: cmp не изменяет операнды, тогда как 'sub' делает.

Первый (правильный):

## 
##
##  quick_sort(int *a, int l, int r){
##      int i, j, pivot, temp;
##      if(l>=r) return;
##
##      pivot = a[r];
##      i = l;
##      j = r;
##
##          while(i<j){
##          while(i < j && a[i]<pivot) i++;
##          while(i < j && a[j]>=pivot) j--;
##          temp = a[i];
##          a[i] = a[j];
##          a[j] = temp;
##      }
##      a[r] = a[i];
##      a[i] = pivot;
##
##      quick_sort(a, l, i-1);
##      quick_sort(a, i+1, r);
##  }
##

.intel_syntax noprefix

.text
.global quick_sort

########################################
# void quick_sort(int *a, int l, int r)
#
# rdi - int *a
# rsi - int l
# rdx - int r
########################################

quick_sort:
enter 0, 0

cmp rsi, rdx    
jge end_quick_sort  

mov r12, [rdi+rdx*4]    

mov r13, rsi    # i=l
mov r14, rdx    # j=r

partition:
cmp r13, r14    
jge end_partition   

left_loop:      
cmp r13, r14    
jge end_left_loop
mov rax, [rdi+r13*4]                    
sub rax, r12                   #this 
cdqe                           #piece 
cmp rax, 0                     #here
jge end_left_loop   
inc r13     
jmp left_loop
end_left_loop:

right_loop:     
cmp r13, r14    
jge end_right_loop
mov rax, [rdi+r14*4]
sub rax, r12
cdqe
cmp rax, 0      
jl  end_right_loop  
dec r14     
jmp right_loop
end_right_loop:

mov rax, [rdi + r13*4]  
mov r15, [rdi + r14*4]  
mov [rdi + r13*4], r15d
mov [rdi + r14*4], eax

jmp partition       
end_partition:

mov rax, [rdi + r13*4]  # a[r] = a[i]
mov [rdi + rdx*4], eax
mov [rdi + r13*4], r12d # a[i] = pivot



quick_sort_left:    # quick_sort(array,l,i-1)
push    rdx
push    r13
mov rdx, r13
dec rdx
call quick_sort
pop r13
pop rdx

quick_sort_right:   # quick_sort(array,i+1,r)
mov rsi, r13
inc rsi
call quick_sort

end_quick_sort:
xor rax, rax
leave
ret 

Второй (неправильный):

.intel_syntax noprefix

.text

.global quick_sort

quick_sort:

enter 0,0

cmp rsi, rdx
jge end_qs

mov r12, [rdi + 4*rdx]
mov r13, rsi
mov r14, rdx

main_while:

cmp r13, r14
jge end_main_while

left_while:

cmp r13, r14
jge end_left_while
mov rax, [rdi + 4*r13]
cmp rax, r12                       # changed to just one line (cmp)


jge end_left_while

inc r13
jmp left_while
end_left_while:

right_while:

cmp r13, r14
jge end_right_while

mov rax, [rdi + 4*r14]
cmp rax, r12


jl end_right_while

dec r14
jmp right_while

end_right_while:

mov rax, [rdi + 4*r13]
mov r15, [rdi + 4*r14]
mov [rdi + 4*r13], r15d
mov [rdi + 4*r14], eax

jmp main_while
end_main_while:

mov rax, [rdi + 4*r13]
mov [rdi + 4*rdx], eax
mov [rdi + 4*r13], r12d

qs_left:
push rdx
push r13
mov rdx, r13
dec rdx
call quick_sort
pop r13
pop rdx

qs_right:
mov rsi, r13
inc rsi
call quick_sort

end_qs:
xor rax, rax
leave
ret
...