-
Notifications
You must be signed in to change notification settings - Fork 0
/
RobbinsLab6.asm
286 lines (235 loc) · 7.37 KB
/
RobbinsLab6.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
;Jack Robbins
;3/2/2022
;Lab 6 Functions
;This program modifies lab 5 to do the same arithmetic but will do so using a function
;Need to include these two statements for the macros and functions
%include "CPsub64.inc"
%include "Macros_CPsub64.inc"
;declare the starting point
global main
;Declare and initialize all messages we want to use
;No need to calculate lengths as the program will use WriteString
section .data
;print a simple welcome message
WelcomeMessage: db "Let's do some arithmetic!",0,0ah
;print a message to prompt the user for the first operand
getFirstOperand: db "Enter the first operand: ",0
;print a message to prompt the user for the second operand
getSecondOperand: db "Enter the second operand: ",0
;print a message to prompt the user for an operator
getOperator: db "Enter the desired operator(+ or - or * or /): ",0
;print a repeat message
repeatMessage: db "Would you like to do another operation? (Y/N): ",0
;general purpose messages for printing equations and results
;The message for displaying the answer
answerMessage: db "The answer is: ",0
;A message declaring a remainder
remainderMessage: db " Remainder: ",0
;Declare all variables that will be used later
section .bss
;The user-inputted first operand
firstOperand: resb 255
;The user-inputted second operand
secondOperand: resb 255
;The user-inputted operator
operator: resb 255
;The user-input for repetition
userRepeat: resb 255
;Perform all instructions
section .text
main: ;Start here
;Put what we want to print in rdx, then call WriteString
mov rdx, WelcomeMessage
call WriteString
;Print a blank line
call Crlf
;go to the get inputs section
jmp get_inputs
;The label that handles all of the user input
get_inputs:
;Prompt the user for the operator
mov rdx, getOperator
call WriteString
;Get user input from console
mov rdx, operator
mov rcx, 255
call ReadString
;Prompt the user for the first operand
mov rdx, getFirstOperand
call WriteString
;Get user input from console
mov rdx, firstOperand
mov rcx, 255
call ReadString
;Prompt the user for the second operand
mov rdx, getSecondOperand
call WriteString
;Get user input from console
mov rdx, secondOperand
mov rcx, 255
call ReadString
;After all user input has been entered, jump to the conversion label
jmp convert_inputs
;The label where all of the inputs are converted for use
convert_inputs:
;Convert the first number to an integer
mov rdx, firstOperand
mov rcx, 255
call ParseInteger64
;Save the value so it won't get overwritten
mov r8, rax
;convert the second number to an integer
mov rdx, secondOperand
mov rcx, 255
call ParseInteger64
;Save the value so it won't get overwritten
mov r10, rax
;After all inputs have been converted, jump to make the function call
jmp call_function
;Begin setting up the function
;The call function section that handles the function call and cleanup afterwards
call_function:
;First prepare the stack
;Put the value for the operator in r14
mov r14, [operator]
;Push the value of the second operand first
push r10
;push the value of the first operand next
push r8
;finally push the value of the operator
push r14
;Stack has been prepared, is in order of operator, firstOperand, secondOperand, now jump to the function call
;Call the function
call perform_arithmetic_display_results
;Clear out the stack afterwards
;Put the operator in r14
pop r14
;put the first operand in r8
pop r8
;put the second operand in r10
pop r10
;Add 32 to rsp to clear out the stack
add rsp, 32
;Jump to the repeat decision section
jmp repeat_decision
;The label that handles the repeating of the program
repeat_decision:
;Ask the user if they would like to repeat
mov rdx, repeatMessage
call WriteString
;Get user input after they have answered
mov rdx, userRepeat
mov rcx, 255
call ReadString
;Move the value of userRepeat into dl for use in comparison
mov dl, [userRepeat]
;Compare dl with Y and y, jump to the get_inputs label if they're equal
cmp dl, "Y"
je get_inputs
cmp dl, "y"
je get_inputs
;Exit the program
Exit
;Declaring and writing the perform_arithmetic_display_results function after the program exit
perform_arithmetic_display_results:
;Prologue(Steps to set up the function)
;Save the location of the calling instructions
push rbp
;move the pointer to the top of the stack
mov rbp, rsp
;End prologue, function is now set up
;Put the value for the operator in r15
mov r15, [rbp+16]
;Put the first operand in r8
mov r8, [rbp+24]
;Put the second operand in r10
mov r10, [rbp+32]
;If the value equals +, jump to the addition label
cmp r15, "+"
je perform_addition
;If the value equals -, jump to the subtraction label
cmp r15, "-"
je perform_subtraction
;If the value equals *, jump to the multiplication label
cmp r15, 2ah
je perform_multiplication
;If the value equals /, jump to the division label
cmp r15, 2fh
je perform_division
;The label where all the division is handled
perform_addition:
;add r8 and r10, result will be stored in r8
;First save the value in r8 as it will be overwritten by the addition
mov r14, r8
add r8, r10
;Jump to the section that displays results
jmp display_results
;The label where all the subtraction is handled
perform_subtraction:
;subtract r8 and r10, the result will be stored in r8
;First save the value in r8 as it will be overwritten
mov r14, r8
sub r8, r10
;Jump to the section that displays results
jmp display_results
;The label where all the multiplication is handled
perform_multiplication:
;integer multiply r8 and r10
;need to put r8 in rax first
mov rax, r8
;Integer multiply by r10, result is in rax
imul r10
;Result is in rax, save it in r8
mov r8, rax
;Jump to the section that displays results
jmp display_results
;The label where all the division is handled
perform_division:
;integer divide r8 and r10
;zero out rdx
mov rdx, 0
;Put the dividend in rax
mov rax, r8
;divide rax by the divisor in r10
idiv r10
;save the result in r8
mov r8, rax
;save the remainder in r14
mov r14, rdx
jmp display_results
;The label that displays all results
display_results:
;get the operator again
mov r15, [rbp+16]
;Display the result of addition
mov rdx, answerMessage
call WriteString
mov rax, r8
call WriteInt
;Determine if result is from division
cmp r15, 2fh
;Jump to display remainder if yes
je display_remainder
;Jump to finalize_print if no
jne finalize_print
;The label that displays the remainder
display_remainder:
;first write the remainder message
mov rdx, remainderMessage
call WriteString
;Print the remainder
mov rax, r14
call WriteInt
;Jump to finalize_print
jmp finalize_print
;Put the finishing touch on the printed statement and jump to end_fn
finalize_print:
call Crlf
jmp end_fn
;The section of the function that returns to the main program
end_fn:
;Now return to program
;Restore address of the caller
pop rbp
;Return the function
ret