-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCAL.asm
506 lines (424 loc) · 14.3 KB
/
CAL.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
section .data
int_format db "%d", 0 ; Format for scanf to read integers
float_format db "%lf", 0 ; Format for scanf to read double (use %lf for scanf)
menu_msg db "Choose an operation:", 10, 0
option1 db "1. Addition", 10, 0
option2 db "2. Subtraction", 10, 0
option3 db "3. Multiplication", 10, 0
option4 db "4. Division", 10, 0
option5 db "5. Exit", 10, 0
option6 db "6. Modulus", 10, 0
option7 db "7. Exponentiation(2^2)", 10, 0
option8 db "8. Sine", 10, 0
option9 db "9. Cosine", 10, 0
option10 db "10. Tangent", 10, 0
option11 db "11. Square Root", 10, 0
option12 db "12. Store Result", 10, 0
option13 db "13. Recall Stored Result", 10, 0
prompt db "Enter your choice: ", 0
prompt1 db "Enter first number: ", 0
prompt2 db "Enter second number: ", 0
result_msg db "Result: %d", 10, 0
float_result_msg db "Result: %f", 10, 0 ; Use %f for printf to print floats
error_msg db "Error: Division by zero!", 10, 0
type_prompt db "Enter 1 for Integer, 2 for Float: ", 0
section .bss
choice resd 1 ; Store user's menu choice (integer)
num1 resd 1 ; Reserve space for first number
num2 resd 1 ; Reserve space for second number
result resd 1 ; Reserve space for result
num_type resd 1 ; Store the number type choice
float_num1 resq 1 ; Reserve space for first floating-point number (double)
float_num2 resq 1 ; Reserve space for second floating-point number (double)
float_result resq 1 ; Reserve space for floating-point result (double)
memory_storage resq 1 ; Reserve space for storing a floating-point result
memory_used resb 1 ; Flag to indicate if memory storage is in use
section .text
extern printf, scanf, ExitProcess, fmod, pow, sin, cos, tan, sqrt
global main
main:
sub rsp, 40 ; Reserve space for shadow and alignment
menu_loop:
; Print the menu
lea rcx, [rel menu_msg]
call printf
lea rcx, [rel option1]
call printf
lea rcx, [rel option2]
call printf
lea rcx, [rel option3]
call printf
lea rcx, [rel option4]
call printf
lea rcx, [rel option5]
call printf
lea rcx, [rel option6]
call printf
lea rcx, [rel option7]
call printf
lea rcx, [rel option8]
call printf
lea rcx, [rel option9]
call printf
lea rcx, [rel option10]
call printf
lea rcx, [rel option11]
call printf
lea rcx, [rel option12]
call printf
lea rcx, [rel option13]
call printf
; Get the user's choice
lea rcx, [rel prompt]
call printf
lea rdx, [rel choice]
lea rcx, [rel int_format]
call scanf
; Load the user's choice into eax for comparison
mov eax, [rel choice]
; Check user's choice and branch accordingly
cmp eax, 1
je choose_num_type_add
cmp eax, 2
je choose_num_type_sub
cmp eax, 3
je choose_num_type_mul
cmp eax, 4
je choose_num_type_div
cmp eax, 6
je choose_num_type_mod
cmp eax, 7
je choose_num_type_pow
cmp eax, 8
je float_sin_operation
cmp eax, 9
je float_cos_operation
cmp eax, 10
je float_tan_operation
cmp eax, 11
je float_sqrt_operation
cmp eax, 12
je store_result_operation
cmp eax, 13
je recall_result_operation
cmp eax, 5
je exit_program
; Invalid choice, go back to menu
jmp menu_loop
choose_num_type_add:
; Ask for number type (1 for Integer, 2 for Float)
lea rcx, [rel type_prompt]
call printf
lea rcx, [rel int_format]
lea rdx, [rel num_type]
call scanf
mov eax, [rel num_type]
cmp eax, 1
je int_add_operation
cmp eax, 2
je float_add_operation
; Invalid choice, go back to menu
jmp menu_loop
choose_num_type_sub:
; Ask for number type (1 for Integer, 2 for Float)
lea rcx, [rel type_prompt]
call printf
lea rcx, [rel int_format]
lea rdx, [rel num_type]
call scanf
mov eax, [rel num_type]
cmp eax, 1
je int_sub_operation
cmp eax, 2
je float_sub_operation
; Invalid choice, go back to menu
jmp menu_loop
choose_num_type_mul:
; Ask for number type (1 for Integer, 2 for Float)
lea rcx, [rel type_prompt]
call printf
lea rcx, [rel int_format]
lea rdx, [rel num_type]
call scanf
mov eax, [rel num_type]
cmp eax, 1
je int_mul_operation
cmp eax, 2
je float_mul_operation
; Invalid choice, go back to menu
jmp menu_loop
choose_num_type_div:
; Ask for number type (1 for Integer, 2 for Float)
lea rcx, [rel type_prompt]
call printf
lea rcx, [rel int_format]
lea rdx, [rel num_type]
call scanf
mov eax, [rel num_type]
cmp eax, 1
je int_div_operation
cmp eax, 2
je float_div_operation
; Invalid choice, go back to menu
jmp menu_loop
choose_num_type_mod:
; Ask for number type (1 for Integer, 2 for Float)
lea rcx, [rel type_prompt]
call printf
lea rcx, [rel int_format]
lea rdx, [rel num_type]
call scanf
mov eax, [rel num_type]
cmp eax, 1
je int_mod_operation
cmp eax, 2
je float_mod_operation
; Invalid choice, go back to menu
jmp menu_loop
choose_num_type_pow:
; Ask for number type (1 for Integer, 2 for Float)
lea rcx, [rel type_prompt]
call printf
lea rcx, [rel int_format]
lea rdx, [rel num_type]
call scanf
mov eax, [rel num_type]
cmp eax, 1
je int_pow_operation
cmp eax, 2
je float_pow_operation
; Invalid choice, go back to menu
jmp menu_loop
int_add_operation:
call int_get_input1
call int_get_input2
mov eax, [rel num1] ; Load num1 into eax
add eax, [rel num2] ; Add num2 to eax
mov [rel result], eax ; Store the result
jmp int_print_result
int_sub_operation:
call int_get_input1
call int_get_input2
mov eax, [rel num1] ; Load num1 into eax
sub eax, [rel num2] ; Subtract num2 from eax
mov [rel result], eax ; Store the result
jmp int_print_result
int_mul_operation:
call int_get_input1
call int_get_input2
mov eax, [rel num1] ; Load num1 into eax
imul eax, [rel num2] ; Multiply eax by num2
mov [rel result], eax ; Store the result
jmp int_print_result
int_div_operation:
call int_get_input1
call int_get_input2
mov eax, [rel num2] ; Load num2 (divisor) into eax
test eax, eax ; Check if the divisor is 0
jz int_handle_div_zero ; Jump to error handling if divisor is 0
mov eax, [rel num1] ; Load num1 (dividend) into eax
xor edx, edx ; Clear edx before division
div dword [rel num2] ; Divide edx:eax by num2 (divisor)
mov [rel result], eax ; Store the quotient in result
jmp int_print_result
int_mod_operation:
call int_get_input1
call int_get_input2
mov eax, [rel num2] ; Load num2 (divisor) into eax
test eax, eax ; Check if the divisor is 0
jz int_handle_div_zero ; Jump to error handling if divisor is 0
mov eax, [rel num1] ; Load num1 into eax
xor edx, edx ; Clear edx for division
div dword [rel num2] ; Perform division
mov eax, edx ; Move remainder from edx to eax
mov [rel result], eax ; Store the remainder in result
jmp int_print_result
int_handle_div_zero:
lea rcx, [rel error_msg]
call printf
jmp menu_loop
int_pow_operation:
call int_get_input1
call int_get_input2
mov eax, [rel num1] ; Load the base into eax
mov ecx, [rel num2] ; Load the exponent into ecx
cmp ecx, 0 ; If the exponent is 0
je int_pow_done_zero ; Result should be 1 for any base^0
mov edx, eax ; Store the base value in edx
dec ecx ; Decrement exponent by 1, since we already have base^1
int_pow_loop:
imul eax, edx ; Multiply eax by the base (edx)
loop int_pow_loop ; Loop until ecx reaches 0
jmp int_pow_done ; Jump to done
int_pow_done_zero:
mov eax, 1 ; If the exponent was 0, the result is 1
jmp int_pow_done
int_pow_done:
mov [rel result], eax ; Store the result
jmp int_print_result ; Print the result
int_print_result:
; Print the result
lea rcx, [rel result_msg]
mov rdx, [rel result]
call printf
jmp menu_loop
float_add_operation:
call get_float_input1
call get_float_input2
; Perform floating-point addition
movsd xmm0, qword [rel float_num1] ; Load first float into xmm0
addsd xmm0, qword [rel float_num2] ; Add second float to xmm0
movsd qword [rel float_result], xmm0 ; Store result back to memory
jmp float_print_result
float_sub_operation:
call get_float_input1
call get_float_input2
; Perform floating-point subtraction
movsd xmm0, qword [rel float_num1] ; Load first float into xmm0
subsd xmm0, qword [rel float_num2] ; Subtract second float from xmm0
movsd qword [rel float_result], xmm0 ; Store result back to memory
jmp float_print_result
float_mul_operation:
call get_float_input1
call get_float_input2
; Perform floating-point multiplication
movsd xmm0, qword [rel float_num1] ; Load first float into xmm0
mulsd xmm0, qword [rel float_num2] ; Multiply xmm0 by second float
movsd qword [rel float_result], xmm0 ; Store result back to memory
jmp float_print_result
float_div_operation:
call get_float_input1
call get_float_input2
; Perform floating-point division
movsd xmm0, qword [rel float_num1] ; Load first float into xmm0
movsd xmm1, qword [rel float_num2] ; Load second float into xmm1
comisd xmm1, xmm0 ; Compare the second float to zero
jp float_handle_div_zero ; Jump to error handling if divisor is 0
divsd xmm0, xmm1 ; Divide xmm0 by xmm1
movsd qword [rel float_result], xmm0 ; Store result back to memory
jmp float_print_result
float_mod_operation:
call get_float_input1
call get_float_input2
; Perform floating-point modulus
movsd xmm0, qword [rel float_num1] ; Load first float into xmm0
movsd xmm1, qword [rel float_num2] ; Load second float into xmm1
call fmod ; Call fmod(xmm0, xmm1)
movsd qword [rel float_result], xmm0 ; Store the result in memory
jmp float_print_result
float_handle_div_zero:
lea rcx, [rel error_msg]
call printf
jmp menu_loop
float_pow_operation:
call get_float_input1
call get_float_input2
; Perform floating-point exponentiation
movsd xmm0, qword [rel float_num1] ; Load the base into xmm0
movsd xmm1, qword [rel float_num2] ; Load the exponent into xmm1
call pow ; Call pow(xmm0, xmm1)
movsd qword [rel float_result], xmm0 ; Store the result in memory
jmp float_print_result
extern sin, cos, tan
float_sin_operation:
call get_float_input1
movsd xmm0, qword [rel float_num1]
call sin
movsd qword [rel float_result], xmm0
jmp float_print_result
float_cos_operation:
call get_float_input1
movsd xmm0, qword [rel float_num1]
call cos
movsd qword [rel float_result], xmm0
jmp float_print_result
float_tan_operation:
call get_float_input1
movsd xmm0, qword [rel float_num1]
call tan
movsd qword [rel float_result], xmm0
jmp float_print_result
float_sqrt_operation:
call get_float_input1
movsd xmm0, qword [rel float_num1]
call sqrt
movsd qword [rel float_result], xmm0
jmp float_print_result
float_print_result:
; Print the result
lea rcx, [rel float_result_msg]
mov rdx, qword [rel float_result]
call printf
jmp menu_loop
int_get_input1:
sub rsp, 40 ; Align stack before scanf call
; Prompt and input first number
lea rcx, [rel prompt1] ; Load address of prompt1 into rcx
call printf
lea rdx, [rel num1] ; Load address of num1 into rdx
lea rcx, [rel int_format] ; Load address of format into rcx
call scanf ; Call scanf with format in rcx, address in rdx
add rsp, 40 ; Restore stack alignment
ret
int_get_input2:
sub rsp, 40 ; Align stack before scanf call
; Prompt and input second number
lea rcx, [rel prompt2] ; Load address of prompt2 into rcx
call printf
lea rdx, [rel num2] ; Load address of num2 into rdx
lea rcx, [rel int_format] ; Load address of format into rcx
call scanf ; Call scanf with format in rcx, address in rdx
add rsp, 40 ; Restore stack alignment
ret
get_float_input1:
sub rsp, 40 ; Align stack before scanf call
; Prompt and input first floating-point number
lea rcx, [rel prompt1]
call printf
lea rdx, [rel float_num1]
lea rcx, [rel float_format]
call scanf
add rsp, 40 ; Restore stack alignment
ret
get_float_input2:
sub rsp, 40 ; Align stack before scanf call
; Prompt and input second floating-point number
lea rcx, [rel prompt2]
call printf
lea rdx, [rel float_num2]
lea rcx, [rel float_format]
call scanf
add rsp, 40 ; Restore stack alignment
ret
; memory_operations
store_result_operation:
mov al, [rel num_type] ; Check the type of the last calculation (1 for int, 2 for float)
cmp al, 1
je store_int_result
; Store the floating-point result
movsd xmm0, qword [rel float_result]
movsd qword [rel memory_storage], xmm0
mov byte [rel memory_used], 1 ; Set the memory_used flag
jmp menu_loop
store_int_result:
cvtsi2sd xmm0, dword [rel result]
movsd qword [rel memory_storage], xmm0
mov byte [rel memory_used], 1 ; Set the memory_used flag
jmp menu_loop
recall_result_operation:
cmp byte [rel memory_used], 0
je no_memory_error
movsd xmm0, qword [rel memory_storage]
movsd qword [rel float_num1], xmm0
mov byte [rel memory_used], 0 ; Clear the memory_used flag
jmp menu_loop
no_memory_error:
; Display error message for no stored memory
lea rcx, [rel error_msg]
call printf
jmp menu_loop
exit_program:
; Clean up and exit
add rsp, 40
xor ecx, ecx
call ExitProcess