-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.asm
More file actions
1244 lines (1097 loc) · 33.5 KB
/
main.asm
File metadata and controls
1244 lines (1097 loc) · 33.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
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
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
.text
jal loadPath
la $t7,fileWords # ponteiro para o texto
li $t6,' '
removeCBr: lb $t0,($t7) # subistituir todos os '\r' pro ' '
addi $t7,$t7,1
beqz $t0,CBrRemoved
bne $t0,13,removeCBr
sb $t6,-1($t7)
j removeCBr
CBrRemoved: la $s7,fileWords
jal consumeBlankLines
jal readByte
bne $v1,'.',errorNoSection
jal readByte
bne $v1,'d',maybeText
jal readByte
bne $v1,'a',errorNoSection
jal readByte
bne $v1,'t',errorNoSection
jal readByte
bne $v1,'a',errorNoSection
li $s6,0 # 'nosso pc' contador da memoria de dados
la $a0,openDataFile # endere�o da string que cont�m o nome do arquivo
jal writeHeader
jal readNotNullByte
beq $v1,10,dataSection # checo se depos de ler text nao ha nenhum char significativo
beq $v1,0,success
j errorNoSection
jal consumeBlankLines
findText: jal writeRodape
jal closeFile
jal readByte
bne $v1,'.',errorNoSection
jal readByte
maybeText: bne $v1,'t',errorNoSection
jal readByte
bne $v1,'e',errorNoSection
jal readByte
bne $v1,'x',errorNoSection
jal readByte
bne $v1,'t',errorNoSection
la $a0,openTextFile # endere�o da string que cont�m o nome do arquivo
jal writeHeader
li $s6,0x400000 # 'nosso pc' contador da memoria de instrucoes
jal readNotNullByte
beq $v1,10,textSection # checo se depos de ler text nao ha nenhum char significativo
beq $v1,0,success
j errorNoSection
dataSection: # programa principal para tratamento da area .data
jal consumeBlankLines
lb $t0,($s7)
beq $t0,'.',findText
beq $t0,0,success # nao tem area .text
jal checkIfIsLabel
beq $v0,$zero,errorWrongParam
la $a0,dataLabelKeys
jal storeLabel
la $t0,dataLabelValues
add $t0,$t0,$v0
sw $s6,($t0)
jal readNotNullByte
beq $v1,10,dataSection
bne $v1,'.',errorWStorageType
jal readByte
bne $v1,'w',errorWStorageType
jal readByte
bne $v1,'o',errorWStorageType
jal readByte
bne $v1,'r',errorWStorageType
jal readByte
bne $v1,'d',errorWStorageType
dataLine: jal readNotNullByte
beq $v1,10,dataSection
addi $s7,$s7,-1
li $a3,','
jal getNumberValue
move $s5,$v0
jal writePC
move $a0,$s5
jal writeInstr
addi $s6,$s6,4 # 4 pq trato de words
lb $t0,-1($s7) # checar o �ltimo Byte lido
beq $t0,10,dataSection
j dataLine
textSection: # programa principal para tratamento da area .text
move $s5,$s7 # salvo o ponteiro para o inicio do .text
jal storeAllTextLabels
move $s7,$s5 # restoro o pornteito para reler o .text de novo focado nas instrucoes
li $s6,0x400000 # restauro o contador de instr
textLine:
jal consumeBlankLines
lb $t0,($s7)
beq $t0,0,success
# pra cima, temos a condicao de parada
jal checkIfIsLabel
beq $v0,$zero,typeRA
skipLabel: lb $t0,($s7)
addi $s7,$s7,1
bne $t0,':',skipLabel
jal consumeBlankLines
lb $t0,($s7)
beq $t0,0,success
# pra cima vemos se temos uma Label na linha antes de tudo e pulamos ela
typeRA: la $a0,valuesRA
la $a1,keysRA
li $a2,1 # numero de values por key
li $a3,' '
jal getValueAddr # pega o endereco relativo a chave passada
beq $v0,$zero,typeRB
# Achei a instr, agora so empilhar na pilha: funct:5($sp) shamt(4) rd(3) rt(2) rs(1) opcode:0($sp)
addi $sp,$sp,-8 # desloco 8 Bytes, mas nunca uso 6 ou 7($sp)
lb $t0,($v0) # pego o funct do cmd lido
sb $t0,5($sp) # empilhar funct
li $a3,','
jal getRegCode # pegar cod do rd
sb $v0,3($sp) # empilhar rd
li $a3,','
jal getRegCode # pegar cod do rs
sb $v0,1($sp) # empilhar rs
li $a3,10
jal getRegCode # pegar cod do rt
sb $v0,2($sp) # empilhar rt
jal checkManyParams
sb $zero,4($sp) # empilhar shamt
sb $zero,0($sp) # empilhar opcode
jal writePC
jal assemblerR
move $a0,$v0
jal writeInstr
addi $s6,$s6,4
j textLine
typeRB: la $a0,valuesRB
la $a1,keysRB
li $a2,1 # numero de values por key
li $a3,' '
jal getValueAddr # pega o endereco relativo a chave passada
beq $v0,$zero,typeRC
# Achei a instr, agora so empilhar na pilha: funct:5($sp) shamt(4) rd(3) rt(2) rs(1) opcode:0($sp)
addi $sp,$sp,-8
lb $t0,($v0)
sb $t0,5($sp) # empilhar funct
li $a3,','
jal getRegCode
sb $v0,1($sp) # empilhar rs
li $a3,10
jal getRegCode
sb $v0,2($sp) # empilhar rt
jal checkManyParams
sb $zero,4($sp) # empilhar shamt
sb $zero,3($sp) # empilhar rd
sb $zero,0($sp) # empilhar opcode
jal writePC
jal assemblerR
move $a0,$v0
jal writeInstr
addi $s6,$s6,4
j textLine
typeRC: la $a0,valuesRC
la $a1,keysRC
li $a2,1 # numero de values por key
li $a3,' '
jal getValueAddr # pega o endereco relativo a chave passada
beq $v0,$zero,typeRD
# Achei a instr, agora so empilhar na pilha: funct:5($sp) shamt(4) rd(3) rt(2) rs(1) opcode:0($sp)
addi $sp,$sp,-8
lb $t0,($v0)
sb $t0,5($sp) # empilhar funct
li $a3,10
jal getRegCode
sb $v0,1($sp) # empilhar rs
jal checkManyParams
sb $zero,4($sp) # empilhar shamt
sb $zero,3($sp) # empilhar rd
sb $zero,2($sp) # empilhar rt
sb $zero,0($sp) # empilhar opcode
jal writePC
jal assemblerR
move $a0,$v0
jal writeInstr
addi $s6,$s6,4
j textLine
typeRD: la $a0,valuesRD
la $a1,keysRD
li $a2,2 # numero de values por key
li $a3,' '
jal getValueAddr # pega o endereco relativo a chave passada
beq $v0,$zero,typeRE
# Achei a instr, agora so empilhar na pilha: funct:5($sp) shamt(4) rd(3) rt(2) rs(1) opcode:0($sp)
addi $sp,$sp,-8 # desloco 8 Bytes, mas nunca uso 6 ou 7($sp)
lb $t0,($v0) # pego o opcode do cmd lido
sb $t0,0($sp) # empilhar opcode
lb $t0,1($v0) # pego o funct do cmd lido
sb $t0,5($sp) # empilhar funct
li $a3,','
jal getRegCode # pegar cod do rd
sb $v0,3($sp) # empilhar rd
li $a3,','
jal getRegCode # pegar cod do rs
sb $v0,1($sp) # empilhar rs
li $a3,10
jal getRegCode # pegar cod do rt
sb $v0,2($sp) # empilhar rt
jal checkManyParams
sb $zero,4($sp) # empilhar shamt
jal writePC
jal assemblerR
move $a0,$v0
jal writeInstr
addi $s6,$s6,4
j textLine
typeRE: la $a0,valuesRE
la $a1,keysRE
li $a2,2 # numero de values por key
li $a3,' '
jal getValueAddr # pega o endereco relativo a chave passada
beq $v0,$zero,typeRF
# Achei a instr, agora so empilhar na pilha: funct:5($sp) shamt(4) rd(3) rt(2) rs(1) opcode:0($sp)
addi $sp,$sp,-8 # desloco 8 Bytes, mas nunca uso 6 ou 7($sp)
lb $t0,($v0) # pego o opcode do cmd lido
sb $t0,0($sp) # empilhar opcode
lb $t0,1($v0) # pego o funct do cmd lido
sb $t0,5($sp) # empilhar funct
li $a3,','
jal getRegCode
sb $v0,3($sp) # empilhar rd
li $a3,10
jal getRegCode
sb $v0,1($sp) # empilhar rs
jal checkManyParams
sb $zero,4($sp) # empilhar shamt
sb $zero,2($sp) # empilhar rt
jal writePC
jal assemblerR
move $a0,$v0
jal writeInstr
addi $s6,$s6,4
j textLine
typeRF: la $a0,valuesRF
la $a1,keysRF
li $a2,1 # numero de values por key
li $a3,' '
jal getValueAddr # pega o endereco relativo a chave passada
beq $v0,$zero,typeRG
# Achei a instr, agora so empilhar na pilha: funct:5($sp) shamt(4) rd(3) rt(2) rs(1) opcode:0($sp)
addi $sp,$sp,-8 # desloco 8 Bytes, mas nunca uso 6 ou 7($sp)
lb $t0,0($v0)
sb $t0,5($sp) # empilhar funct
li $a3,','
jal getRegCode
sb $v0,3($sp) # empilhar rd
li $a3,','
jal getRegCode
sb $v0,2($sp) # empilhar rt
li $a3,' '
jal getNumberValue
bgeu $v0,0x20,errorOutOfRange# deve caber em 5 bits
sb $v0,4($sp) # empilhar shamt
jal checkManyParams
sb $zero,1($sp) # empilhar rs
sb $zero,0($sp) # empilhar opcode
jal writePC
jal assemblerR
move $a0,$v0
jal writeInstr
addi $s6,$s6,4
j textLine
typeRG: la $a0,valuesRG
la $a1,keysRG
li $a2,1 # numero de values por key
li $a3,' '
jal getValueAddr # pega o endereco relativo a chave passada
beq $v0,$zero,typeRH
# Achei a instr, agora so empilhar na pilha: funct:5($sp) shamt(4) rd(3) rt(2) rs(1) opcode:0($sp)
addi $sp,$sp,-8 # desloco 8 Bytes, mas nunca uso 6 ou 7($sp)
lb $t0,($v0) # pego o funct do cmd lido
sb $t0,5($sp) # empilhar funct
li $a3,','
jal getRegCode # pegar cod do rd
sb $v0,3($sp) # empilhar rd
li $a3,','
jal getRegCode # pegar cod do rt
sb $v0,2($sp) # empilhar rt
li $a3,10
jal getRegCode # pegar cod do rs
sb $v0,1($sp) # empilhar rs
jal checkManyParams
sb $zero,4($sp) # empilhar shamt
sb $zero,0($sp) # empilhar opcode
jal writePC
jal assemblerR
move $a0,$v0
jal writeInstr
addi $s6,$s6,4
j textLine
typeRH: la $a0,valuesRH
la $a1,keysRH
li $a2,1 # numero de values por key
li $a3,' '
jal getValueAddr # pega o endereco relativo a chave passada
beq $v0,$zero,typeIA
# Achei a instr, agora so empilhar na pilha: funct:5($sp) shamt(4) rd(3) rt(2) rs(1) opcode:0($sp)
addi $sp,$sp,-8
lb $t0,($v0)
sb $t0,5($sp) # empilhar funct
li $a3,10
jal getRegCode
sb $v0,3($sp) # empilhar rd
jal checkManyParams
sb $zero,4($sp) # empilhar shamt
sb $zero,2($sp) # empilhar rt
sb $zero,1($sp) # empilhar rs
sb $zero,0($sp) # empilhar opcode
jal writePC
jal assemblerR
move $a0,$v0
jal writeInstr
addi $s6,$s6,4
j textLine
typeIA: la $a0,valuesIA
la $a1,keysIA
li $a2,1 # numero de values por key
li $a3,' '
jal getValueAddr # pega o endereco relativo a chave passada
beq $v0,$zero,typeIB
# Achei a instr, agora so empilhar na pilha: imm:4-7($sp) rt(2) rs(1) opcode:0($sp)
addi $sp,$sp,-8 # desloco 8 Bytes e nunca uso 3($sp)
lb $t0,($v0)
sb $t0,0($sp) # empilhar opcode
li $a3,','
jal getRegCode
sb $v0,2($sp) # empilhar rt
li $a3,','
jal getRegCode
sb $v0,1($sp) # empilhar rs
li $a3,' '
jal getNumberValue
bge $v0,0x10000,errorOutOfRange# deve caber em 16 bits
sw $v0,4($sp) # empilhar imm
jal checkManyParams
jal writePC
jal assemblerI
move $a0,$v0
jal writeInstr
addi $s6,$s6,4
j textLine
typeIB: la $a0,valuesIB
la $a1,keysIB
li $a2,1 # numero de values por key
li $a3,' '
jal getValueAddr # pega o endereco relativo a chave passada
beq $v0,$zero,typeIC
# Achei a instr, agora so empilhar na pilha: addr:4-7($sp) rt(2) rs(1) opcode:0($sp)
addi $sp,$sp,-8 # desloco 8 Bytes e nunca uso 3($sp)
lb $t0,($v0)
sb $t0,0($sp) # empilhar opcode
li $a3,','
jal getRegCode
sb $v0,1($sp) # empilhar rs
li $a3,','
jal getRegCode
sb $v0,2($sp) # empilhar rt
li $a3,10
jal getTextLabelCode
subu $t0,$v0,$s6
addi $t0,$t0,-4
srl $t0,$t0,2 #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! nao sei pq tem q dividir por 4, mas funciona
sw $t0,4($sp) # empilhar addr
jal checkManyParams
jal writePC
jal assemblerI
move $a0,$v0
jal writeInstr
addi $s6,$s6,4
j textLine
typeIC: la $a0,valuesIC
la $a1,keysIC
li $a2,1 # numero de values por key
li $a3,' '
jal getValueAddr # pega o endereco relativo a chave passada
beq $v0,$zero,typeID
# Achei a instr, agora so empilhar na pilha: imm:4-7($sp) rt(2) rs(1) opcode:0($sp)
addi $sp,$sp,-8 # desloco 8 Bytes e nunca uso 3($sp)
lb $t0,($v0)
sb $t0,0($sp) # empilhar opcode
li $a3,','
jal getRegCode
sb $v0,2($sp) # empilhar rt
li $a3,'('
jal getNumberValue
bge $v0,0x10000,errorOutOfRange# deve caber em 16 bits
sw $v0,4($sp) # empilhar imm
li $a3,')'
jal getRegCode
sb $v0,1($sp) # empilhar rs
addi $s7,$s7,1 # quero pular a verificacao do ')'
jal checkManyParams
jal writePC
jal assemblerI
move $a0,$v0
jal writeInstr
addi $s6,$s6,4
j textLine
typeID: la $a0,valuesID
la $a1,keysID
li $a2,1 # numero de values por key
li $a3,' '
jal getValueAddr # pega o endereco relativo a chave passada
beq $v0,$zero,typeIE
# Achei a instr, agora so empilhar na pilha: imm:4-7($sp) rt(2) rs(1) opcode:0($sp)
addi $sp,$sp,-8 # desloco 8 Bytes e nunca uso 3($sp)
lb $t0,($v0)
sb $t0,0($sp) # empilhar opcode
li $a3,','
jal getRegCode
sb $v0,2($sp) # empilhar rt
li $a3,' '
jal getNumberValue
bge $v0,0x10000,errorOutOfRange# deve caber em 16 bits
sw $v0,4($sp) # empilhar imm
jal checkManyParams
sb $zero,1($sp)
jal writePC
jal assemblerI
move $a0,$v0
jal writeInstr
addi $s6,$s6,4
j textLine
typeIE: la $a0,valuesIE
la $a1,keysIE
li $a2,2 # numero de values por key
li $a3,' '
jal getValueAddr # pega o endereco relativo a chave passada
beq $v0,$zero,typeJA
# Achei a instr, agora so empilhar na pilha: addr:4-7($sp) rt(2) rs(1) opcode:0($sp)
addi $sp,$sp,-8 # desloco 8 Bytes e nunca uso 3($sp)
lb $t0,($v0)
sb $t0,0($sp) # empilhar opcode
lb $t0,1($v0)
sb $t0,2($sp) # empilhar rt
li $a3,','
jal getRegCode
sb $v0,1($sp) # empilhar rs
li $a3,10
jal getTextLabelCode
subu $t0,$v0,$s6
addi $t0,$t0,-4
srl $t0,$t0,2 #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! nao sei pq tem q dividir por 4, mas funciona
sw $t0,4($sp) # empilhar addr
jal checkManyParams
jal writePC
jal assemblerI
move $a0,$v0
jal writeInstr
addi $s6,$s6,4
j textLine
typeJA: la $a0,valuesJA
la $a1,keysJA
li $a2,1 # numero de values por key
li $a3,' '
jal getValueAddr # pega o endereco relativo a chave passada
beq $v0,$zero,noInstr
# Achei a instr, agora so empilhar na pilha: addr:4($sp) & opcode:0($sp)
lb $t0,($v0)
sb $t0,0($sp)
li $a3,10
jal getTextLabelCode
srl $t0,$v0,2 #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! nao sei pq tem q dividir por 4, mas funciona
sw $t0,4($sp)
jal checkManyParams
jal writePC
jal assemblerJ
move $a0,$v0
jal writeInstr
addi $s6,$s6,4
j textLine
noInstr: addi $s7,$s7,1
jal errorInvInstr
success: jal writeRodape
li $v0,55
la $a0,msgSuccess
li $a1,1
syscall
end: # parar o programa
jal closeFile
li $v0, 10
syscall
writeHeader: # escrever no openFilePath
# abrir o arquivo para escrita (modo de escrita)
# recebe em $a0, o PATH para criar arquivo
li $v0,13 # c�digo da chamada do sistema para abrir o arquivo
li $a1, 1 # modo de escrita (1)
li $a2, 0
syscall
move $s0, $v0 # armazenar o descritor de arquivo retornado
# escrever no arquivo .mif
li $v0, 15 # c�digo da chamada do sistema para escrever no arquivo
move $a0, $s0
la $a1, header
li $a2, 80 # comprimento da string
syscall
jr $ra
writeRodape: li $v0, 15 # c�digo da chamada do sistema para escrever no arquivo
move $a0, $s0
la $a1,rodape
li $a2, 6 # comprimento da string
syscall
jr $ra
writePC: # escrever o valor do PC:
# converter o conteudo do registrador para hexa
addi $sp, $sp, -4
sw $ra, 0($sp)
move $a0, $s6 # PC
la $a1, buffer # buffer para o valor
li $a2, 9 # tamanho do buffer
jal binToHex
li $v0, 15 # c�digo da chamada do sistema para escrever no arquivo
move $a0, $s0
la $a1, buffer
li $a2, 8 # comprimento da string
syscall
# escrever o separador " : "
li $v0, 15 # c�digo da chamada do sistema para escrever no arquivo
move $a0, $s0
la $a1, separador
li $a2, 3 # comprimento da string
syscall
lw $ra, 0($sp)
addi $sp, $sp, 4
jr $ra
writeInstr: # escrever o valor da instrucao
# recebe em $a0 a instrucao pra repassar pra intToHex
move $a0,$a0
la $a1, buffer # buffer para o valor
li $a2, 9 # tamanho do buffer
addi $sp, $sp, -4
sw $ra, 0($sp)
jal binToHex
li $v0, 15 # c�digo da chamada do sistema para escrever no arquivo
move $a0, $s0
la $a1, buffer
li $a2, 8 # comprimento da string
syscall
# escrever o ";" no fim da linha
li $v0, 15 # c�digo da chamada do sistema para escrever no arquivo
move $a0, $s0
la $a1, fimLinha
li $a2, 2 # comprimento da string
syscall
lw $ra, 0($sp)
addi $sp, $sp, 4
jr $ra
closeFile: # fechar o arquivo .MIF
li $v0, 16 # c�digo do sistema para fechar um arquivo
move $a0, $s0 # identificador do arquivo
syscall
jr $ra
readByte: # ler um Byte (Char) e armazena em $v1, incrementando o ponteiro
lbu $v1,($s7)
addi $s7,$s7,1
jr $ra
readNotNullByte:# ler proxs Bytes (Char) ate achar um (!= ' ') e armazena em $v1, incrementando o ponteiro
lbu $v1,($s7)
addi $s7,$s7,1
beq $v1,' ',readNotNullByte
beq $v1,9,readNotNullByte
jr $ra
printChar: # mostrar na tela o conteudo de $a0 como char
li $v0,11
syscall
jr $ra
printInt: # mostrar na tela o conteudo de $a0 como int
li $v0,1
syscall
jr $ra
printHexa: # mostrar na tela o conteudo de $a0 como hexadecimal
li $v0,34
syscall
jr $ra
printArq: # mostrar na tela no o arquivo lido
li $v0,4
la $a0,fileWords
syscall
jr $ra
binToHex:
li $t3, 8 # $t3 = numero de caracteres (8)
li $t4, 16 # $t4 = base hexadecimal
addi $a1, $a1, 8 # aponta pro final do buffer
sb $zero, 0($a1)
convertLoop: remu $t2, $a0, $t4 # $t2 = $a0 % 16
lb $t2,hexaSymbols($t2)
sb $t2, -1($a1) # Store the ASCII character
srl $a0,$a0,4 # $a0 = $a0 / 16
subi $a1, $a1, 1 # Move the buffer pointer left
subi $t3, $t3, 1 # Decrement character count
bnez $t3, convertLoop
jr $ra # Return
consumeBlankLines: # consome todos os ' ' e '\n' seguidos
lbu $t1,($s7)
addi $s7,$s7,1
beq $t1,' ',consumeBlankLines # ignorar spaces
beq $t1,9,consumeBlankLines # ignorar tabs
beq $t1,10,consumeBlankLines # ignorar quebras de linha em linhas vazias
addi $s7,$s7,-1 # volta em 1 o ponteiro do arq para lermos o char != '\n' depois
jr $ra
consumeSpaces: # consome todos os ' '
lbu $t1,($s7)
addi $s7,$s7,1
beq $t1,' ',consumeSpaces
beq $t1,9,consumeSpaces
addi $s7,$s7,-1 # volta em 1 o ponteiro do arq para lermos o char != ' '
jr $ra
checkManyParams: # indica erro se tiver mais parametros numa linha
addi $s7,$s7,-1 # pra tambe�m checar o indicador do final da palavra
addi $sp,$sp,-4
sw $ra,0($sp)
jal readNotNullByte
lw $ra,0($sp)
addi $sp,$sp,4
bne $v1,10,checkEndFile
jr $ra
checkEndFile: bne $v1,0,errorManyParams
addi $s7,$s7,-1 # pra reler o 0 na condicao de parada do loop
jr $ra
getValueAddr: # recebe $a0(array dos valores), $a1(array das chaves), $a2(num de valor por chave) e $a3(indicador do final da palavra)
# le a palavra atual e retorna, se achar, o ponteiro para o(s) valor(es) em $v0(+) ou 0 se nao achar
move $t7,$s7 # salvo o endereco que estou lendo para comparar do inicio para os proximos instrucoes da string
move $t0,$a0 # ponteiro para indice do array dos Hexas
move $t1,$a1 # ponteiro para indice do char a ser lido da string de instrucoes
checkByte: lb $t2,($t1) # byte lido da string de instrucoes
lbu $t3,($s7) # byte lido do arq
addi $s7,$s7,1
beq $t3,' ',match # SE achamos ' ', entao ja lemos palavra toda e temos um match
beq $t3,9,match # SE achamos '\t' , entao ja lemos palavra toda e temos um match
beq $t3,$a3,match # OU se achamos nosso indicador -> ',' ou '\n' ou ')'
beq $t3,0,match # OU se achamos o 0 indicando fim de arquivo
bne $t2,$t3,nextKey
addi $t1,$t1,1
j checkByte
findNextKey: beq $t2,0,notFound # se achar zero, ja leu a string toda sem achar o comando
addi $t1,$t1,1
lb $t2,($t1)
nextKey: bne $t2,',',findNextKey
addi $t1,$t1,1
add $t0,$t0,$a2 # pulo os valores da chave atual e indexo os da prox chave
move $s7,$t7 # reseto o ponteiro do arq para comparar com outro opcode
j checkByte
match: bne $t2,',',nextKey # por convencao as chaves terminam em ','. Entao garanto que li a chave toda para evitar palavras contidas: add esta em addi
move $v0,$t0
jr $ra
notFound: move $v0,$zero
move $s7,$t7 # reseto o ponteiro do arq para comparar com outra string de instrucoes
jr $ra
getRegCode: # recebe em $a3 o indicador do getValueAddr apenas para repassar para ele
# le o registrador atual do arquivo e, se achar, retorna o codigo em $v0 ou da erro por falta de parametros(registradores)
#move $t3,$a3
addi $sp,$sp,-4
sw $ra,0($sp)
jal readNotNullByte
beq $v1,10,errorFewParams
bne $v1,'$',errorWrongParam # registradores comecam com $
lbu $t1,($s7)
bltu $t1,48,errorNoSuchOperator # aqui lemos um caracter que nao existe nos registradores
la $a1,regKeysNaN # assumo que o registrador esta escrito com seu 'apelido': $9 -> $t2
bgeu $t1,58,keepNaNKeys # aqui lemos um caracter nao numerico entao acertamos na assuncao acima
la $a1,regKeysNum # aqui lemos um caracter nao numerico entao erramos na assun�cao
keepNaNKeys: la $a0,numValues # agr temos que achar o valor desse registrador
li $a2,1 # numero de values por key
#move $a3,$t3
jal getValueAddr # pega o endereco relativo a chave passada
beq $v0, $zero,errorNoSuchOperator # registrador inexistente
lb $v0,($v0)
lw $ra,0($sp)
addi $sp,$sp,4
jr $ra
getNumberValue: # receve em $a3 um indicador de fim de numero
# retorna em $v0 o valor numerico de um numero decimal escrito no arquivo
addi $sp,$sp,-4
sw $ra,0($sp)
move $t9,$zero # flag de numero negativo, assumo sem sinal
move $v0,$zero # valor de retorno da funcao
jal readNotNullByte
beqz $v1,success
bne $v1,'-',noFlag
addiu $t9,$zero,1 # ativo a flag de numero com sinal
jal readByte
noFlag: bne $v1,'0',dec
jal readByte
beq $v1,'x',hexa # nao come�a com 0x, deve ser decimal. Poderia tratar como octal, mas n�o ser� feito
addi $s7,$s7,-1
j dec
hexa: move $t7,$s7 # salvo o endere�o do MSB
la $t0,hexaSymbols
li $t1,16
j findLSB
dec: addi $t7,$s7,-1 # salvo o endere�o do MSB
la $t0,decSymbols
li $t1,10
findLSB: jal readByte
beq $v1,' ',LSB
beq $v1,9,LSB
beq $v1,10,LSB
beq $v1,0,LSB
beq $v1,$a3,LSB # quando ler no .data, passar ',' . PAssar ' ' ou 10 c.c.
j findLSB
LSB: addi $t8,$s7,-2 # vetor $t8 aponta pro LSB
move $t4,$zero # expoente $t4 da base $t1
nextDigit: move $t5,$zero # index do digito na lista de simbolos. Note que o index = valor do numero
lb $t2,($t8)
findSymbol: lb $t3,($t0) # simbolo de index $t5
beq $t3,0,errorInvSymbol
beq $t2,$t3,foundValue
addi $t0,$t0,1
addi $t5,$t5,1
j findSymbol
foundValue: subu $t0,$t0,$t5 # reseto o $t0 para o priiro elemento da lista
addi $sp,$sp,-1
sb $t4,0($sp) # salvar o valor do expoente
exponential: beq $t4,$zero,gotDigitValue # calculei $t5*$t1^($t4) e armazenei em $t5
mul $t5,$t5,$t1
mfhi $t6 # checar se passou de 32 bits
bne $t6,$zero,errorOutOfRange
addi $t4,$t4,-1
j exponential
gotDigitValue: lb $t4,0($sp) # recupero o expoente(peso) do ultimo digito
addi $sp,$sp,1
add $v0,$v0,$t5
addi $t4,$t4,1
beq $t8,$t7,retNumber
addi $t8,$t8,-1
j nextDigit
retNumber: beq $t9,$zero,unsigned
not $v0,$v0
addi $v0,$v0,1
unsigned: lw $ra,0($sp)
addi $sp,$sp,4
jr $ra
getDataLabelCode: # recebe em $a3 o parametros do getLabelCode apenas para repassar para ele
# chama getLabelCode com os parametros da secao .text e trata erros
addi $sp,$sp,-4
sw $ra,0($sp)
la $a0,dataLabelValues
la $a1,dataLabelKeys
jal getLabelAddr
beq $v0,$zero,errorDataLabel
lw $v0,($v0)
lw $ra,0($sp)
addi $sp,$sp,4
jr $ra
errorDataLabel: la $a0,textLabelValues
la $a1,textLabelKeys
move $a2,$zero # nao me importo em pegar o endereco
jal getValueAddr
beq $v0,$zero,errorNoSuchLabel
j errorInvMemory
getTextLabelCode:# recebe em $a3 o parametros do getLabelCode apenas para repassar para ele
# chama getLabelCode com os parametros da secao .text e trata erros
addi $sp,$sp,-4
sw $ra,0($sp)
la $a0,textLabelValues
la $a1,textLabelKeys
jal getLabelAddr
beq $v0,$zero,errorTextLabel
lw $v0,($v0)
lw $ra,0($sp)
addi $sp,$sp,4
jr $ra
errorTextLabel: la $a0,dataLabelValues
la $a1,dataLabelKeys
move $a2,$zero # nao me importo em pegar o endereco
jal getValueAddr
beq $v0,$zero,errorNoSuchLabel
j errorInvSkip
getLabelAddr: # recebe em $a0,$a1,$a3 o parametros do getValueAddr apenas para repassar para ele
# retorna em $v0, o endereco do valor da label(PC) da secao escolhida pelos parametros $a0 e $a1 ou 0 caso nao ache.
addi $sp,$sp,-4
sw $ra,0($sp)
jal consumeSpaces
lb $t0,($s7)
beq $t0,'$',errorWrongParam
li $a2,4 # cada valor esta em Words (4 Bytes)
jal getValueAddr
lw $ra,0($sp)
addi $sp,$sp,4
jr $ra
assemblerR: # desempilho a pilha - funct:5($sp) shamt(4) rd(3) rt(2) rs(1) opcode:0($sp) - e monto o codigo de instrucao tipo R em $v0
lb $a0,0($sp)
move $t0,$a0
sll $t0,$t0,5
lb $a0,1($sp)
add $t0,$t0,$a0
sll $t0,$t0,5
lb $a0,2($sp)
add $t0,$t0,$a0
sll $t0,$t0,5
lb $a0,3($sp)
add $t0,$t0,$a0
sll $t0,$t0,5
lb $a0,4($sp)
add $t0,$t0,$a0
sll $t0,$t0,6
lb $a0,5($sp)
add $t0,$t0,$a0
add $sp,$sp,8
move $v0,$t0
jr $ra
assemblerI: # desempilho a pilha - addr:4-7($sp) rt(2) rs(1) opcode:0($sp) - e monto o codigo de instrucao tipo I em $v0
lb $a0,0($sp)
move $t0,$a0
sll $t0,$t0,5
lb $a0,1($sp)
add $t0,$t0,$a0
sll $t0,$t0,5
lb $a0,2($sp)
add $t0,$t0,$a0
sll $t0,$t0,16
lw $a0,4($sp)
andi $a0,$a0,0xffff # deixar numeros negativos em 16 bits
add $t0,$t0,$a0
add $sp,$sp,8
move $v0,$t0
jr $ra
assemblerJ: # desempilho a pilha - addr:4-7($sp) opcode:0($sp) - e monto o codigo de instrucao tipo I em $v0
lb $a0,0($sp)
move $t0,$a0
sll $t0,$t0,26
lw $a0,4($sp)
add $t0,$t0,$a0
move $v0,$t0
jr $ra
storeAllTextLabels:
addi $sp,$sp,-4
sw $ra,0($sp)
checkLine: jal consumeBlankLines
jal checkIfIsLabel
beq $v0,$zero,skipLine
# ver se a label � repetida antes de armazenar ou invoco erro
la $a0,textLabelValues
la $a1,textLabelKeys
move $a2,$zero # nao me importo em pegar o endereco
li $a3,':'
jal getValueAddr
bne $v0,$zero,errorSameLabel
#ver no dataLabel tbm
la $a0,dataLabelValues
la $a1,dataLabelKeys
move $a2,$zero # nao me importo em pegar o endereco
li $a3,':'
jal getValueAddr
bne $v0,$zero,errorSameLabel
#
la $a0,textLabelKeys
jal storeLabel
la $t0,textLabelValues
add $t0,$t0,$v0
sw $s6,($t0)
jal consumeBlankLines # serve para evitar erro na contagem(pc) de linhas apenas com label
skipLine: lb $t0,($s7)
addi $s7,$s7,1
beq $t0,0,done # terminei de armazenar as labels
bne $t0,10,skipLine
addi $s6,$s6,4
j checkLine
done: lw $ra,0($sp)
addi $sp,$sp,4
jr $ra
storeLabel: # escreve na memoria uma label separada por virgula
move $t0,$a0 # ponteiro para onde escrever as labels
move $t1,$zero # indice de onde estou colocando a label
checkStart: lb $t2,($t0) # checo se uma label ja foi escrita
beq $t2,0,storeByte
addi $t0,$t0,1
bne $t2,',',checkStart
addi $t1,$t1,4 # cada virgula lida representa uma label lida
j checkStart
storeByte: lb $t2,($s7) # Byte lido do arquivo
addi $s7,$s7,1
beq $t2,':',endWord