-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathheapsort.asm
222 lines (191 loc) · 5.45 KB
/
heapsort.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
;
; heapsort.asm
;
; Created: 1/3/2019 2:18:51 PM
; Author : Joshua
;
; assume we are using an Atmega328P, the microprocessor in the Arduino Uno
.include "m328Pdef.inc"
; on reset go to the setup label
.ORG 0x0000
rjmp setup
setup:
; define some useful references
.def i = r16
.def heapSize = r17
.def parentAddr = r18
.def currentAddr = r19
.def currentVal = r20
.def parentVal = r21
.def heapEndAddr = r22
; load the numbers to be sorted into memory addresses 0x0100-0x0104
ldi r16, 10
sts 0x0100, r16
ldi r16, 2
sts 0x0101, r16
ldi r16, 27
sts 0x0102, r16
ldi r16, 7
sts 0x0103, r16
ldi r16, 15
sts 0x0104, r16
; set the references
clr i
ldi heapSize, 5
mov heapEndAddr, heapSize
dec heapEndAddr
; set z register
ldi zh, 0x01
ldi zl, 0x00
; Build the max heap in place
buildHeap:
; if we have cycled through every element, move on to deconstruct the heap
cp i, heapSize
breq deconstructHeap
; copy the the current element number into the currentAddress register
mov currentAddr, i
bubbleUp:
; if the current address is 0, we're done bubbling up
cpi currentAddr, 0
breq increment
; move the curretnt address into z low
mov zl, currentAddr
; get the value at the current address
ld currentVal, z
; copy the current address to the parent address
mov parentAddr, currentAddr
; subtract one
subi parentAddr, 1
; and bit shift right to divide by 2
asr parentAddr
; copy the parent address into z low
mov zl, parentAddr
; get the value at the parent address
ld parentVal, z
; compare the two values
cp parentVal, currentVal
; and if the parent is less than the current, swap them
brlt swapElement
; otherwise move onto the next element
rjmp increment
swapElement:
; store the current value to the parent address
st z, currentVal
; set the z pointer to the current address
mov zl, currentAddr
; store the parent value in the current address
st z, parentVal
; set the current address to the parent
mov currentAddr, parentAddr
; go back to the bubble loop
rjmp bubbleUp
; increment the loop counter and move to the next element
increment:
inc i
rjmp buildHeap
deconstructHeap:
; reuse the parent registers to avoid conflicting with definitions in "m328Pdef.inc"
.undef parentAddr
.undef parentVal
; define some references for the left and right children
.def rightChildVal = r23
.def leftChildVal = r24
.def rightChildAddr = r25
.def leftChildAddr = r18
.def heapEndVal = r21
;break
; if i is equal to 0 the heap has been deconstructed
cpi i, 0
; go to the end
breq end
; set the current address to the first (biggest) element in the max heap
ldi currentAddr, 0
; set the z pointer to the last heap element address
mov zl, heapEndAddr
; store the value in heapEndVal
ld heapEndVal, z
; set the z pointer to the current element address
mov zl, currentAddr
; store the value in currentVal
ld currentVal, z
; store the last heap element in the current (root) element
st z, heapEndVal
; set the z pointer to the last heap element address
mov zl, heapEndAddr
; store the first (max) heap element at last heap element
st z, currentVal
; update currentVal
mov currentVal, heapEndVal
; decrement the heap end address
dec heapEndAddr
bubbleDown:
; copy the current address into left child address
mov leftChildAddr, currentAddr
; bit shift left (multiply by 2)
lsl leftChildAddr
; add one
inc leftChildAddr
; copy the left child to the right child
mov rightChildAddr, leftChildAddr
; and add one again
inc rightChildAddr
; if the left child address is out of bounds decrement and continue the deconstruct loop
cp heapEndAddr, leftChildAddr
brlt decrement
; set the z pointer and fetch the left child value
mov zl, leftChildAddr
ld leftChildVal, z
; if the right child address is out of bounds go directly to left swap
cp heapEndAddr, rightChildAddr
brlt leftSwap
; set the z pointer and fetch the right child value
mov zl, rightChildAddr
ld rightChildVal, z
; find the max child
cp leftChildVal, rightChildVal
brlt rightSwap
leftSwap:
; make sure that the max child is in fact greater than the current element
cp currentVal, leftChildVal
; if not, decrement the counter and heap end address
brge decrement
; copy the left child address to the z pointer
mov zl, leftChildAddr
; store the current value to the left child address
st z, currentVal
; set the z pointer to the current address
mov zl, currentAddr
; store the left child value in the current address
st z, leftChildVal
; set the current address to the left child
mov currentAddr, leftChildAddr
; set the current val to the left child
mov currentVal, leftChildVal
; go back to the bubble loop
rjmp bubbleDown
rightSwap:
; make sure that the max child is in fact greater than the current element
cp currentVal, rightChildVal
; if not, decrement the counter and heap end address
brge decrement
; copy the right child address to the z pointer
mov zl, rightChildAddr
; store the current value to the right child address
st z, currentVal
; set the z pointer to the current address
mov zl, currentAddr
; store the right child value in the current address
st z, rightChildVal
; set the current address to the right child
mov currentAddr, rightChildAddr
; set the current val to the right child
mov currentVal, rightChildVal
; go back to the bubble loop
rjmp bubbleDown
; decrement the loop counter and run the loop again for the next element
decrement:
dec i
rjmp deconstructHeap
; when we are done just run this infinite loop
end:
rjmp end