-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathProj6_umj.asm
1180 lines (1033 loc) · 31.7 KB
/
Proj6_umj.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
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
TITLE String Primitives & Macros Program (Proj6_umj.asm)
; Author: Jennifer Um
; Last Modified: 2022-03-04
; OSU email address: [email protected]
; Course number/section: CS271 Section 400
; Project Number: 6 Due Date: 2022-03-13
; Description: Prompt and receive ten valid SDWORDs from a user, then display the numbers, the sum, and the average.
; Program will use macros to read and write strings.
; ReadInt, ReadDec, WriteInt, and WriteDec are not allowed in this program.
mGetString MACRO m_prompt, m_input_str, m_input_str_len, m_input_str_maxlen
push EDX
push ECX
push EAX
mov EDX, m_prompt
call WriteString
mov EDX, m_input_str
mov ECX, m_input_str_maxlen
call ReadString
mov m_input_str_len, EAX
;call CRLF
pop EAX
pop ECX
pop EDX
ENDM
mDisplayString MACRO m_str_memory
PUSH EDX
MOV EDX, m_str_memory
CALL WriteString
POP EDX
ENDM
INCLUDE Irvine32.inc
.data
LO EQU -2147483648
MAXLEN EQU 50
VALID EQU 0
INVALID EQU 1
DESIREDVALIDCOUNTTOTAL EQU 10
ASCIIDECIMALOFMINUSSIGN EQU 45
special_case_int_array SDWORD 2,1,4,7,4,8,3,6,4,8 ; int array representation of absolute value of -2147483648 (most negative valid SD num)
intro_title BYTE "PROGRAMMING ASSIGNMENT 6: Designing low-level I/O procedures",13,10,"Written by: Jennifer Um",13,10,13,10,0
intro_info BYTE "Please provide 10 signed decimal integers.",13,10,"Each number needs to be small enough to fit inside a 32 bit register.",13,10,"After you have finished inputting the raw numbers I will display a list of the integers, their sum, and their average value.",13,10,13,10,0
goodbye BYTE 13,10,13,10,"Thanks for playing!",13,10,0
prompt BYTE "Please enter an signed number: ",0
input_error BYTE "ERROR: You did not enter a signed number or your number was too big.",13,10,0
array_title BYTE 13,10,"You entered the following numbers:",13,10,0
sum_title BYTE 13,10,"The sum of these numbers is: ",0
average_title BYTE 13,10,"The truncated average is: ",0
comma_and_space BYTE ", ",0
period_and_space BYTE ". ",0
extra_credit_info BYTE "** EC: Number each line of user input and display a running subtotal of the user’s valid numbers. These displays must use WriteVal.",13,10,13,10,0
valid_numbers_array SDWORD DESIREDVALIDCOUNTTOTAL DUP(0)
reverse_input_int_array SDWORD MAXLEN DUP(0)
multiplicand_int_array SDWORD MAXLEN DUP(0)
input_int_array SDWORD MAXLEN DUP(0)
reverse_int_array DWORD MAXLEN DUP(0)
reverse_ascii_str BYTE MAXLEN DUP(0)
input_str BYTE MAXLEN DUP(0)
reverse_input_str BYTE MAXLEN DUP(0)
ascii_str BYTE MAXLEN DUP(0)
input_int SDWORD 0
num_of_digits DWORD 0
index_tracker DWORD 0
input_state DWORD INVALID
multiplier SDWORD 1
valid_number_count DWORD 0
valid_numbers_sum SDWORD 0
valid_numbers_average SDWORD 0
input_char_as_int SDWORD ?
quotient SDWORD ?
remainder SDWORD ?
input_str_len DWORD ?
.code
main PROC
; print introduction
push OFFSET extra_credit_info
push OFFSET intro_info
push OFFSET intro_title
call Introduction
_getNumbersLoop:
mov EAX, valid_number_count
inc EAX
; EC: print each line of user input and display a running subtotal of the user’s valid numbers
push OFFSET index_tracker
push OFFSET ascii_str
push OFFSET reverse_ascii_str
push OFFSET reverse_int_array
push EAX
call WriteVal
mDisplayString OFFSET period_and_space
; get the input
push OFFSET special_case_int_array
push OFFSET input_int_array
push OFFSET multiplicand_int_array
push OFFSET input_int
push OFFSET index_tracker
push OFFSET input_error
push OFFSET reverse_input_int_array
push OFFSET multiplier
push OFFSET num_of_digits
push MAXLEN
push OFFSET input_state
push OFFSET input_char_as_int
push OFFSET reverse_input_str
push OFFSET input_str_len
push input_str_len
push OFFSET input_str
push OFFSET prompt
call ReadVal
cmp input_state, INVALID
je _getNumbersLoop ; input_state = INVALID
; at this point, input_state is valid
; store input_int into the array
mov EAX, valid_number_count ; this is also the index to add the element
mov EBX, 4 ; type of SDWORD
mul EBX ; EAX = index * type
mov EBX, OFFSET valid_numbers_array
add EBX, EAX ; EBX = OFFSET valid_numbers_array + (index * type)
mov EDI, EBX ; EDI = OFFSET valid_numbers_array + (index * type)
mov EAX, input_int
mov [EDI], EAX
; increment valid number count
mov EAX, valid_number_count
inc EAX
mov valid_number_count, EAX
; check if we have enough valid numbers
cmp EAX, 10
jne _getNumbersLoop ; valid_number_count < 10
jmp _calculateValidNumbers ; valid_number_count > 10
_calculateValidNumbers:
; calculate the sum
push OFFSET index_tracker
push OFFSET valid_numbers_sum
push OFFSET valid_numbers_array
call SumValidNumbers
; calculate the average
push OFFSET valid_numbers_sum
push OFFSET valid_numbers_average
call AverageValidNumbers
; reset index_tracker to 0
mov EAX, 0
mov index_tracker, EAX
; print the results of the calculation
push OFFSET comma_and_space
push OFFSET index_tracker
push OFFSET ascii_str
push OFFSET reverse_ascii_str
push OFFSET reverse_int_array
push valid_numbers_sum
push valid_numbers_average
push OFFSET valid_numbers_array
push OFFSET array_title
push OFFSET sum_title
push OFFSET average_title
call PrintResults
; print farewell
push OFFSET goodbye
call Farewell
Invoke ExitProcess,0 ; exit to operating system
main ENDP
; -- WriteVal --
; Turn the SDWORD int into a string and print it
; preconditions: the following should already be set
; - [EBP+8] int
; postconditions
; - none
; receives:
; - [EBP+24] OFFSET index_tracker
; - [EBP+20] OFFSET ascii_str
; - [EBP+16] OFFSET reverse_ascii_array
; - [EBP+12] OFFSET reverse_int_array
; - [EBP+8] int
; return
; - [EBP+24] OFFSET index_tracker
; - [EBP+20] OFFSET ascii_str
; - [EBP+16] OFFSET reverse_ascii_array
; - [EBP+12] OFFSET reverse_int_array
WriteVal PROC
push EBP
mov EBP, ESP
push EAX
push EBX
push ECX
push EDX
push ESI
push EDI
; reset index_tracker
mov EDI, [EBP+24] ;OFFSET index_tracker
mov EAX, 0
mov [EDI], EAX
mov EAX, [EBP+8] ; int to convert to string
cmp EAX, 0
jl _negativeNumber ; EAX < 0
jmp _positiveNumber ; EAX >= 0
_positiveNumber:
mov ECX, 0
mov EDI, [EBP+12] ;OFFSET reverse_int_array
_positiveNumDividebyTenLoop:
CDQ
mov EBX, 10 ; divisor
idiv EBX ; EAX=quotient, EDX= negative remainder
add EDX, 48 ; EDX = postive remainder int + 48 = ASCII decimal representation
mov [EDI], EDX
add EDI, 4
inc ECX
cmp EAX, 0
jne _positiveNumDividebyTenLoop ; EAX != 0
jmp _fillReverseASCIIStr ; EAX = 0 at this point
_negativeNumber:
mov ECX, 0
mov EDI, [EBP+12] ;OFFSET reverse_int_array
_negativeNumDividebyTenLoop:
CDQ
mov EBX, 10 ; divisor
idiv EBX ; EAX=quotient, EDX= negative remainder
push EAX ; quotient
mov EAX, -1
mov EBX, EDX ; EBX = negative remainder
imul EBX ; EAX = negative remainder * -1 = positive remainder
add EAX, 48 ; EAX = postive remainder int + 48 = ASCII decimal representation
mov [EDI], EAX
add EDI, 4
inc ECX
pop EAX ; quotient
cmp EAX, 0
jne _negativeNumDividebyTenLoop ; EAX != 0
jmp _appendMinusSignASCII; EAX = 0 at this point
_appendMinusSignASCII:
mov EAX, ECX ; ECX currently holds the number of digits in the number and the index to add the int rep. of '-'
mov EBX, 4 ; Type of WORD
mul EBX ; EAX = size of type * index
mov EBX, [EBP+12] ;OFFSET reverse_int_array
add EBX, EAX ; EBX = OFFSET reverse_int_array + (size of type * index)
mov EDI, EBX ; EDX = OFFSET reverse_int_array + (size of type * index)
mov EAX, ASCIIDECIMALOFMINUSSIGN
mov [EDI], EAX
; increment ECX
inc ECX
jmp _fillReverseASCIIStr
; move BYTE values of reverse_int_array into reverse_ascii_array
; ECX = length of the reverse_int_array at this point
_fillReverseASCIIStr:
; populate index_tracker
mov EDI, [EBP+24] ; OFFSET index_tracker
mov [EDI], ECX
mov EDX, 0
_fillReverseASCIIStrLoop:
; get OFFSET of index in reverse_int_array being read
mov EAX, EDX ; EAX = index
mov EBX, 4 ; type of DWORD
push EDX
mul EBX ; EAX = type of DWORD * index
pop EDX
mov EBX, [EBP+12] ;OFFSET reverse_int_array
add EBX, EAX ; EBX = OFFSET reverse_int_array + (type of DWORD * index)
mov ESI, EBX ; ESI = OFFSET reverse_int_array + (type of DWORD * index)
; get OFFSET of index in reverse_ascii_array being updated
mov EAX, EDX ; EAX = index
mov EBX, 1 ; type of BYTE
push EDX
mul EBX ; EAX = type of BYTE * index
pop EDX
mov EBX, [EBP+16] ;OFFSET reverse_ascii_str
add EBX, EAX ; EBX = OFFSET reverse_ascii_str + (type of BYTE * index)
mov EDI, EBX ; EBX = OFFSET reverse_ascii_str + (type of BYTE * index)
mov EAX, [ESI] ; OFFSET reverse_int_str + (type of DWORD * index)
LODSB
STOSB
; increase the index
inc EDX
loop _fillReverseASCIIStrLoop
_fillASCIIStr:
mov ESI, [EBP+24] ; OFFSET index_tracker
mov ECX, [ESI]
mov ESI,[EBP+16] ;OFFSET reverse_ascii_str
add ESI, ECX
dec ESI
mov EDI, [EBP+20] ; OFFSET ascii_str
_fillASCIIStrLoop:
STD
LODSB
CLD
STOSB
loop _fillASCIIStrLoop
_appendNullChar:
mov ESI, [EBP+24] ; OFFSET index_tracker
mov ECX, [ESI]
mov EAX, 0
mov EDI, [EBP+20] ; OFFSET ascii_str
add EDI, ECX
STOSB
mDisplayString [EBP+20] ; OFFSET ascii string
pop EDI
pop ESI
pop EDX
pop ECX
pop EBX
pop EAX
pop EBP
RET 20
WriteVal ENDP
; -- PrintResults --
; Print the results (numbers in array, average, and sum).
; preconditions: the following should already be set
; - [EBP+48] OFFSET comma_and_space
; - [EBP+28] valid_numbers_sum
; - [EBP+24] valid_numbers_average
; - [EBP+20] OFFSET valid_numbers_array
; - [EBP+16] OFFSET array_title
; - [EBP+12] OFFSET sum_title
; - [EBP+8] OFFSET average_title
; postconditions
; - none
; receives:
; - [EBP+48] OFFSET comma_and_space
; - [EBP+44] OFFSET index_tracker
; - [EBP+40] OFFSET ascii_str
; - [EBP+36] OFFSET reverse_ascii_str
; - [EBP+32] OFFSET reverse_int_array
; - [EBP+28] valid_numbers_sum
; - [EBP+24] valid_numbers_average
; - [EBP+20] OFFSET valid_numbers_array
; - [EBP+16] OFFSET array_title
; - [EBP+12] OFFSET sum_title
; - [EBP+8] OFFSET average_title
; returns:
; - [EBP+48] OFFSET comma_and_space
; - [EBP+44] OFFSET index_tracker
; - [EBP+40] OFFSET ascii_str
; - [EBP+36] OFFSET reverse_ascii_str
; - [EBP+32] OFFSET reverse_int_array
PrintResults PROC
push EBP
mov EBP, ESP
push EAX
push EBX
push ECX
push EDX
push ESI
push EDI
; display array
mDisplayString [EBP+16] ; display array_title
mov ECX, DESIREDVALIDCOUNTTOTAL
;mov ESI, [EBP+20] ;OFFSET valid_numbers_array
mov EDX, 0 ; used for indexing
_printArrayValueLoop:
mov EAX, EDX ; index of number to print
mov EBX, 4 ; type of DWORD
push EDX
mul EBX ; EAX = type * index
pop EDX
mov EBX, [EBP+20] ;OFFSET valid_numbers_array
add EBX, EAX ; EBX = OFFSET valid_numbers_array + (type * index)
mov ESI, EBX ; ESI = OFFSET valid_numbers_array + (type * index)
mov EAX, [ESI]
; get the string of the number
push [EBP+44] ;OFFSET index_tracker
push [EBP+40] ;OFFSET ascii_str
push [EBP+36] ;OFFSET reverse_ascii_array
push [EBP+32] ;OFFSET reverse_int_array
push EAX
Call WriteVal
;mDisplayString [EBP+40] ; OFFSET ascii string
; determine if we need to print comma and space
cmp EDX, DESIREDVALIDCOUNTTOTAL-1
je _continuePrintArrayValueLoop ; EDX = 10
mDisplayString [EBP+48] ; EDX != 10. OFFSET comma_and_space
_continuePrintArrayValueLoop:
inc EDX ; update to next index
loop _printArrayValueLoop
; display sum
mDisplayString [EBP+12] ; display sum_title
push [EBP+44] ;OFFSET index_tracker
push [EBP+40] ;OFFSET ascii_str
push [EBP+36] ;OFFSET reverse_ascii_array
push [EBP+32] ;OFFSET reverse_int_array
mov EAX, [EBP+28] ; valid_numbers_sum
push EAX
Call WriteVal
;mDisplayString [EBP+40]
; display average
mDisplayString [EBP+8] ; display array_title
push [EBP+44] ;OFFSET index_tracker
push [EBP+40] ;OFFSET ascii_str
push [EBP+36] ;OFFSET reverse_ascii_array
push [EBP+32] ;OFFSET reverse_int_array
mov EAX, [EBP+24] ; valid_numbers_average
push EAX
Call WriteVal
;mDisplayString [EBP+40]
pop EDI
pop ESI
pop EDX
pop ECX
pop EBX
pop EAX
pop EBP
RET 44
PrintResults ENDP
; -- AverageValidNumbers --
; Average the numbers in the array.
; preconditions: the following should already be set
; - [EBP+12] OFFSET valid_numbers_sum
; - constant DESIREDVALIDCOUNTTOTAL should be set
; postconditions
; - none
; receives:
; - [EBP+12] OFFSET valid_numbers_sum
; - [EBP+8] OFFSET valid_numbers_array
; returns
; - [EBP+8] OFFSET valid_numbers_average
AverageValidNumbers PROC
push EBP
mov EBP, ESP
push EAX
push EBX
push ECX
push EDX
push ESI
push EDI
mov ESI, [EBP+12] ;OFFSET valid_numbers_sum
mov EAX, [ESI]
CDQ
mov EBX, DESIREDVALIDCOUNTTOTAL
IDIV EBX
mov EDI, [EBP+8] ; OFFSET valid_numbers_average
mov [EDI], EAX
pop EDI
pop ESI
pop EDX
pop ECX
pop EBX
pop EAX
pop EBP
RET 8
AverageValidNumbers ENDP
; -- SumValidNumbers --
; Sum the numbers in the array.
; preconditions: the following should already be set
; - [EBP+16] OFFSET index_tracker
; - [EBP+12] OFFSET valid_numbers_sum
; - [EBP+8] OFFSET valid_numbers_array
; - constant DESIREDVALIDCOUNTTOTAL should be set
; postconditions
; - none
; receives:
; - [EBP+16] OFFSET index_tracker
; - [EBP+12] OFFSET valid_numbers_sum
; - [EBP+8] OFFSET valid_numbers_array
; returns
; - [EBP+16] OFFSET index_tracker
; - [EBP+12] OFFSET valid_numbers_sum
SumValidNumbers PROC
push EBP
mov EBP, ESP
push EAX
push EBX
push ECX
push EDX
push ESI
push EDI
; reset index_tracker to 0
mov EDI, [EBP+16] ; OFFSET index_tracker
mov EAX, 0
mov [EDI], EAX
mov ECX, DESIREDVALIDCOUNTTOTAL
_updateSumLoop:
; get value of index_tracker
mov ESI, [EBP+16] ;OFFSET index_tracker
mov EAX, [ESI]
; get value stored at index in valid_numbers_array
mov EBX, 4 ; type of SDWORD
mul EBX ; EAX = type * index
mov EBX, [EBP+8] ;OFFSET valid_numbers_array
add EBX, EAX ; EBX = OFFSET valid_numbers_array + (type * index)
mov ESI, EBX ; ESI = OFFSET valid_numbers_array + (type * index)
mov EAX, [ESI] ;EAX =value stored at valid_numbers_array address
; get valid_numbers_sum
mov EDI, [EBP+12] ;OFFSET valid_numbers_sum
mov EBX, [EDI] ; EBX = valid_numbers_sum
add EBX, EAX ; EBX = value stored at valid_numbers_array address + valid_numbers_sum
mov [EDI], EBX
; inc index_tracker
mov EDI, [EBP+16] ;OFFSET index_tracker
mov EAX, [EDI]
inc EAX
mov [EDI], EAX
loop _updateSumLoop
pop EDI
pop ESI
pop EDX
pop ECX
pop EBX
pop EAX
pop EBP
RET 12
SumValidNumbers ENDP
; -- ReadVal --
; Prompt user to enter a number, read the input string from the user and verify it is a valid SDWORD.
; - if valid, convert it to an int if its a valid SDWORD number.
; - if invalid, print error message
; preconditions: the following should already be set
; - [EBP+72] OFFSET special_case_int_array
; - [EBP+36] MAXLEN
; - [EBP+8] OFFSET prompt (str)
; postconditions
; - none
; receives:
; - [EBP+72] OFFSET special_case_int_array
; - [EBP+68] OFFSET input_int_array
; - [EBP+64] OFFSET multiplicand_int_array
; - [EBP+60] OFFSET input_int
; - [EBP+56] OFFSET index_tracker
; - [EBP+52] OFFSET input_error
; - [EBP+48] OFFSET reverse_input_int_array
; - [EBP+44] OFFSET multiplier
; - [EBP+40] OFFSET num_of_digits
; - [EBP+36] MAXLEN
; - [EBP+32] OFFSET input_state
; - [EBP+28] OFFSET input_char_as_int
; - [EBP+24] OFFSET reverse_input_str
; - [EBP+20] OFFSET input_str_len
; - [EBP+16] OFFSET input_str_len
; - [EBP+12] OFFSET input_str
; - [EBP+8] OFFSET prompt (str)
; returns:
; - [EBP+68] OFFSET input_int_array
; - [EBP+64] OFFSET multiplicand_int_array
; - [EBP+60] OFFSET input_int
; - [EBP+56] OFFSET index_tracker
; - [EBP+52] OFFSET input_error
; - [EBP+48] OFFSET reverse_input_int_array
; - [EBP+44] OFFSET multiplier
; - [EBP+40] OFFSET num_of_digits
; - [EBP+32] OFFSET input_state
; - [EBP+28] OFFSET input_char_as_int
; - [EBP+24] OFFSET reverse_input_str
; - [EBP+20] OFFSET input_str_len
; - [EBP+12] OFFSET input_str
ReadVal PROC
push EBP
mov EBP, ESP
push EAX
push EBX
push ECX
push EDX
push ESI
push EDI
;reset the following variables
; - [EBP+60] OFFSET input_int
; - [EBP+56] OFFSET index_tracker
; - [EBP+40] OFFSET num_of_digits
mov EAX, 0
mov EDI, [EBP+60] ; OFFSET input_int
mov [EDI], EAX
mov EDI, [EBP+56] ;OFFSET index_tracker
mov [EDI], EAX
mov EDI, [EBP+40] ;OFFSET num_of_digits
mov [EDI], EAX
; set the following variables
; - [EBP+16] input_str_len
; - [EBP+12] OFFSET input_str
; - [EBP+8] OFFSET prompt (str)
; get by value the following variables
; - [EBP+36] MAXLEN
mGetString [EBP+8], [EBP+12], [EBP+16], [EBP+36]
; update global variable of input_str_len
mov EDI, [EBP+20] ; address of input_str_len
mov EAX, [EBP+16] ; value of input_str_len
mov [EDI], EAX
_checkIfInputLenZero:
mov EAX, [EBP+16] ; address of input_str_len
cmp EAX, 0
jg _reverseInputString ; input_str_len > 0
jmp _setInvalidInput ; input_str_len <= 0
; at this point, input_str_len >= 1
; reverse input_str and place in reverse_input_str
; set up loop counter and indices
_reverseInputString:
mov ECX, [EBP+16] ; input_str_len
mov ESI, [EBP+12] ; address of input_str
add ESI, ECX
dec ESI
mov EDI, [EBP+24] ; address of reverse_input_str
; reverse string
_revLoop:
STD
LODSB
CLD
STOSB
LOOP _revLoop
push [EBP+44] ; OFFSET multiplier
push [EBP+40] ; OFFSET num_of_digits
mov EAX, [EBP+32] ; OFFSET input_state
push EAX
push [EBP+28] ; OFFSET input_char_as_int
push [EBP+16] ; input_str_len
push [EBP+24] ; OFFSET reverse_input_str
call ValidateStringInputIsAnIntAndSetUpForConversion
; check input_state
mov ESI, [EBP+32] ; OFFSET input_state
mov EAX, [ESI]
cmp EAX, INVALID
je _setInvalidInput ; EAX (input_state) = INVALID
; at this point, input_str is a valid number
push [EBP+72] ; OFFSET special_case_int_array
push [EBP+68] ; OFFSET input_int_array
push [EBP+64] ; multiplicand_int_array
push [EBP+60] ; OFFSET input_int
push [EBP+56] ; OFFSET index tracker
push [EBP+48] ; OFFSET reverse_input_int_array
mov ESI, [EBP+44] ; OFFSET multiplier; pass by value
mov EAX, [ESI]
push EAX
mov ESI, [EBP+40] ; OFFSET num_of_digits; pass by value
mov EAX, [ESI]
push EAX
mov EAX, [EBP+32] ; OFFSET input_state
push EAX
push [EBP+28] ; OFFSET input_char_as_int
push [EBP+16] ; input_str_len
push [EBP+24] ; OFFSET reverse_input_str
call ConvertValidatedInputStringToSDWORD
; check input_state
mov ESI, [EBP+32] ;OFFSET input_state
mov EAX, [ESI]
cmp EAX, INVALID
je _setInvalidInput ; EAX (input_state) = INVALID
jmp _setValidInput ; EAX (input_state) = VALID
_setInvalidInput:
mDisplayString [EBP+52] ; OFFSET input error
jmp _endReadVal
_setValidInput:
jmp _endReadVal
_endReadVal:
pop EDI
pop ESI
pop EDX
pop ECX
pop EBX
pop EAX
pop EBP
RET 68
ReadVal ENDP
; -- ConvertValidatedInputStringToSDWORD --
; Get an input that is within SDWPORD bounds from the reverse_input_string
; preconditions: the following should already be set
; - [EBP+52] offset special_case_int_array
; - [EBP+32] OFFSET reverse_input_int_array
; - [EBP+28] multiplier
; - [EBP+24] num_of_digits
; - [EBP+12] input_str_len
; - [EBP+8] OFFSET reverse_input_str
; postconditions
; - none
; receives:
; - [EBP+52] OFFSET special_case_int_array
; - [EBP+48] OFFSET input_int_array
; - [EBP+44] OFFSET multiplicand_int_array
; - [EBP+40] OFFSET input_int
; - [EBP+36] OFFSET index_tracker
; - [EBP+32] OFFSET reverse_input_int_array
; - [EBP+28] multiplier
; - [EBP+24] num_of_digits
; - [EBP+20] OFFSET input_state
; - [EBP+16] OFFSET input_char_as_int
; - [EBP+12] input_str_len
; - [EBP+8] OFFSET reverse_input_str
; returns
; - [EBP+52] OFFSET special_case_int_array
; - [EBP+48] OFFSET input_int_array
; - [EBP+44] OFFSET multiplicand_int_array
; - [EBP+40] OFFSET input_int
; - [EBP+36] OFFSET index_tracker
; - [EBP+32] OFFSET reverse_input_int_array
; - [EBP+20] OFFSET input_state
; - [EBP+16] OFFSET input_char_as_int
; - [EBP+8] OFFSET reverse_input_str
ConvertValidatedInputStringToSDWORD PROC
push EBP
mov EBP, ESP
push EAX
push EBX
push ECX
push EDX
push ESI
push EDI
CLD
; for the length of num_of_digits, upload input int equivalent into reverse_input_int_array
mov ECX, [EBP+24] ; num_of_digits
mov ESI, [EBP+8] ; address of reverse_input_str
; update index_tracker to 0
mov EAX, 0
mov EDI, [EBP+36] ;OFFSET index_tracker
mov [EDI], EAX
_copyCharIntEquivalentIntoArrayLoop:
LODSB
sub AL, 48 ; ASCII of char decimal - 48 = input character as int
mov EDI, [EBP+16] ; OFFSET input_char_as_int
mov [EDI], EAX ; mov EAX (32 bit int) into input_char_as_int
; get index_tracker and store in EAX
mov ESI, [EBP+36] ;OFFSET index_tracker
mov EAX, [ESI]
mov EBX, 4 ; Type of SDWORD
mul EBX ; EAX = index_tracker * Type
mov EBX, [EBP+32] ; OFFSET reverse_input_int_array
add EBX, EAX ; EBX = OFFSET reverse_input_int_array + (index_tracker * Type)
mov EDI, EBX ; EDI = OFFSET reverse_input_int_array + (index_tracker * Type)
mov ESI, [EBP+16] ; OFFSET input_char_as_int
mov EAX, [ESI] ; mov input_char_as_int into EAX
mov [EDI], EAX ; mov input_char_as_int into correct index in reverse_input_int_array
; inc index_tracker
mov EDI, [EBP+36] ;OFFSET index_tracker
mov EAX, [EDI]
inc EAX
mov [EDI], EAX
; repoint ESI to next index in reverse_input_str
; EAX currently holds correct index value
mov EBX, 1
mul EBX ; EAX = index value * Type
mov EBX, [EBP+8] ; offset reverse_input_str
add EBX, EAX ; EBX = OFFSET reverse_input_str + (index value * Type)
mov ESI, EBX ; ESI = OFFSET reverse_input_str + (index value * Type)
loop _copyCharIntEquivalentIntoArrayLoop
; reverse reverse_input_int_array and store it in input_int_array
mov ECX, [EBP+24] ; num_of_digits
; update index_tracker to num_of_digits -1
mov EAX, ECX
dec EAX
mov EDI, [EBP+36] ;OFFSET index_tracker
mov [EDI], EAX
; set up arrays
mov ESI, [EBP+32] ;OFFSET reverse_input_int_array
_updateInputIntArrayLoop:
; store current value in ESI in index_tracker index of input_int_array
push ESI
; index to update in input_int_array
mov ESI, [EBP+36] ;OFFSET index_tracker
mov EAX, [ESI] ; EAX contains index to update in input_int_array
mov EBX, 4 ; type of SDWORD
mul EBX ; EAX = type of SDWORD * index to update in input_int_array
mov EBX, [EBP+48] ;OFFSET input_int_array
add EBX, EAX ; EBX = OFFSET input_int_array+ (type of SDWORD * index to update in input_int_array)
mov EDI, EBX ; EDI = OFFSET input_int_array+ (type of SDWORD * index to update in input_int_array)
pop ESI
mov EAX, [ESI] ; get current value from reverse_input_int_array
mov [EDI], EAX ; update input_int_array at specified index with current value from reverse_input_int_array
; move forward in input_int_array
add ESI, 4
; dec index tracker by one
mov EDI, [EBP+36] ;OFFSET index_tracker
mov EAX, [EDI] ; EAX contains current value in input_int_array
dec EAX
mov [EDI], EAX
loop _updateInputIntArrayLoop
; check to see if input array represents "-2147483648" (most negative valid SDWORD)
_checkIfInputIntArrayEqualToSpecialValue:
mov EAX, [EBP+28] ; multiplier
cmp EAX, -1
jne _skipInputIntArrayEqualToSpecialValue ; EAX != -1, therefore number is positive
mov EAX, [EBP+12] ; check if length of input matches lengthf of special number
cmp EAX, 11 ; max str length of "-2147483648"
jne _skipInputIntArrayEqualToSpecialValue ; EAX != 11
; compare if values in special_case_int_array and input_int_array are the same
mov ECX, [EBP+24] ; num_of_digits ; DEBUG
mov ESI, [EBP+48] ; OFFSET input_int_array
mov EDI, [EBP+52] ; OFFSET special_case_int_array
_compareArrayLoop:
mov EAX, [ESI] ; OFFSET input_int_array
mov EBX, [EDI] ; OFFSET special_case_int_array
cmp EAX, EBX
je _continueCompareArrayLoop ; EAX = EBX
jmp _skipInputIntArrayEqualToSpecialValue ; EAX != EBX
_continueCompareArrayLoop:
add ESI, 4
add EDI, 4
LOOP _compareArrayLoop
; update input_int
mov EDI, [EBP+40]
mov EAX, LO
mov [EDI], EAX
jmp _validNumber
_skipInputIntArrayEqualToSpecialValue:
; update input_int
; update index_tracker to 0
mov EAX, 0
mov EDI, [EBP+36] ;OFFSET index_tracker
mov [EDI], EAX
; for the length of pow tracker, update values in multiplicand_int_array to 1
mov ECX, [EBP+24] ; num_of_digits
mov EDI, [EBP+44] ;OFFSET multiplicand_int_array
_updateValInArrayToOneLoop:
mov EAX, 1
mov [EDI], EAX
add EDI, 4
loop _updateValInArrayToOneLoop
; update mulitiplicand_int_array and input_int_array
; each the value in each mulitiplicand_int_array will be multiplied against the value in the
; same index of input_int_array. For example if mulitiplicand_int_array = [100, 10, 1],
; and input_int_array = [4, 2, 3], input_int_array then be equal to [400, 20, 3]
; update multiplicand_int_array
; update index_tracker to 0
mov EAX, 0
mov EDI, [EBP+36] ;OFFSET index_tracker
mov [EDI], EAX
; update ECX
mov ECX, [EBP+24] ; num_of_digits
cmp ECX, 1
jle _updateInputIntArray ; (ECX = num_of_digits) <= 1
; at this point, (ECX = num_of_digits) > 1
dec ECX ; start loop at num_of_digits - 1
mov ESI, [EBP+44] ; OFFSET multiplicand_int_array
mov EDI, [EBP+44] ; OFFSET multiplicand_int_array
_multiplicandLoop:
push ECX
mov EBX, 1
_updateEBXLoop:
mov EAX, 10
mul EBX
mov EBX, EAX
loop _updateEBXLoop
pop ECX
; update value in multiplicand_int_array
mov [EDI], EBX
; go to next index in multiplicand_int_array
add ESI, 4
add EDI, 4
loop _multiplicandLoop
_updateInputIntArray:
; multiply the values in input_int_array * respective value in multiplicand_int_array
mov ECX, [EBP+24] ; num_of_digits
mov EDI, [EBP+48] ; OFFSET input_int_array
mov ESI, [EBP+44] ; OFFSET multiplicand_int_array ; DEBUG
_multiplyValuesInInputIntArrayLoop:
mov EAX, [ESI] ; EAX = current value in multiplicand_int_array
mov EBX, [EDI] ; EBX = current value in reverse_input_int_array
mul EBX ; EAX = current value in multiplicand_int_array * current value in reverse_input_int_array
mov [EDI], EAX ; value in EDI = current value in multiplicand_int_array * current value in reverse_input_int_array
; move forward in both arrays
add ESI, 4
add EDI, 4
loop _multiplyValuesInInputIntArrayLoop
; add values to input_int and check for overflow
mov ECX, [EBP+24] ; num_of_digits
mov ESI, [EBP+48] ;OFFSET input_int_array
mov EDI, [EBP+40] ; OFFSET input_int
_addToInputInt:
mov EBX, [ESI] ;OFFSET input_int_array
mov EAX, [EDI] ; OFFSET input_int
add EAX, EBX
jo _invalidNumber ; we've overflowed
mov [EDI], EAX
mov EAX, [EBP+24] ; num_of_digits
cmp ECX, EAX ; if ECX = EAX, then we've only added one digit. at this point, we can multiply by multiplier
add ESI, 4
loop _addToInputInt
jmp _validAbsoluteNumber
_validAbsoluteNumber:
; multiply by multiplier and cjeck for overflow
mov ESI, [EBP+40] ; OFFSET input_int
mov EAX, [ESI] ; input_int value
mov EBX, [EBP+28] ; multiplier
imul EBX ; EAX = multiplier * input_int value
jo _invalidNumber ; we've overflowed
mov EDI, [EBP+40] ; OFFSET input_int
mov [EDI], EAX
jmp _validNumber
_validNumber:
; update input_state
mov EDI, [EBP+20] ; OFFSET input_state
mov EAX, VALID
mov [EDI], EAX
jmp _endConvertValidatedInputStringToSDWORD
_invalidNumber:
; update input_state
mov EDI, [EBP+20] ; OFFSET input_state
mov EAX, INVALID
mov [EDI], EAX
jmp _endConvertValidatedInputStringToSDWORD
_endConvertValidatedInputStringToSDWORD:
pop EDI