-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathmap.inc
237 lines (227 loc) · 4.6 KB
/
map.inc
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
; this is a simple map used primarily for the source cache
struct Map
hash_mask dd ?
linked_blocks dd ?
free_space dd ?
free_space_length dd ?
ends
struct MapEntry
name dd ?
name_length dd ?
value dd ?
next_entry dd ?
ends
create_string_map:
; in: cl = number of hash bits
; out: ebx - new map
; preserves: esi
mov ebx,1
shl ebx,cl
shl ebx,2
lea ecx,[sizeof.Map+ebx*4]
call malloc_fixed
xchg ebx,eax
mov ecx,eax
dec eax
mov [ebx+Map.hash_mask],eax
lea edi,[ebx+sizeof.Map]
xor eax,eax
rep stosd
mov ecx,1000h
call malloc_fixed
mov [ebx+Map.linked_blocks],eax
xor edx,edx
mov [eax],edx
add eax,10h
mov [ebx+Map.free_space],eax
mov [ebx+Map.free_space_length],1000h-10h
retn
destroy_string_map:
; in: ebx - map
; preserves: esi, edi
mov eax,ebx
mov ebx,[ebx+Map.linked_blocks]
call mfree
free_map_blocks:
test ebx,ebx
jz string_map_destroyed
mov eax,ebx
mov ebx,[ebx]
call mfree
jmp free_map_blocks
string_map_destroyed:
retn
get_from_map:
; in:
; ebx - map
; esi - string
; ecx = string length, zero for ASCIIZ string
; out:
; eax = value
; cf set when no entry found
; preserves: ebx, [esi], edi
; note: when entry is found, esi is replaced with pointer to the same string in persistent storage
call get_bucket
test eax,eax
jz not_found_in_map
call find_map_entry
jc not_found_in_map
mov eax,[eax+MapEntry.value]
retn
get_bucket:
call hash_string
and edx,[ebx+Map.hash_mask]
mov eax,[ebx+sizeof.Map+edx*4]
retn
find_map_entry:
cmp [eax+MapEntry.name_length],ecx
jne next_map_entry
push edi
mov edi,[eax+MapEntry.name]
test edi,edi
jz not_this_map_entry
push ecx esi
repe cmpsb
pop esi ecx
jne not_this_map_entry
mov esi,edi
sub esi,ecx
pop edi
clc
retn
not_this_map_entry:
pop edi
next_map_entry:
mov eax,[eax+MapEntry.next_entry]
test eax,eax
jnz find_map_entry
not_found_in_map:
stc
retn
put_into_map:
; in:
; ebx - map
; esi - string
; ecx = string length, zero for ASCIIZ string
; eax = value
; preserves: ebx, [esi], edi
; note:
; esi is replaced with pointer to the same string in persistent storage,
; an ASCIIZ string is a key with length including the terminating zero
; and when it is put into persistent storage, final zero is copied as well
push eax
call get_bucket
test eax,eax
jz new_bucket
call find_map_entry
jnc put_value_into_map_entry
mov eax,[ebx+sizeof.Map+edx*4]
find_free_map_entry:
cmp [eax+MapEntry.name],0
je fill_map_entry
mov edx,eax
mov eax,[eax+MapEntry.next_entry]
test eax,eax
jnz find_free_map_entry
call allocate_map_entry
mov [edx+MapEntry.next_entry],eax
jmp new_map_entry
new_bucket:
call allocate_map_entry
mov [ebx+sizeof.Map+edx*4],eax
new_map_entry:
mov [eax+MapEntry.next_entry],0
fill_map_entry:
mov [eax+MapEntry.name_length],ecx
push eax
call store_string
pop eax
mov [eax+MapEntry.name],esi
put_value_into_map_entry:
pop [eax+MapEntry.value]
retn
allocate_map_entry:
mov eax,[ebx+Map.free_space]
add [ebx+Map.free_space],sizeof.MapEntry
sub [ebx+Map.free_space_length],sizeof.MapEntry
jc map_out_of_free_space
retn
map_out_of_free_space:
push ecx edx
mov ecx,1000h
call malloc_fixed
mov edx,eax
xchg [ebx+Map.linked_blocks],edx
mov [eax],edx
add eax,10h
mov [ebx+Map.free_space],eax
mov [ebx+Map.free_space_length],1000h-10h
pop edx ecx
jmp allocate_map_entry
remove_from_map:
; in:
; ebx - map
; esi - string
; ecx = string length, zero for ASCIIZ string
; preserves: ebx, [esi], edi
call get_bucket
test eax,eax
jz not_found_in_map
call find_map_entry
jc not_found_in_map
mov dword [eax+MapEntry.name],0
retn
iterate_through_map:
; in:
; ebx - map
; edi - callback function
; callback:
; eax = value
; esi - string
; ecx = string length
; edx - MapEntry
mov ecx,[ebx+Map.hash_mask]
inc ecx
add ebx,sizeof.Map
iterate_through_hash_table:
mov edx,[ebx]
iterate_through_bucket:
test edx,edx
jz end_of_bucket
push ebx ecx edx edi
mov eax,[edx+MapEntry.value]
mov esi,[edx+MapEntry.name]
mov ecx,[edx+MapEntry.name_length]
call edi
pop edi edx ecx ebx
mov edx,[edx+MapEntry.next_entry]
jmp iterate_through_bucket
end_of_bucket:
add ebx,4
loop iterate_through_hash_table
retn
hash_string:
; in: esi - string, ecx = string length, zero for ASCIIZ string
; out: ecx = string length, edx = 32-bit hash
; preserves: ebx, esi, edi
mov edx,FNV_OFFSET
jecxz hash_asciiz
mov eax,ecx
hash_known_length:
xor dl,[esi]
inc esi
imul edx,FNV_PRIME
loop hash_known_length
mov ecx,eax
sub esi,ecx
retn
hash_asciiz:
inc ecx
lodsb
xor dl,al
imul edx,FNV_PRIME
test al,al
jnz hash_asciiz
hash_ready:
sub esi,ecx
retn