-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtutorial.asm
More file actions
303 lines (242 loc) · 10.5 KB
/
tutorial.asm
File metadata and controls
303 lines (242 loc) · 10.5 KB
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
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
# This code calculates the arithmetic mean of the array
.data
array: .double 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 # Array of floating-point numbers
len: .word 6 # Length of the array
.text
mtc1 $zero, $f12 # Set $f12 low 32-bits to 0.0 (initialize the sum to 0.0)
mthc1 $zero, $f12 # Set $f12 high 32-bits to 0.0 (initialize the sum to 0.0)
la $t4, array # Load the address of the array into $t4
li $t2, 48 # Load the size of the array in bytes (6 elements * 8 bytes per double = 48 bytes)
loop:
bnez $t2, 1 # If $t2 is not zero, continue to the next iteration of the loop
j end # Jump to the end of the program if $t2 is zero
addi $t2, $t2, -8 # Decrement $t2 by 8 (move to the previous element)
add $t3, $t4, $t2 # Calculate the address of the current element of the array
ldc1 $f10, 0($t3) # Load the value of the current element into $f10
add.d $f12, $f12, $f10 # Add the value of the current element to the sum in $f12
j loop # Jump back to the beginning of the loop
end:
la $t4, len # Load the address of the length variable into $t4
lwc1 $f10, 0($t4) # Load the value of the length into $f10
cvt.d.w $f10, $f10 # Convert the integer length to double precision
div.d $f12, $f12, $f10 # Divide the sum by the length to calculate the mean
li $v0, 3 # Set $v0 to 3 (system call code for printing a floating-point number)
syscall
li $a0, 10 # Set $a0 to 10 (ASCII code for newline character)
li $v0, 11 # Set $v0 to 11 (system call code for printing a character)
syscall
#============================================================================================
#### This code computes the geometric mean of the array ####
.data
array: .double 1, 2, 3, 4, 5, 6 # Array of numbers
length: .word 6 # Length of the array
eps: .double 0.001
.text
.globl main
main:
# Initialize variables
la $t0, array # Load the address of the array into $t0
la $t1, length # Load the address of length into $t1
lw $t1, 0($t1) # Load the value of length into $t1
li $t2, 1 # Initialize $t2 with 1
mtc1 $t2, $f1 # Move $t2 to the floating-point register $f1
cvt.d.w $f1, $f1 # Convert the integer value in $f1 to double precision
loop:
beqz $t1, end_loop # If length is zero, exit the loop
ldc1 $f2, 0($t0) # Load the double value at the current index of array into $f2
mul.d $f1, $f1, $f2 # Multiply the product with the current element and store the result in $f1
addi $t0, $t0, 8 # Increment the array pointer by 8 bytes (64 bits)
addi $t1, $t1, -1 # Decrement the length by 1
j loop # Jump back to the loop
end_loop:
addi $sp, $sp, -16 # Allocate space on the stack
la $t1, length # Load the address of length into $t1
lw $t1, 0($t1) # Load the value of length into $t1
sdc1 $f1, 0($sp) # Store the product value on the stack
sw $t1, 8($sp) # Store the length value on the stack
jal binary_search # Jump and link to the binary_search function
# Print the result
li $v0, 3 # System call code for printing float
syscall
# Print the line
li $v0, 11 # System call code for printing character
li $a0, 10 # Load the ASCII code for a new line into $a0
syscall
# Exit the program
li $v0, 10 # System call code for exit
syscall
# Functions
pow_n:
ldc1 $f20, 0($sp) # Load the number from the stack
ldc1 $f21, 0($sp) # Load the number from the stack
lw $t0, 8($sp) # Load n from the stack
pow_n_loop:
addi $t0, $t0, -1 # Decrement n by 1
bnez $t0, pow_n_continue # If n is not zero, continue
mov.d $f12, $f21 # Move the result (ans) to the output register
jr $ra # Return
pow_n_continue:
mul.d $f21, $f21, $f20 # Multiply ans by the number
j pow_n_loop # Jump back to pow_n_loop
binary_search:
ldc1 $f1, 0($sp) # Load the number from the stack
ldc1 $f10, 0($sp) # Load the number from the stack
lw $t0, 8($sp) # Load n from the stack
li $t2, 1 # Initialize low = 1.0
mtc1 $t2, $f2 # Move $t2 to the floating-point register $f2
cvt.d.w $f2, $f2 # Convert the integer value in $f2 to double precision
la $t2, eps # Load the address of eps into $t2
ldc1 $f3, 0($t2) # Load the value of eps into $f3
li $t3, 2 # Load 2 into $t3
mtc1 $t3, $f8 # Move $t3 to the floating-point register $f8
cvt.d.w $f8, $f8 # Convert the integer value in $f8 to double precision
bs_loop:
sub.d $f4, $f1, $f2 # Calculate high - low and store the result in $f4
cmp.le.d $f5, $f4, $f3 # Compare (high - low) with eps and set the result in $f5
bc1eqz $f5, 1 # If (high - low) <= eps, exit the loop
j bs_exit # Jump to bs_exit
add.d $f6, $f2, $f1 # Calculate low + high and store the result in $f6
div.d $f7, $f6, $f8 # Calculate (low + high) / 2.0 and store the result in $f7
addi $sp, $sp, -52 # Allocate space on the stack
# Preserve registers
sw $ra, 48($sp)
sdc1 $f10, 40($sp) # Push low onto the stack
sdc1 $f2, 32($sp) # Push low onto the stack
sdc1 $f1, 24($sp) # Push high onto the stack
sdc1 $f8, 16($sp) # Push 2.0 onto the stack
sw $t0, 8($sp) # Push n onto the stack
sdc1 $f7, 0($sp) # Push mid onto the stack
jal pow_n # Call the pow_n function to calculate pow_n(mid, n)
# Restore registers
lw $ra, 48($sp)
ldc1 $f10, 40($sp) # Pop low from the stack
ldc1 $f2, 32($sp) # Pop low from the stack
ldc1 $f1, 24($sp) # Pop high from the stack
ldc1 $f8, 16($sp) # Pop 2.0 from the stack
lw $t0, 8($sp) # Pop n from the stack
ldc1 $f7, 0($sp) # Pop mid from the stack
addi $sp, $sp, 52 # Deallocate space on the stack
cmp.lt.d $f9, $f12, $f10 # Compare pow_n(mid, n) with high and set the result in $f9
bc1eqz $f9, 1 # If pow_n(mid, n) < high, jump to bs_low
j bs_low # Jump to bs_low
mov.d $f1, $f7 # Set high = mid
j bs_loop # Jump back to bs_loop
bs_low:
mov.d $f2, $f7 # Set low = mid
j bs_loop # Jump back to bs_loop
bs_exit:
mov.d $f12, $f2 # Set low = mid
jr $ra # Return
#============================================================================================
#### This code computes the hypothenus given x and y ####
.text
.globl main
main:
# Load default values for side1 and side2
li $s0, 3 # Load 3 into $s0
li $s1, 4 # Load 4 into $s1
# Calculate the squares of side1 and side2
mul $t0, $s0, $s0 # side1 * side1
mul $t1, $s1, $s1 # side2 * side2
# Calculate the sum of the squares
add $t2, $t0, $t1 # side1^2 + side2^2
# Calculate the square root of the sum
mtc1 $t2, $f12
cvt.s.w $f12, $f12
sqrt.s $f12, $f12 # Square root of the sum
# Print the result
li $v0, 2 # System call code for printing integer
syscall
# Print the line
li $v0, 11 # System call code for printing character
li $a0, 10 # load new line ascii code to $a0
syscall
# Exit the program
li $v0, 10 # System call code for exit
syscall
#=============================================================================================
#### This code calculates x to the power ####
.text
.globl main
main:
# Store x and n in registers
li $s0, 2 # Move x to $s0
li $s1, 2 # Move n to $s1
# Initialize result to 1
li $t0, 1 # Load 1 into $t0
loop:
beqz $s1, exit # Exit loop if n == 0
mul $t0, $t0, $s0 # Multiply result by x
addi $s1, $s1, -1 # Decrement n by 1
j loop # Jump to loop label
exit:
# Print the result
li $v0, 1 # System call code for printing integer
move $a0, $t0 # Move result to $a0
syscall
# Print the line
li $v0, 11 # System call code for printing character
li $a0, 10 # load new line ascii code to $a0
syscall
# Exit the program
li $v0, 10 # System call code for exit
syscall
#============================================================================================
#### This snippet computes the root of the function y = x^2 - x using Newton approximation ####
.data
x0: .float 1.5 # Initial guess for the root
epsilon: .float 0.001 # Error tolerance
.text
.globl main
main:
# Load initial guess and error tolerance
la $t0, x0
lwc1 $f0, 0($t0) # Load x0 into $f0
la $t0, epsilon
lwc1 $f1, 0($t0) # Load epsilon into $f1
loop:
# Compute the function value and its derivative at x0
mul.s $f2, $f0, $f0 # Compute x0^2
sub.s $f3, $f2, $f0 # Compute x0^2 - x0 (function value)
addi $sp, $sp, -4 # Allocate space on the stack
swc1 $f0, 0($sp) # Store x0 on the stack
addi $sp, $sp, -4 # Allocate space on the stack
swc1 $f2, 0($sp) # Store x0^2 on the stack
addi $sp, $sp, -4 # Allocate space on the stack
swc1 $f3, 0($sp) # Store function value on the stack
jal calculate_derivative # Jump to calculate_derivative function
addi $sp, $sp, 12 # Deallocate the stack space
# Calculate the new approximation using Newton's method
div.s $f6, $f3, $f6 # Divide function value by derivative
sub.s $f0, $f0, $f6 # Subtract the division result from x0
# Check if the approximation is within the error tolerance
abs.s $f12, $f6 # Take the absolute value of the division result
cmp.lt.s $f12, $f12, $f1 # Compare the absolute value with epsilon
bc1eqz $f12, 1 # Branch if true to the exit label
j exit
# Repeat the loop
j loop
calculate_derivative:
lwc1 $f4, 8($sp) # Load x0 from the stack
lwc1 $f5, 4($sp) # Load x0^2 from the stack
li $t4, 2
mtc1 $t4, $f12
cvt.s.w $f12, $f12
mul.s $f6, $f4, $f12 # Compute 2 * x0
li $t4, 1
mtc1 $t4, $f12
cvt.s.w $f12, $f12
sub.s $f6, $f6, $f12 # Compute 2 * x0 - 1 (derivative value)
jr $ra
exit:
# Print the result
li $v0, 2 # System call code for printing float
mov.s $f12, $f0 # Load the result from memory to $f12
syscall
# Print the line
li $v0, 11 # System call code for printing character
li $a0, 10 # load new line ascii code to $a0
syscall
# Exit the program
li $v0, 10 # System call code for exit
syscall