# Version history # -v0: initial version # -v1: correct mistakes in the precondition and postcondition for merge # correct the first argument of the second recursive mergesort call .text main: la $a0, toSort li $a1, 3 jal mergesort li $v0, 10 syscall .data toSort: .word 3, 1, 2 .text # mergesort(p, n) # use mergesort technique to sort an array of integers # n integers stored at location p. # p will be passed in $a0, n in $a1 # precondition: n>=0 -- not strictly necessary # Result: p[0..n) is sorted # mergesort(p, n) { # if (n==1) return; # mergesort(p, n/2); # mergesort(p+(n/2), n-(n/2)); # #!! remember that this is pointer addition! # merge(p, n/2, n-(n/2)); # } mergesort: # prolog addiu $sp, $sp, -20 sw $ra, 0($sp) li $t0, 1 ble $a1, $t0, sortEpilog sw $a0, 4($sp) # store p sw $a1, 8($sp) # store n # set up first recursive call sra $a1, $a1, 1 # n/2 sw $a1, 12($sp) # save n/2 for later jal mergesort # set up second recursive call lw $a0, 4($sp) # p lw $a1, 8($sp) # n # move $t0, $a1 # n # sll $t0, 1 # (n/2)*4 - incorrect! lw $a1, 12($sp) sll $a1, $a1, 2 # (n/2)*4 - correct! add $a0, $a0, $a1 # address of p+(n/2) in $a0 lw $a1, 8($sp) # n lw $t0, 12($sp) # n/2 sub $a1, $a1, $t0 # n - (n/2) sw $a1, 16($sp) # save n - (n/2) for later jal mergesort # set up call to merge lw $a0, 4($sp) # p lw $a1, 12($sp) # n/2 lw $a2, 16($sp) # n - (n/2) jal merge sortEpilog: lw $ra, 0($sp) addiu $sp, $sp, 20 jr $ra # merge(p, n1, n2) # auxiliary procedure # p - pointer to an array # n1 - number of elements in first segment # n2 - number of elements in second segment # precondition p[0..n1) is sorted and # p[n1..n1+n2) is sorted # postcondition: p[0..n1+n2) is sorted # # merge(p, n1, n2) { # # # first make a copy # int tmp[n1+n2]; # Note: tmp array must be on stack and is of variable size # int *p1 = p; # int *p2 = tmp; # int *limit = &(tmp[p1+p2]) # for (p1=p, p2=tmp; p2 < limit; p1++, p2++) { # *p2 = *p1; # } # p1 = tmp; # p2 = &tmp[n1]; # int *p1limit = p2 # int *p2limit = limit; # int *p3 = p; # # while (1) { # if ((p1 < p1limit) && (p2 < p2limit)) { # if (*p1 <= *p2) {w = *p1; p1++} # else { w = *p2; p2++} # } # else if (p1 < p1limit) {w = *p1; p1++} # else if (p2 < p2limit) {w = *p2; p2++} # else break # *p3 = w; p3++ # } merge: #prolog mergeepilog: jr $ra