-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathEgerton_Project6A.asm
More file actions
352 lines (302 loc) · 11.5 KB
/
Egerton_Project6A.asm
File metadata and controls
352 lines (302 loc) · 11.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
;Lauren Egerton
;egertonl@oregonstate.edu
;CS271-400
;Assignment #6A
;Due 03/13/2016
TITLE Designing low-level I/O procedures (Egerton_Project6A.asm)
; Author: Lauren Egerton
; Course / Project ID CS 271/Assignment #6A Date: 03/13/16
; Description: This program takes input from a user ten times and stores it in the form of a digit string, then
; converts each digit string to a numeric value and stores that value in an array of double words. Input is
; validated and must be betwen 0 and (2^32 - 1). The numeric values are added together and stored as
; a sum. The average of this sum is calculated and both are displayed to the user. The program converts
; the numeric values, the sum, and the average back to digit strings before displaying them to the user.
; The program also uses macros to get user input and display output.
INCLUDE Irvine32.inc
; macros defined here
getString MACRO output, buffer ;getString macro (use Irvine's readString)
push edx ;save edx register
push ecx ;save ecx register
displayString output ;call macro to WriteString
mov edx, buffer
mov ecx, 30 ;maximum number of characters user can enter
call ReadString ;store input in a memory location (variable)
pop ecx ;restore ecx register
pop edx ;restore edx register
ENDM
displayString MACRO buffer ;displayString macro (use Irvine's WriteString)
push edx ;save edx register
mov edx, buffer
call WriteString
pop edx ;restore edx
ENDM
.data
;output variables
title1 BYTE "PROGRAMMING ASSIGNMENT 6: Designing low-level I/O procedures", 0 ;display title
title2 BYTE "Written by: Lauren Egerton ", 0 ;display author
intro1 BYTE "Please provide 10 unsigned decimal integers.", 0 ;display game explanation
intro2 BYTE "Each number needs to be small enough to fit inside a 32 bit register.", 0 ;and game rules
intro3 BYTE "After you have finished inputting the raw numbers I will display a list", 0 ;explain outcome of game
intro4 BYTE "of the integers, their sum, and their average value.", 0 ;explain outcome of game
dothis1 BYTE "Please enter an unsigned number: ", 0 ;prompt user to enter a number
error1 BYTE "ERROR: You did not enter an unsigned number or your number was too big.", 0 ;display error message
error2 BYTE "Try again. ", 0 ;prompt user to try again
display1 BYTE "You entered the following numbers: ", 0 ;display the numbers entered by the user
display2 BYTE "The sum of these numbers is: ", 0 ;display the sum of numbers entered by the user
display3 BYTE "The average is: ", 0 ;display the average of the numbers
goodbye BYTE "Goodbye, and thanks for playing!", 0 ;display parting message
space BYTE ", ", 0 ;display spaces between output
;input variables
input BYTE 30 DUP(0) ;store string input by user - to be converted
output BYTE 11 DUP(0) ;store converted number as a string for output
number DWORD ? ;store converted string as number
sum DWORD ? ;store the sum of numbers entered by the user
average DWORD ? ;store the average of the numbers entered by the user
arrayList DWORD 10 DUP(?) ;array to store list of converted integers
check DWORD 4294967295 ;bigger than this will not fit in a 32-bit register
count DWORD 0 ;keep track of loop
.code
main PROC
;introduction
displayString OFFSET title1 ;pass by address to macro
call Crlf
displayString OFFSET title2 ;pass by address to macro
call Crlf ;new paragraph
call Crlf
displayString OFFSET intro1 ;pass by address to macro
call Crlf
displayString OFFSET intro2 ;pass by address to macro
call Crlf
displayString OFFSET intro3 ;pass by address to macro
call Crlf
displayString OFFSET intro4 ;pass by address to macro
call Crlf
call Crlf
;get input from user and store in array
push OFFSET arrayList ;ebp+28
push OFFSET number ;ebp+24
push OFFSET input ;ebp+20
push OFFSET dothis1 ;ebp+16
push OFFSET error1 ;ebp+12
push OFFSET error2 ;ebp+8
call readVal ;pushed 24 bits onto stack
;add the numbers in the array
push OFFSET arrayList ;ebp+12
push OFFSET sum ;ebp+8
call sumArray ;pushed 8 bits onto stack
;calculate average
push OFFSET sum ;ebp+12
push OFFSET average ;ebp+8
call Calculate ;pushed 8 bits on stack
mov esi, OFFSET arrayList ;put address of array in esi
mov count, 0 ;set counter to 0
call Crlf
displayString OFFSET display1
call Crlf
Show: ;convert numbers in array to strings and display each one
mov eax, [esi] ;store first int in number variable
add esi, 4 ;next number in array
mov number, eax ;put first value in array into number
push OFFSET number ;ebp+12
push OFFSET output ;ebp+8
call writeVal ;pushed 8 bits on to stack
cmp count, 9 ;repeat Show 10 times
je Quit ;leave loop
displayString OFFSET space ;add comma and space between each string
inc count ;increment count each time
jmp Show ;repeat loop
Quit:
call Crlf
;display sum
displayString OFFSET display2
push OFFSET sum ;ebp+12
push OFFSET output ;ebp+8
call writeVal ;pushed 8 bits on to stack
call Crlf
;display average
displayString OFFSET display3 ;show average
push OFFSET average ;ebp+12
push OFFSET output ;ebp+8
call writeVal ;pushed 8 bits on to stack
call Crlf ;new paragraph
call Crlf
;display farewell
displayString OFFSET goodbye ;farewell
call Crlf
exit ; exit to operating system
main ENDP
; ***************************************************************
; Procedure to convert a digit string to numeric and validate
; user input.
; receives: address of array, address of two strings to display,
; address of input variable
; returns: user input as a numeric value in the array
; preconditions: none
; registers changed: none
; ***************************************************************
readVal PROC
push ebp
mov ebp,esp
pushad ;save registers
mov ecx, 10 ;outer loop count
mov edi, [ebp+28] ;store address of array in edi
L1:
push ecx ;save registers
Top:
getString [ebp+16], [ebp+20] ;invoke displayString macro - dothis1 and input parameters
mov edx, 0 ;set edx to 0
mov ebx, 0 ;reset ebx to 0 for next total
mov ecx, eax ;string length is the inner loop counter
mov esi, [ebp+20] ;put input address (user string) in the source register - do i need to movzx in esi?
cld ;clear direction flag, move forward
Validate:
xor eax, eax ;clear eax before lodsb
lodsb ;put first byte into esi
cmp al, 48 ;validate user input
jb error ;can only have char 0,1,2,3,4,5,6,7,8,9
cmp al, 57 ;validate string, user input
ja error
sub eax, 48 ;convert ASCII to number
push eax ;save current value of eax
push ecx ;save ecx
mov eax, ebx ;put current total in eax
mov ecx, 10 ;put 10 into ecx
mul ecx ;multiply eax * 10
cmp edx, 0 ;is there carry in to edx from eax?
mov ebx, eax ;put eax * 10 back into total ebx
pop ecx ;restore ecx
pop eax ;restore eax
jnz error ;if edx is not 0, display error
add ebx, eax ;add current value in eax to ebx for updated total
jc error
loop Validate ;loop 10 times to get each char converted to numeric
mov [edi], ebx ;store value in first element of array
add edi, 4 ;mov edi to next element
pop ecx ;restore registers
loop L1
jmp quit
error:
displayString [ebp+12] ;error1 parameter
call Crlf
displayString [ebp+8] ;error2 parameter
jmp Top
quit:
popad ;restore registers
pop ebp
ret 24 ;pushed 6 OFFSETS, return 6 * 4 bits
readVal ENDP
; ***************************************************************
; Procedure to convert a numeric value to a digit string
; receives: address of input and output variable
; returns: none
; preconditions: input is a numeric value and output is a null-
; terminated string
; registers changed: none
; cite : Prof. Redfield's help with clearing the array in between
; uses.
; ***************************************************************
writeVal PROC
push ebp
mov ebp,esp
pushad ;save registers
mov edi, [ebp+8] ;edi points to output, a string
mov esi, [ebp+12] ;esi points to a number (DWORD) to convert
xor eax, eax ;clear eax
mov ecx, 10 ;divisor always 10
xor ebx, ebx ;clear ebx for counter
mov eax, [esi] ;put number into eax
cld ;move forward
Convert: ;convert each numeric digit to string
cdq ;clear edx for division
div ecx ;divide eax by ecx
push dx ;will be a number between 0 and 9 in the remainder
inc bx ;count number of pushes
cmp eax, 0 ;is eax = 0?
jne Convert ;if eax is not 0, keep looping
mov cx, bx ;loop counter is equal to bx number of pushes
GetIt:
pop ax ;pop all of the dx's into ax's
add al, 48 ;convert numeric digit to ASCII
stosb ;store the first char in destination register
loop GetIt
mov edx, [ebp+8] ;display the string (converted number)
call WriteString
std
mov al, 0
mov cx,bx
ClearIt:
stosb
loop ClearIt
cld
popad ;restore registers
pop ebp
ret 8
writeVal ENDP
; ***************************************************************
; Procedure to display an array.
; receives: address of array
; returns: prints the array
; preconditions: none
; registers changed: eax, ecx, edi
; cite : Lecture 20 and demo5.asm
; ***************************************************************
showArray PROC
push ebp
mov ebp,esp
mov ecx,10 ;count in ecx
mov edi,[ebp+8] ;address of array in edi
more:
mov eax,[edi] ;start with first element
call WriteDec
add edi,4
loop more
pop ebp
ret 8
showArray ENDP
; ***************************************************************
; Procedure to sum the numbers in an array
; receives: address of array and variable sum on system stack
; returns: user input in global count
; preconditions: numbers are stored in array
; registers changed: none
; cite : textbook p. 150-151
; ***************************************************************
sumArray PROC
push ebp
mov ebp, esp
pushad ;save registers
mov eax, 0 ;accumulator
mov ecx, 10 ;loop counter
mov edi, [ebp+12] ;put address of array in edi
L1: add eax, [edi] ;add first value to eax
add edi, 4 ;move to next value in array
loop L1
mov edx, [ebp+8] ;address of sum in edx
mov [edx], eax ;store sum in global variable
popad ;restore registers
pop ebp
ret 8
sumArray ENDP
; ***************************************************************
; Procedure to calculate the average of a list of numbers
; receives: address of sum and average variable on system stack
; returns: calculated average at address of variable
; preconditions: sum is calculated
; registers changed: none
; ***************************************************************
calculate PROC ;procedure to caculate average
push ebp
mov ebp, esp
pushad ;save registers
mov edi, [ebp+12] ;address of sum in edi
mov esi, [ebp+8] ;address of average in esi
mov eax, [edi] ;dereference edi's address = value, dividend
mov edx, 0 ;set edx to 0
mov ebx, 10 ;divisor is 10
div ebx ;divide eax by ebx
mov [esi], eax ;store quotient in value of average
popad ;restore registers
pop ebp
ret 8
calculate ENDP
END main