This repository has been archived by the owner on Apr 11, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
list.asm
498 lines (370 loc) · 18 KB
/
list.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
;-----------------------------------------------------------------------------
;
; DHBW Ravensburg - Campus Friedrichshafen
;
; Vorlesung Systemnahe Programmierung (SNP)
;
;----------------------------------------------------------------------------
;
; Architecture: x86-64
; Language: NASM Assembly Language
;
; Authors: Johannes Brandenburger, Lukas Braun, Henry Schuler
;
;----------------------------------------------------------------------------
sys_read equ 3
sys_write equ 4
stdout equ 1
stdin equ 2
;-----------------------------------------------------------------------------
; SECTION DATA
;-----------------------------------------------------------------------------
SECTION .data
startAdress dq 0 ; start adress of the program currently 0, filled in later by the list_init function
secondBreak dq 0 ; second ram-breakpoint (maybe not needed)
listSize dq 0 ; size of the list
errorMsg db 'Error in list.asm!' ; error message
lenErrorMsg equ $-errorMsg ; length of the error message
intInAscii db ' ' ; buffer for the debug output
formatStrInt:
db `---> rax: %ld\n`, 0 ; format string for the debug output
;-----------------------------------------------------------------------------
; SECTION TEXT
;-----------------------------------------------------------------------------
SECTION .text
;-----------------------------------------------------------------------------
; extern void list_init(void)
;-----------------------------------------------------------------------------
global list_init:function
list_init:
push rbp
mov rbp,rsp
push rbx
; set the first breakpoint (start of the list)
mov rax, 45 ; load sys_brk (allocate mem) into eax
xor rbx, rbx ; clear rbx (needed for sys_brk)
int 80h ; call sys_brk (first breakpoint)
; check if the first breakpoint was set correctly
cmp rax, 0 ; check if the allocation was successful (-1 if not)
jl exit ; if not, exit the program
; set the second breakpoint (end of the list)
mov [startAdress], rax ; save start adress of the program in startAdress
add rax, 1048576 ; add number of bytes to be reserved (65 536 (16 bit) * 2 (tv_sec + tv_usec) * 8)
mov rbx, rax ; save the adress of second breakpoint in rbx
mov rax, 45 ; load sys_brk (allocate mem) into eax
int 80h ; call sys_brk (second breakpoint)
; check if the second breakpoint was set correctly
cmp rax, 0 ; check if the allocation was successful (-1 if not)
jl exit ; if not, exit the program
pop rbx
mov rsp,rbp
pop rbp
ret
;-----------------------------------------------------------------------------
; extern short list_size(void);
;-----------------------------------------------------------------------------
global list_size:function
list_size:
push rbp
mov rbp,rsp
; return the list size
mov rax, [listSize] ; load the size of the list into rax
mov rsp,rbp
pop rbp
ret
;-----------------------------------------------------------------------------
; extern bool list_is_sorted(void);
;-----------------------------------------------------------------------------
global list_is_sorted:function
list_is_sorted:
push rbp
mov rbp,rsp
push rbx
; immediately return false if the list is empty
mov rax, [listSize] ; load the size of the list into rax
cmp rax, 0 ; check if the list is empty
je .exit_not_sorted ; if so, return false
; begin to check if the list is sorted
mov rbx, [startAdress] ; load the start adress of the list into rax
mov rcx, 1 ; set counter to 1
mov rdx, 1 ; set return value to true
.loop:
; load the two tv_sec to compare
mov r8, [rbx] ; load the current tv_sec of the list into r8
mov r9, [rbx+16] ; load the next tv_sec of the list into r9
; compare the two tv_sec values
cmp r9, r8 ; check if the next tv_sec is bigger than the current tv_sec
jb .exit_not_sorted ; if not, return false
ja .already_bigger_tv_sec
; load the two tv_usec to compare
mov r8, [rbx+8] ; load the current tv_usec of the list into r8
mov r9, [rbx+24] ; load the next tv_usec of the list into r9
; compare the two tv_usec values
cmp r9, r8 ; check if the next tv_usec is bigger than the current tv_usec
jle .exit_not_sorted ; if not, return false
.already_bigger_tv_sec:
; the tv_usec values are not relevant if the tv_sec values are already not equal
add rbx, 16 ; increase the current adress by 16 bytes (size of one tv_sec)
inc rcx ; increment the counter by 1
cmp rcx, [listSize] ; check if the counter is equal to the size of the list
je .loop_exit ; if so, the list is gone through -> return true
jne .loop ; if not, go to the beginning of the loop
.exit_not_sorted:
; return false
mov rdx, 0 ; return false
.loop_exit:
; all elements are gone through -> return true
mov rax, rdx ; return the return value
pop rbx
mov rsp,rbp
pop rbp
ret
;-----------------------------------------------------------------------------
; extern short list_add(struct timeval *tv);
;-----------------------------------------------------------------------------
global list_add:function
list_add:
push rbp
mov rbp, rsp
push rbx
; start the loop
mov rbx, [startAdress] ; load the start adress of the list in rax
xor rcx, rcx ; clear rcx (counter = 0)
.loop:
; check if the right adress is reached
cmp rcx, [listSize] ; check if the counter is equal the size of the list
je .loop_exit ; if so, the right adress is reached
; increment the counter
add rbx, 16 ; add 16 to the current adress
inc rcx ; increment the counter
jmp .loop
.loop_exit:
; write tv_sec into memory
mov rax, [rdi] ; load the timeval.tv_sec into rax
mov [rbx], rax ; load the timeval.tv_sec into memory at the right adress (startAdress + 16*listSize)
; write tv_usec into memory
mov rax, [rdi+8] ; load the timeval.tv_usec into rax
mov [rbx + 8], rax ; load the timeval.tv_usec into memory at the right adress (startAdress + 16*listSize + 8)
; increase the size of the list
mov rax, [listSize] ; load the size of the list into rax
inc rax ; increase the size of the list by 1
mov [listSize], rax ; save the new size of the list in listSize
; return the new position of the element
dec rax ; decrease the size of the list by 1 to get current position
pop rbx
mov rsp, rbp
pop rbp
ret
;-----------------------------------------------------------------------------
; extern short list_find(struct timeval *tv);
;-----------------------------------------------------------------------------
global list_find:function
list_find:
push rbp
mov rbp,rsp
push rbx
push r12
push r13
push r14
; store given tv
mov r10, rdi ; write the adress of the tv in r10
; immediately return 0 if the list is empty
mov rax, [listSize] ; load the size of the list into rax
cmp rax, 0 ; check if the list is empty
je .exit_not_found ; if so, return false
; check if tv is smaller or equal than the smallest tv
mov rdi, r10 ; write adress of given tv in rdi (for compare_timevals())
mov rsi, [startAdress] ; write start adress of list in rsi (for compare_timevals())
mov rbx, 0 ; current comparison at index 0 (for return)
call compare_timevals ; compaires tv at rdi and rsi
cmp rax, 1 ; rax: 0 (rdi<rsi), 1 (rdi==rsi), 2 (rdi>rsi),
je .exit_found ; if equal -> found already
jb .exit_not_found ; if smaller the tv is not in the list
; check if tv is bigger or equal than the biggest tv
mov rdi, [listSize] ; write current list size in rdi
dec rdi ; decrement it (getting last tv's index)
mov rbx, rdi ; current comparison at last (for return)
call get_adress_by_index ; get adress from index in rdi in rax
mov rdi, r10 ; write adress of given tv in rdi (for compare_timevals())
mov rsi, rax ; write adress of last tv in rsi (for compare_timevals())
call compare_timevals ; compaires tv at rdi and rsi
cmp rax, 1 ; rax: 0 (rdi<rsi), 1 (rdi==rsi), 2 (rdi>rsi),
je .exit_found ; if equal -> found already
ja .exit_not_found ; if smaller the tv is not in the list
; start binary search loop
; define borders (r11, r13)
mov r11, 0 ; set lower border
mov r13, [listSize]
dec r13 ; set higher border
.loop:
; get middle of borders (r12)
mov rax, r13
sub rax, r11 ; rax: higher border - lower border
mov r14, 2 ; set divisor
xor rdx, rdx ; clear output register
div r14
add rax, r11 ; add lower border to get middle
mov r12, rax ; save middle of borders
; compair middle with
mov rbx, r12 ; current comparison at middle (for return)
; call long get_address_by_index(int index);
mov rdi, r12
call get_adress_by_index ; get middle adress
; call int compare_timevals(struct timeval *tv1, struct timeval *tv2)
mov rdi, r10 ; write adress of given tv in rdi (for compare_timevals())
mov rsi, rax ; write middle adress in rsi (for compare_timevals())
call compare_timevals
cmp rax, 1
jb .lower
ja .higher
je .exit_found
.lower:
cmp r11, r13
je .exit_not_found
; higher bound = middle
mov r13, r12
jmp .loop
.higher:
; check if lower border == middle
cmp r11, r12
cmove r11, r13 ; if lower border == middle -> set higher border to lower border -> force checking higher border value
; if not: lower bound = middle
cmovne r11, r12
jmp .loop
.exit_not_found:
mov rax, -1
jmp .end_return
.exit_found:
mov rax, rbx
jmp .end_return
.end_return:
pop r14
pop r13
pop r12
pop rbx
mov rsp,rbp
pop rbp
ret
;-----------------------------------------------------------------------------
; extern long get_adress_by_index(int index);
; rdi (index) -> rax (adress) NOTE: can be improved
;-----------------------------------------------------------------------------
global get_adress_by_index:function
get_adress_by_index:
push rbp
mov rbp,rsp
push rbx
xor rcx, rcx ; clear counter
mov rbx, [startAdress] ; start adress in rbx
.loop:
cmp rcx, rdi ; compair the current index with the given index
je .loop_exit ; if equal -> finished
add rbx, 16 ; increment the current adress with 16
inc rcx ; increment the current index (counter) with 1
jmp .loop ; next index
.loop_exit:
mov rax, rbx ; return the current adress
pop rbx
mov rsp,rbp
pop rbp
ret
;-----------------------------------------------------------------------------
; int compare_timevals(struct timeval *tv1, struct timeval *tv2) (RDX, RSI)
; returns in RAX:
; 0 if tv1 < tv2
; 1 if tv1 == tv2
; 2 if tv1 > tv2
;-----------------------------------------------------------------------------
global compare_timevals:function
compare_timevals:
push rbp
mov rbp, rsp
; load the two tv_sec to compare
mov r8, [rdi] ; load first tv_sec into r8
mov r9, [rsi] ; load second tv_sec into r8
; compare the two tv_sec values
cmp r8, r9 ; compare the two tv_sec
jb .smaller ; if already smaller return 0
ja .bigger ; if already bigger return 2
; load the two tv_usec to compare
mov r8, [rdi+8] ; load first tv_usec into r8
mov r9, [rsi+8] ; load second tv_usec into r9
; compare the two tv_usec values
cmp r8, r9 ; compare the two tv_sec
jb .smaller ; if smaller return 0
ja .bigger ; if bigger return 2
je .equal ; if equal return 1
.smaller:
mov rax, 0 ; return 0
call .compaired
.bigger:
mov rax, 2 ; return 2
call .compaired
.equal:
mov rax, 1 ; return 1
call .compaired
.compaired:
mov rsp, rbp
pop rbp
ret
;-----------------------------------------------------------------------------
; extern bool list_get(struct timeval *tv, short idx);
;-----------------------------------------------------------------------------
global list_get:function
list_get:
push rbp
mov rbp,rsp
push rbx
; check if the list size is 0
mov rax, [listSize] ; load the size of the list into rax
cmp rax, 0 ; check if the size is 0
je .not_found ; if so, return false
; check if the index is bigger than the list size
mov rax, [listSize] ; load the size of the list into rax
cmp rsi, rax ; check if the param index is bigger than the size of the list
jge .not_found ; if so, return false
; check if the index is smaller than 0
cmp rsi, 0 ; check if the param index is smaller than 0
jl .not_found ; if so, return false
; get the offset to the adress of the given index
mov rax, rsi ; load the index into rax
mov rbx, 16 ; set the offset for one address in rbx (multiplyer)
xor rdx, rdx ; clear the output register
mul rbx ; rax * rbx = offset
; calculate the adress of the given index (rbx)
mov rbx, [startAdress] ; load the start adress of the list into rbx
add rbx, rax ; add the offset to the start adress to get the adress of the given index
; get the timeval.tv_sec of the list element with the given index
mov rax, [rbx] ; load the tv_sec of the list element into rax
mov [rdi], rax ; save the tv_sec of the list element into the given adress
; get the timeval.tv_usec of the list element with the given index
mov rax, [rbx+8] ; load the tv_usec of the list element into rax
mov [rdi+8], rax ; save the tv_usec of the list element into the given adress
.done:
; return true
mov rax, 1 ; return 1 to indicate that the timeval was found and copied to the adress
; exit the function
pop rbx
mov rsp,rbp
pop rbp
ret
.not_found:
; return false
mov rax, 0 ; return 0 to indicate that the timeval was not found
; exit the function
mov rsp,rbp
pop rbp
ret
exit:
push rbp
mov rbp,rsp
push rbx
mov rax, sys_write ; Sys-Call Number (Write)
mov rbx, stdout ; file discriptor (STD OUT)
mov rcx, errorMsg ; Message to write
mov rdx, lenErrorMsg ; length of the Message
int 80h ; call Kernel
pop rbx
mov rsp,rbp
pop rbp
ret