Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
7538 | leency | 1 | ;MM_ = MemoryManager |
2 | ;Этот модуль позволяет выделять память маленькими кусочками, оптимально используя |
||
3 | ;страницы памяти |
||
4 | ;Блоки - это одна или несколько страниц, которые имеют запись |
||
5 | ;в MM_BlockInfo и которые в конце имеют стекообразную структуру(в смысле |
||
6 | ;растёт к меньшим адресам), заканчивающейся dword 0. В начале блока |
||
7 | ;находятся данные. В структуре находятся пары dword'ов: начало |
||
8 | ;участков, их конец(посл. байт+1). Эти пары всегда сортируются по |
||
9 | ;расположению описываемых |
||
10 | ;участков в обратном порядке, т.е. в самом конце блока будет пара данных |
||
11 | ;на самый первый участок. Для выделения памяти нужно найти блок, в котором |
||
12 | ;достаточно места (причём необходимое место = запрашиваемый объём + место |
||
13 | ;под пару с данными в конце блока) и вставить пару с нужными данными. |
||
14 | ;Для удаления участка нужно только убрать из пар пару с нужным участком |
||
15 | ;и поправить расположение остальных пар. |
||
16 | ;begData1.....endData1,begData2...endData2,.......0,beg2,end2,beg1,end1 |
||
17 | |||
18 | |||
19 | ;выделяет память |
||
20 | ;return eax = указатель на выделеный блок |
||
21 | ;proc MM_AllocMem stdcall,Size:DWORD |
||
22 | |||
23 | ;БАГ в выделении крупных кусков: всегда выделяет новую страницу |
||
24 | |||
25 | |||
26 | |||
27 | align 4 |
||
28 | MM_AllocMem: |
||
29 | Size equ ebp+8 |
||
30 | begFree equ ebp-8 ;начало |
||
31 | endFree equ ebp-4 ;и конец свободного места от конца инфы до |
||
32 | endArea equ ebp-12 |
||
33 | push ebp |
||
34 | mov ebp,esp |
||
35 | add esp,-4*3 |
||
36 | push ebx edi esi |
||
37 | ;dps 'MEM: ' |
||
38 | ;dph [Size] |
||
39 | ;dps ' ' |
||
40 | ;начала пар записей |
||
41 | mov edx,[MM_NBlocks] |
||
42 | cmp edx,0 |
||
43 | jne .BegTestBlocks ;если блоков нет, то добавить новый |
||
44 | mov ecx,[Size] |
||
45 | call AddBlock |
||
46 | jmp .return |
||
47 | align 4 |
||
48 | .BegTestBlocks: |
||
49 | |||
50 | |||
51 | xor ebx,ebx |
||
52 | mov ecx,edx |
||
53 | align 4 |
||
54 | .TestBlock: ;проверка блока |
||
55 | ;проверка: есть ли место для ещё одной пары |
||
56 | mov edi,[MM_BlocksInfo+ebx] |
||
57 | add edi,[MM_BlocksInfo+ebx+4] |
||
58 | mov [endArea], edi |
||
59 | sub edi,4 |
||
60 | |||
61 | cmp dword[edi],0 ;если в блоке нет ни одной записи |
||
62 | jne .NoEmptyBlock |
||
63 | mov eax,[MM_BlocksInfo+ebx] |
||
64 | mov dword[edi-4],eax |
||
65 | mov dword[edi],eax |
||
66 | mov edx,[Size] |
||
67 | add dword[edi],edx |
||
68 | mov dword[edi-8],0 |
||
69 | jmp .return |
||
70 | align 4 |
||
71 | .NoEmptyBlock: |
||
72 | xor eax,eax |
||
73 | push ecx |
||
74 | or ecx,-1 |
||
75 | std |
||
76 | repne scasd |
||
77 | cld |
||
78 | pop ecx |
||
79 | mov eax,[edi+12] ;конец посл участка |
||
80 | add eax,4 |
||
81 | cmp eax,edi |
||
82 | jb @f |
||
83 | |||
84 | add ebx,8 |
||
85 | dec ecx |
||
86 | jnz .TestBlock |
||
87 | |||
88 | mov ecx,[Size] |
||
89 | call AddBlock |
||
90 | jmp .return |
||
91 | @@: |
||
92 | |||
93 | |||
94 | mov [begFree],eax ;eax = конец посл. участка + 4 |
||
95 | mov [endFree],edi ;edi = указатель на конец посл участка - 12 |
||
96 | sub dword[begFree],4 |
||
97 | add dword[endFree],12 |
||
98 | |||
99 | ;проверка перед всеми участками |
||
100 | mov edi,[MM_BlocksInfo+ebx] |
||
101 | mov eax,[endArea] |
||
102 | mov eax,[eax-8] |
||
103 | sub eax,[MM_BlocksInfo+ebx] |
||
104 | cmp eax,[Size] |
||
105 | ja .AddInBegBlock |
||
106 | |||
107 | ;проверка между участками |
||
108 | mov eax,[endArea] |
||
109 | cmp dword[eax-12],0 |
||
110 | je .EndTest ;если в блоке только 1 участок |
||
111 | |||
112 | sub eax,4 |
||
113 | @@: |
||
114 | mov edi,[eax-12] |
||
115 | sub edi,[eax] |
||
116 | cmp edi,[Size] |
||
117 | jae .AddInMiddle |
||
118 | sub eax,8 |
||
119 | cmp dword[eax-8],0 |
||
120 | jne @b |
||
121 | |||
122 | .EndTest: |
||
123 | |||
124 | ;проверка после всех блоков |
||
125 | mov eax,[begFree] |
||
126 | mov edi,[endFree] |
||
127 | lea esi,[edi-8] ;8 - место под запись |
||
128 | sub esi,eax |
||
129 | |||
130 | cmp esi,[Size] |
||
131 | ja .AddInEnd |
||
132 | |||
133 | add ebx,8 |
||
134 | dec ecx |
||
135 | jnz .TestBlock |
||
136 | |||
137 | mov ecx,[Size] |
||
138 | call AddBlock |
||
139 | |||
140 | jmp .return |
||
141 | align 4 |
||
142 | .AddInBegBlock: ;Добавить в начало. В edi начало блока |
||
143 | ;pop eax |
||
144 | |||
145 | mov eax,edi |
||
146 | add eax,[MM_BlocksInfo+ebx+4] |
||
147 | sub eax,4 |
||
148 | push eax |
||
149 | call MoveRecordsLeft |
||
150 | pop eax |
||
151 | mov [eax-4],edi |
||
152 | push edi |
||
153 | add edi,[Size] |
||
154 | mov [eax],edi |
||
155 | pop eax |
||
156 | |||
157 | jmp .return |
||
158 | align 4 |
||
159 | .AddInMiddle: ;Добавить между участками, еах=конец участка перед свободным местом |
||
160 | |||
161 | ;pop ecx ;add esp,4 |
||
162 | push eax |
||
163 | sub eax,8 |
||
164 | call MoveRecordsLeft |
||
165 | pop eax |
||
166 | |||
167 | mov edx,[eax] |
||
168 | mov [eax-12],edx |
||
169 | add edx,[Size] |
||
170 | mov [eax-8],edx |
||
171 | mov eax,[eax] |
||
172 | jmp .return |
||
173 | align 4 |
||
174 | .AddInEnd: ;Добавить после участков. еdi=указатель на 2ой элем пары с инфой о посл участке |
||
175 | |||
176 | ;add esp,4 |
||
177 | mov eax,[edi] |
||
178 | mov [edi-12],eax |
||
179 | push eax |
||
180 | add eax,[Size] |
||
181 | mov [edi-8],eax |
||
182 | pop eax |
||
183 | |||
184 | .return: |
||
185 | |||
186 | pop esi edi ebx |
||
187 | leave |
||
188 | ret 4 |
||
189 | |||
190 | restore Xren |
||
191 | restore Size |
||
192 | restore begFree |
||
193 | restore endFree |
||
194 | |||
195 | |||
196 | |||
197 | ;eax - первый сдвигаемый dword |
||
198 | ;сдвигает пары dword'ов на 8B назад включая dword 0 |
||
199 | align 4 |
||
200 | proc MoveRecordsLeft |
||
201 | local var1:DWORD,\ |
||
202 | var2:DWORD |
||
203 | |||
204 | p2p [var1],[eax] |
||
205 | p2p [var2],[eax-4] |
||
206 | |||
207 | @@: |
||
208 | sub eax,8 |
||
209 | cmp dword[var1],0 |
||
210 | je @f |
||
211 | |||
212 | push dword[eax] |
||
213 | p2p [eax],[var1] |
||
214 | pop dword[var1] |
||
215 | |||
216 | push dword[eax-4] |
||
217 | p2p [eax-4],[var2] |
||
218 | pop dword[var2] |
||
219 | jmp @b |
||
220 | @@: |
||
221 | |||
222 | mov dword[eax],0 |
||
223 | ret |
||
224 | endp |
||
225 | |||
226 | ;ecx = размер требуемого участка |
||
227 | ;добавляет блок и создаёт в нём участок размером ecx |
||
228 | align 4 |
||
229 | proc AddBlock |
||
230 | mov edx,[MM_NBlocks] |
||
231 | inc edx |
||
232 | cmp edx,MM_MAX_BLOCKS |
||
233 | ja .ErrAlloc |
||
234 | |||
235 | push ecx |
||
236 | add ecx,12 |
||
237 | |||
238 | test ecx,0FFFh ;округляем до большей границы страницы |
||
239 | jz @f |
||
240 | add ecx,1000h |
||
241 | and ecx,0FFFFF000h |
||
242 | @@: |
||
243 | |||
244 | mcall 68,12,ecx |
||
245 | mov [MM_NBlocks],edx ;заполнение данных о блоке |
||
246 | mov [edx*4*2-4*2+MM_BlocksInfo],eax ;begin |
||
247 | mov [edx*4*2-4+MM_BlocksInfo],ecx ;size |
||
248 | ;dps 'Block ' |
||
249 | ;dph eax |
||
250 | ;dps ' ' |
||
251 | ;dph ecx |
||
252 | ;dnl |
||
253 | mov edx,eax |
||
254 | add edx,ecx |
||
255 | mov [edx-8],eax |
||
256 | pop dword[edx-4] |
||
257 | add [edx-4],eax |
||
258 | mov dword[edx-12],0 |
||
259 | ret |
||
260 | |||
261 | .ErrAlloc: |
||
262 | pop ecx |
||
263 | xor eax,eax |
||
264 | ret |
||
265 | endp |
||
266 | ;------------------------------------------------------------------------------- |
||
267 | |||
268 | |||
269 | ;удаляет память |
||
270 | ;proc MM_DelMem Pointer:DWORD |
||
271 | align 4 |
||
272 | MM_DelMem: |
||
273 | Pointer equ ebp+8 |
||
274 | push ebp |
||
275 | mov ebp,esp |
||
276 | ; int3 |
||
277 | push ebx |
||
278 | mov ecx,[MM_NBlocks] |
||
279 | test ecx,ecx |
||
280 | jnz @f |
||
281 | xor eax,eax |
||
282 | pop ebx |
||
283 | leave |
||
284 | ret 4 |
||
285 | @@: |
||
286 | |||
287 | mov eax,[Pointer] |
||
288 | xor ebx,ebx ;ebx - (номер блока)*8 |
||
289 | .TestBlocks: |
||
290 | mov edx,[MM_BlocksInfo+ebx] |
||
291 | add edx,[MM_BlocksInfo+ebx+4] |
||
292 | sub edx,8 ;edx - указатель на 1ую пару |
||
293 | |||
294 | .TestMems: |
||
295 | cmp [edx],eax |
||
296 | je .FoundMem |
||
297 | |||
298 | sub edx,8 |
||
299 | cmp dword[edx+4],0 |
||
300 | jne .TestMems |
||
301 | |||
302 | add ebx,4 |
||
303 | loop .TestBlocks |
||
304 | |||
305 | xor eax,eax |
||
306 | pop ebx |
||
307 | leave |
||
308 | ret 4 |
||
309 | |||
310 | .FoundMem: |
||
311 | cmp dword[edx-4],0 |
||
312 | jz .EndDelMem |
||
313 | |||
314 | .NextMoveMem: |
||
315 | p2p [edx+4],[edx-4] |
||
316 | p2p [edx],[edx-8] |
||
317 | sub edx,8 |
||
318 | cmp dword[edx-4],0 |
||
319 | jnz .NextMoveMem |
||
320 | |||
321 | .EndDelMem: |
||
322 | mov dword[edx+4],0 |
||
323 | mov dword[edx],0 |
||
324 | |||
325 | mov eax,1 |
||
326 | pop ebx |
||
327 | leave |
||
328 | ret 4 |
||
329 | |||
330 | restore Pointer |