-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathcaesar.asm
506 lines (414 loc) · 9.85 KB
/
caesar.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
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
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
# ===========================================
# Federico Maggi
# MIPS Caesar Cipher
# ===========================================
#
# Recursive MIPS Ceasar Cipher
#
# Main:
# $s0 -> Operation
# $s1 -> Key
# $s2 -> String length
# $s3 -> Computed string address
#
.data
opprompt: .asciiz "Choose the operation? (1: cipher - 2: decipher - 0: exit)\n> "
keyprompt: .asciiz "Insert key (must be greated than 0):\n> "
opcprompt: .asciiz "Ciphering with key: "
opdprompt: .asciiz "Deciphering with key: "
txtprompt: .asciiz "Insert the text:\n> "
resprompt: .asciiz "Result:\n"
conprompt: .asciiz "Press '1' to continue:\n> "
byeprompt: .asciiz "Goodbye!\n"
errstrprompt: .asciiz "Invalid string!\n"
errkeyprompt: .asciiz "Invalid Key!\n"
endl: .asciiz "\n"
string: .space 256
.globl main
.text
main:
li $v0, 4
la $a0, opprompt
syscall
li $v0, 5 # Reads the operation to do
syscall
beq $v0, $zero, __exit # OP = 0 -> EXIT
bltz $v0, main # OP < 0 -> MAIN
bgt $v0, 2, main # OP > 2 -> MAIN
addi $s0, $v0, 0 # Save in $s0 the operation
__keyask: # Read key
li $v0, 4 # NOTE: The key must not be equal to 0
la $a0, keyprompt # it is reduced in modulus 26
syscall
li $v0, 5
syscall
li $t0, 26 # Save in $t0 modulus value
div $v0, $t0
mfhi $t1 # $t1 <- $v0 % 26
beqz $t1, __keyask
blt $t1, $0, __keyask
addi $s1, $t1, 0 # Save the key in $s1
__stringask: # Read the string to manipulate
li $v0, 4
la $a0, txtprompt
syscall
li $v0, 8
la $a0, string
li $a1, 255
syscall
la $a0, string
jal __strlen
beq $v1, 0, __stringok
j __stringask
__stringok:
addi $s2, $v0, 0 # $s2 <- strlen( string )
__allocation:
li $v0,9 # Allocate a memory buffer
addi $a0, $s2, 1 # to save the computed string
syscall
addi $s3, $v0, 0
__opselect:
beq $s0, 1, __cipherprompt
beq $s0, 2, __decipherprompt
j main
__decipherprompt:
add $t0, $s1, $s1 # This calculate the opposite
sub $s1, $s1, $t0 # of the key
li $v0, 4
la $a0, opdprompt
syscall
li $v0, 1
addi $a0, $s1, 0
syscall
li $v0, 4
la $a0, endl
syscall
j __invokecipher
__cipherprompt:
li $v0, 4
la $a0, opcprompt
syscall
li $v0, 1
addi $a0, $s1, 0
syscall
li $v0, 4
la $a0, endl
syscall
__invokecipher: # Invoke the cipher procedure with paramethers:
addi $a0, $s2, 0 # $a0 <- String length
li $a1, 0 # $a1 <- Current index
addi $a2, $s3, 0 # $a2 <- Result string address
jal __ciphercore
j __done
__done: # Print result
li $v0, 4
la $a0, resprompt
syscall
#
# Print the operation output
#
addi $a0, $s3, 0
li $v0, 4
syscall
li $a0, 4
la $a0, endl
syscall
li $v0, 4 # Print "continue" request
la $a0, conprompt
syscall
li $v0, 5 # Read reply
syscall
addi $t0, $v0, 0 # $t0 <- reply
li $v0, 4 # Print a \n
la $a0, endl
syscall
beq $t0, 1, main # $t0 != 1 -> EXIT
__exit: # Print goodbye message and exit
li $v0, 4
la $a0, byeprompt
syscall
li $v0, 10
syscall
##################
### Procedures ###
##################
# =================================================
# cipherCore
#
# NOTA:
# The cipher algorithm is the following:
# c = ((p - l) + k) % 26) + l
# p = ((c - l) - k) % 26) + l
#
# Dove:
# c = ciphertext
# p = plaintext
# l = ASCII offset character
# k = key
#
# For information about the offset character cfr:
# __getcharoffset
#
# Paramethers:
# $a0 <- String length
# $a1 <- Current index
# $a2 <- Result string address
#
# Return values
# $v0 <- String length
# $v1 <- error (-1/0)
# =================================================
__ciphercore:
addi $sp, $sp -16 # Save:
sw $a0, 0($sp) # String length
sw $a1, 4($sp) # Current index
sw $a2, 8($sp) # Result strin address
sw $ra, 12($sp) # Return Address
li $t5, 0 # write the end strin character \0
sb $t5, 0($a2) # in current position.
bge $a1, $a0, __ciphercoreend
## CIPHER CHARACTER
addi $t1, $a0, 0
lb $a0, string($a1)
jal __isaspace
beq $v0, 1, __ciphercoreisspace
jal __getcharoffset # this procedure returns the offset in $v0
addi $t2, $v0, 0 # $t2 <- offset
__thecipheralgorithm:
li $t7, 26 # $t7 <- modulus
sub $t3, $a0, $t2 # $t3 = Char - offset
add $t3, $t3, $s1 # $t3 += key
div $t3, $t7 # $t3 % modulus (26)
mfhi $t3
add $t3, $t3, $t2 # $t3 += offset
sb $t3, 0($a2)
__ciphercorenextchar:
addi $a0, $t1, 0
addi $a1, $a1, 1
addi $a2, $a2, 1
jal __ciphercore
__ciphercoreend:
lw $a0, 0($sp)
lw $a1, 4($sp)
lw $a2, 8($sp)
lw $ra, 12($sp)
addi $sp, $sp, 16
jr $ra
__ciphercoreisspace:
li $t5, 32
sb $t5, 0($a2)
j __ciphercorenextchar
# =================================================
# getCharOffset
#
# Returns the right offset to execute
# cipher and decipher operation
#
# The'offset is:
# During cipher:
# 'a': if the char is lowercase
# 'A': if the char is uppercase
# During decipher:
# 'z': if the char is lowercase
# 'Z': if the char is uppercase
#
# Paramether:
# $a0 <- Character to test
#
# Return:
# $v0 <- offset
# =================================================
__getcharoffset:
addi $sp, $sp, -8
sw $a0, 0($sp)
sw $ra, 4($sp)
jal __islowercase
lw $a0, 0($sp)
lw $ra, 4($sp)
addi $sp, $sp, 8
bne $v0, 1, __ciphercoreuppercase
__ciphercorelowercase:
beq $s0, 2, __deciphercorelowercase
li $v0, 97
jr $ra
__deciphercorelowercase:
li $v0, 122
jr $ra
__ciphercoreuppercase:
beq $s0, 2, __deciphercoreuppercase
li $v0, 65
jr $ra
__deciphercoreuppercase:
li $v0, 90
jr $ra
# =================================================
# strLen
#
# The procedure counts the string length and
# validates it. A valid string must not contain
# any character apart from letters and spaces
#
# Paramether;
# $a0 <- string to validate
#
# Return:
# $v0 <- string length
# $v1 <- error (-1/0)
# =================================================
__strlen:
addi $sp, $sp, -8
sw $a0, 0($sp)
sw $ra, 4($sp)
li $t0, 0
li $t1, 0
addi $t2, $a0, 0
li $t3, 10 # New line character
__strlenloop:
lb $t1, 0($t2)
beqz $t1, __strlenexit # $t1 = \00 ?
beq $t1, $t3 __strlenexit # $t1 = \n ?
addi $a0, $t1, 0 # $a0 <- Currenct char
jal __isavalidchar # returns 1 if it's valid
bne $v0, 1, __strlenerror
addi $t2, $t2, 1
addi $t0, $t0, 1
j __strlenloop
__strlenexit:
lw $a0, 0($sp)
lw $ra, 4($sp)
addi $sp, $sp, 8
addi $v0, $t0, 0
li $v1, 0
jr $ra
__strlenerror:
lw $a0, 0($sp)
lw $ra, 4($sp)
addi $sp, $sp, 8
li $v0, 4
la $a0, errstrprompt
syscall
li $v0, -1
li $v1, -1
jr $ra
# =================================================
# isAChar
#
# Paramether
# $a0 <- Character to test
#
# Returns:
# $v0 <- 1: valid char
# 0: not valid char
# =================================================
__isavalidchar:
addi $sp, $sp, -8
sw $a0, 0($sp)
sw $ra, 4($sp)
jal __isaletter
beq $v0, 1, __validcharfound
jal __isaspace
beq $v0, 1, __validcharfound
lw $a0, 0($sp)
lw $ra, 4($sp)
addi $sp, $sp, 8
li $v0, 0
jr $ra
__validcharfound:
lw $a0, 0($sp)
lw $ra, 4($sp)
addi $sp, $sp, 8
li $v0, 1
jr $ra
# =================================================
# isALetter
#
# Paramether:
# $a0 <- Character to test
#
# Returns:
# $v0 <- 1: is a letter
# 0: not a letter
# =================================================
__isaletter:
addi $sp, $sp, -8
sw $a0, 0($sp)
sw $ra, 4($sp)
jal __islowercase
beq $v0, 1, __isaletterok
blt $v0, 0, __isalettererror
jal __isuppercase
beq $v0, 1, __isaletterok
blt $v0, 0, __isalettererror
__isalettererror:
lw $a0, 0($sp)
lw $ra, 4($sp)
addi $sp, $sp, 8
li $v0, 0
jr $ra
__isaletterok:
lw $a0, 0($sp)
lw $ra, 4($sp)
addi $sp, $sp, 8
li $v0, 1
jr $ra
# =================================================
# isASpace
#
# Paramether
# $a0 <- Char to test
#
# Returns
# $v0 <- 1: is a space
# 0: not a space
# =================================================
__isaspace:
bne $a0, 32, __isnotaspace
li $v0, 1
jr $ra
__isnotaspace:
li $v0, 0
jr $ra
# =================================================
# isLowerCase
#
# Paramether
# $a0 <- Char to test
#
# Return
# $v0 <- 1: is lowercase
# 0: not lowercase
# -1: not a letter
# =================================================
__islowercase:
blt $a0, 97, __isnotlowercase
bgt $a0, 122, __islowercaseerror
li $v0, 1
jr $ra
__islowercaseerror:
li $v0, -1
jr $ra
__isnotlowercase:
li $v0, 0
jr $ra
# =================================================
# isUpperCase
#
# Paramether
# $a0 <- character to test
#
# Returns
# $v0 <- 1: is uppercase
# 0: not uppercase
# -1: not a letter
# =================================================
__isuppercase:
blt $a0, 65, __isuppercaseerror
bgt $a0, 90, __isnotuppercase
li $v0, 1
jr $ra
__isuppercaseerror:
li $v0, -1
jr $ra
__isnotuppercase:
li $v0, 0
jr $ra