-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathfhtw.asm
205 lines (153 loc) · 4.59 KB
/
fhtw.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
%include "os_dependent_stuff.asm"
%macro hash_function 5
; clobbers rcx and all arguments
; %1 = key pointer
; %2 = key length
; %3 = desired return register
; %4 & 5 are scratch
xor %3, %3
%%begin:
cmp %2, 8
jl %%last_bits
crc32 %3, qword[%1]
add %1, 8
sub %2, 8
jnz %%begin
jmp %%ret
%%last_bits:
; zero out the higher bits of the last partial byte
; r11 holds the last byte
mov %4, [%1]
; shift operator can only use cl, so put the number of bits remaining into rcx
mov rcx, %2
shl rcx, 3 ; multiply by 8 to get bits
; rdx will hold the desired mask
mov %5, 1
shl %5, cl
dec %5
and %4, %5
crc32 %3, %4
%%ret:
%endmacro
global fhtw_new
fhtw_new:
push rdi ; store requested size for later
; rdi is the size of the the table
; we need 3 pieces of metadata - occupancy, capacity, size of info word in bits
; and 3 arrays - keys, values, and hop info words
; info word size does not change the amount of memory allocated; just says how many bits we use
inc rdi
mov rax, 24
mul rdi
; load arguments to mmap
mov rsi, rax ; size
mov r10, MAP_SHARED | MAP_ANON ; not backed by a file
mov r8, -1 ; file descripter is -1
mov r9, 0 ; no offset
mov rax, SYSCALL_MMAP
mov rdx, PROT_READ | PROT_WRITE ; read/write access
mov rdi, 0 ; we don't care about the particular address
syscall
test rax, rax
;js .error ; local error label
; initialize metadata
; occupancy at [rax] has already been set to 0 by mmap
pop r11
mov [rax + 8], r11 ; store capacity
dec r11
bsr r11, r11
mov [rax + 16], r11 ; store size of info word - logarithmic in capacity
ret
global fhtw_free
fhtw_free:
; put size of memory to be freed in rsi
mov r11, [rdi + 8]
inc r11
mov rax, 24
mul r11
; arguments to munmap
; rdi already set to address
mov rsi, rax
mov rax, SYSCALL_MUNMAP
syscall
ret
global fhtw_set
fhtw_set:
; rdi = table pointer
; rsi = key pointer
; rdx = key length
; rcx = value
; r8 = value length? -- used in function!
; make sure there is room in the table
mov r11, [rdi]
cmp r11, [rdi + 8]
je .table_full
; calculate hash
mov r8, rsi ; save key pointer in r8
mov r9, rcx ; save value in r9
hash_function rsi, rdx, rax, r11, r10
; linear probe for empty space
div [rdi + 8] ; hash value is in rax, we divide by table size.
shl rdx, 3 ; get index in bits
add rdx, rdi
add rdx, 24 ; add rdi + 24 to get start of key array
.begin:
cmp qword[rdx], 0
je .end
add rdx, 8
jmp .begin
.end:
; empty space is in rdx
; if empty space is within length of bitmap, insert
; STUB just insert into empty space - linear probe table
mov [rdx], r8 ; insert key
mov rax, [rdi + 8] ; next 3 lines calculate value position
shl rax, 3
add rax, rdx
mov [rax], r9 ; insert value
; if space is too far away, hop the space back until it is close enough
; when it's close enough, jump to insert
; increase occupancy
ret
.table_full:
; return error code
mov rax, -1
ret
global fhtw_get
fhtw_get:
; table in rdi
; key in rsi
; keylen in rdx
; STUB linear probing
mov r8, rsi
mov r9, rdx
hash_function rsi, rdx, rax, r10, r11
mov r10, rdi
div [r10 + 8] ; hash value is in rax, we divide by table size.
; get pointer in the key array into rdx
shl rdx, 3 ; get index in bits
add rdx, r10
add rdx, 24 ; add rdi + 24 to get start of key array
.begin:
; if we've hit an empty space the key is not valid
cmp [rdx], 0
jz .fail
; TODO loop back if we're at the end of the table
; TODO return fail if we've reached our original position
; repe cmps compares strings one byte at a time; it expects
; rcx == strlen, rdi == str1, rsi == str2
; clobbers all registers, so we have to reset them each time
mov rcx, r9
mov rdi, r8
mov rsi, [rdx]
repe cmps
; zero flag will be set if the two strings are equal
jz .success
add rdx, 8
jmp .begin
.success:
.fail:
global fhtw_hash
fhtw_hash:
hash_function rdi, rsi, rax, rdx, r11
ret