-
Notifications
You must be signed in to change notification settings - Fork 99
/
Copy pathExpenseReport.S
257 lines (225 loc) · 4.95 KB
/
ExpenseReport.S
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
.equ STDOUT, 1
.equ EXIT_SUCCESS, 0
.equ write, 64
.equ exit, 93
.equ DINNER, 1
.equ BREAKFAST, 2
.equ CAR_RENTAL, 3
.text
.global _start
_start:
ldr x0, =expenses
bl printReport
mov x0, #EXIT_SUCCESS
mov x8, #exit
svc #0
printReport:
str x30, [sp,#16]!
mov x9, x0 // x9 = current expese pointer
mov x12, xzr // x12 = meal expenses
mov x13, xzr // x13 = total expenses
mov x0, #STDOUT
ldr x1, =header
mov x2, #headerLen
mov x8, #write
svc #0
.loop:
ldr x10, [x9], #8 // x10 = expense type
cmp xzr, x10
beq .loopDone
ldr x11, [x9], #8 // x11 = expense amount
cmp x10, #DINNER
beq .mealExpense
cmp x10, #BREAKFAST
beq .mealExpense
b .notMeal
.mealExpense:
add x12, x12, x11
.notMeal:
.printExpenseName:
mov x0, #STDOUT
ldr x1, =expenseNames
ldr x1, [x1, x10, LSL#3]
ldr x2, =expenseNameLengths
ldr x2, [x2, x10, LSL#3]
mov x8, #write
svc #0
mov x0, #STDOUT
ldr x1, =tab
mov x2, #tabLen
mov x8, #write
svc #0
ldr x0, =buffer
mov x1, x11
bl itoa10
mov x1, x0
.lenLoop:
ldrb w2, [x0], 1
cbnz w2, .lenLoop
sub x2, x0, x1
sub x2, x2, #1
mov x0, #STDOUT
mov x8, #write
svc #0
mov x0, #STDOUT
ldr x1, =tab
mov x2, #tabLen
mov x8, #write
svc #0
cmp x10, DINNER
cset x1, eq
mov x0, 5000
cmp x11, x0
cset x2, gt
ands x3, x2, x1
bne .mealOverExpense
cmp x10, BREAKFAST
cset x1, eq
mov x0, 1000
cmp x11, x0
cset x2, gt
ands x3, x2, x1
bne .mealOverExpense
.mealNotOverExpense:
ldr x1, =mealNotOverExpensesMarker
b .printMealOverExpensesMarker
.mealOverExpense:
ldr x1, =mealOverExpensesMarker
b .printMealOverExpensesMarker
.printMealOverExpensesMarker:
mov x2, #1
mov x0, #STDOUT
mov x8, #write
svc #0
mov x0, #STDOUT
ldr x1, =newline
mov x2, #newlineLen
mov x8, #write
svc #0
add x13, x13, x11
b .loop
.loopDone:
mov x0, #STDOUT
ldr x1, =meals
mov x2, #mealsLen
mov x8, #write
svc #0
ldr x0, =buffer
mov x1, x12
bl itoa10
mov x1, x0
.lenLoop2:
ldrb w2, [x0], 1
cbnz w2, .lenLoop2
sub x2, x0, x1
sub x2, x2, #1
mov x0, #STDOUT
mov x8, #write
svc #0
mov x0, #STDOUT
ldr x1, =newline
mov x2, #newlineLen
mov x8, #write
svc #0
mov x0, #STDOUT
ldr x1, =total
mov x2, #totalLen
mov x8, #write
svc #0
ldr x0, =buffer
mov x1, x13
bl itoa10
mov x1, x0
.lenLoop3:
ldrb w2, [x0], 1
cbnz w2, .lenLoop3
sub x2, x0, x1
sub x2, x2, #1
mov x0, #STDOUT
mov x8, #write
svc #0
mov x0, #STDOUT
ldr x1, =newline
mov x2, #newlineLen
mov x8, #write
svc #0
ldr x30, [sp], #16
ret
// Converts a number into a decimal string.
// @param x0 buffer in which to convert the number.
// @param x1 number to convert
// @return x0 buffer from x0
itoa10:
mov x6, x0
mov x2, #10
mov x5, #'0'
.itoa10_loop:
udiv x3, x1, x2
msub x4, x3, x2, x1
add x4, x4, x5
strb w4, [x0], #1
mov x1, x3
cmp x1, xzr
bne .itoa10_loop
strb wzr, [x0], #-1
mov x1, x6
.reverse:
cmp x0, x1
ble .reverseDone
ldrb w2,[x0]
ldrb w3,[x1]
strb w3,[x0], #-1
strb w2,[x1], #1
b .reverse
.reverseDone:
mov x0,x6
ret
.data
header:
.ascii "Expense Report\n"
headerLen = . - header
meals:
.ascii "Meal Expenses: "
mealsLen = . - meals
total:
.ascii "Total Expenses: "
totalLen = . - total
tab:
.ascii "\t"
tabLen = . - tab
newline:
.ascii "\n"
newlineLen = . - newline
mealOverExpensesMarker:
.ascii "X"
mealNotOverExpensesMarker:
.ascii " "
dinner:
.ascii "Dinner"
dinnerLen = . - dinner
breakfast:
.ascii "Breakfast"
breakfastLen = . - breakfast
carRental:
.ascii "Car Rental"
carRentalLen = . - carRental
expenseNames:
.quad 0
.quad dinner
.quad breakfast
.quad carRental
expenseNameLengths:
.quad 0
.quad dinnerLen
.quad breakfastLen
.quad carRentalLen
expenses:
.quad DINNER, 5000
.quad DINNER, 5001
.quad BREAKFAST, 1000
.quad BREAKFAST, 1001
.quad CAR_RENTAL, 4
.quad 0, 0
.bss
buffer:
.fill 11,1,0