Subversion Repositories Kolibri OS

Rev

Rev 2129 | Rev 2167 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
431 serge 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
1289 diamond 3
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;;
431 serge 4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
164 serge 7
 
593 mikedld 8
$Revision: 2154 $
9
 
10
 
164 serge 11
struc MEM_BLOCK
2154 serge 12
{
13
   .list        LHEAD
14
   .next_block  dd ? ;+8
164 serge 15
   .prev_block  dd ? ;+4
16
   .base        dd ? ;+16
17
   .size        dd ? ;+20
18
   .flags       dd ? ;+24
19
   .handle      dd ? ;+28
2154 serge 20
   .sizeof:
164 serge 21
}
22
 
23
FREE_BLOCK      equ  4
24
USED_BLOCK      equ  8
546 diamond 25
DONT_FREE_BLOCK equ  10h
164 serge 26
 
27
virtual at 0
28
  MEM_BLOCK MEM_BLOCK
29
end virtual
30
 
31
 
32
block_next   equ MEM_BLOCK.next_block
33
block_prev   equ MEM_BLOCK.prev_block
2154 serge 34
list_fd      equ MEM_BLOCK.list.next
35
list_bk      equ MEM_BLOCK.list.prev
164 serge 36
block_base   equ MEM_BLOCK.base
37
block_size   equ MEM_BLOCK.size
38
block_flags  equ MEM_BLOCK.flags
39
 
40
macro calc_index op
41
{          shr op, 12
42
           dec op
43
           cmp op, 63
44
           jna @f
45
           mov op, 63
46
@@:
47
}
48
 
49
macro remove_from_used op
50
{
357 serge 51
           mov edx, [op+list_fd]
52
           mov ecx, [op+list_bk]
53
           mov [edx+list_bk], ecx
54
           mov [ecx+list_fd], edx
55
           mov [op+list_fd], 0
56
           mov [op+list_bk], 0
164 serge 57
}
58
 
2154 serge 59
;Initial heap state
60
;
61
;+heap_size               terminator        USED_BLOCK
62
;+4096*MEM_BLOCK.sizeof   free space        FREE_BLOCK
63
;HEAP_BASE                heap_descriptors  USED_BLOCK
64
;
65
 
164 serge 66
align 4
67
proc init_kernel_heap
68
 
1130 diamond 69
           mov ecx, 64
164 serge 70
           mov edi, mem_block_list
2154 serge 71
@@:
72
            mov eax, edi
73
            stosd
74
            stosd
75
            loop @B
164 serge 76
 
2154 serge 77
            mov eax, mem_used.fd
357 serge 78
           mov [mem_used.fd], eax
79
           mov [mem_used.bk], eax
80
 
164 serge 81
           stdcall alloc_pages, dword 32
82
           mov ecx, 32
83
           mov edx, eax
84
           mov edi, HEAP_BASE
85
.l1:
86
           stdcall map_page,edi,edx,PG_SW
87
           add edi, 0x1000
88
           add edx, 0x1000
89
           dec ecx
90
           jnz .l1
91
 
2154 serge 92
            mov edi, HEAP_BASE                     ;descriptors
93
            mov ebx, HEAP_BASE+MEM_BLOCK.sizeof      ;free space
94
            mov ecx, HEAP_BASE+MEM_BLOCK.sizeof*2    ;terminator
95
 
164 serge 96
           xor eax, eax
97
           mov [edi+block_next], ebx
98
           mov [edi+block_prev], eax
357 serge 99
           mov [edi+list_fd], eax
100
           mov [edi+list_bk], eax
164 serge 101
           mov [edi+block_base], HEAP_BASE
2154 serge 102
            mov [edi+block_size], 4096*MEM_BLOCK.sizeof
164 serge 103
           mov [edi+block_flags], USED_BLOCK
104
 
2154 serge 105
            mov [ecx+block_next], eax
106
            mov [ecx+block_prev], ebx
107
            mov [edi+list_fd], eax
108
            mov [edi+list_bk], eax
109
            mov [edi+block_base], eax
110
            mov [edi+block_size], eax
111
            mov [edi+block_flags], USED_BLOCK
164 serge 112
 
2154 serge 113
            mov [ebx+block_next], ecx
114
            mov [ebx+block_prev], edi
115
            mov [ebx+block_base], HEAP_BASE+4096*MEM_BLOCK.sizeof
116
 
1090 diamond 117
           mov ecx, [pg_data.kernel_pages]
118
           shl ecx, 12
2154 serge 119
            sub ecx, HEAP_BASE-OS_BASE+4096*MEM_BLOCK.sizeof
170 serge 120
           mov [heap_size], ecx
121
           mov [heap_free], ecx
164 serge 122
           mov [ebx+block_size], ecx
123
           mov [ebx+block_flags], FREE_BLOCK
124
 
125
           mov [mem_block_mask], eax
126
           mov [mem_block_mask+4],0x80000000
127
 
2154 serge 128
            mov ecx, mem_block_list+63*8
129
            list_add ebx, ecx
130
 
131
            mov ecx, 4096-3-1
132
            mov eax, HEAP_BASE+MEM_BLOCK.sizeof*4
133
 
134
            mov [next_memblock], HEAP_BASE+MEM_BLOCK.sizeof*3
135
@@:
136
            mov [eax-MEM_BLOCK.sizeof], eax
137
            add eax, MEM_BLOCK.sizeof
138
            loop @B
139
 
140
            mov [eax-MEM_BLOCK.sizeof], dword 0
141
 
142
 
2129 serge 143
           mov ecx, heap_mutex
144
           call mutex_init
2154 serge 145
            mov [heap_blocks], 4094
146
            mov [free_blocks], 4093
164 serge 147
           ret
148
endp
149
 
369 serge 150
; param
151
;  eax= required size
152
;
153
; retval
154
;  edi= memory block descriptor
155
;  ebx= descriptor index
156
 
164 serge 157
align 4
819 serge 158
get_small_block:
164 serge 159
           mov ecx, eax
369 serge 160
           shr ecx, 12
161
           dec ecx
162
           cmp ecx, 63
163
           jle .get_index
164
           mov ecx, 63
165
.get_index:
166
           lea esi, [mem_block_mask]
164 serge 167
           xor ebx, ebx
369 serge 168
           or edx, -1
164 serge 169
 
170
           cmp ecx, 32
171
           jb .bit_test
172
 
173
           sub ecx, 32
174
           add ebx, 32
175
           add esi, 4
176
.bit_test:
177
           shl edx, cl
369 serge 178
           and edx, [esi]
179
.find:
180
           bsf edi, edx
164 serge 181
           jz .high_mask
369 serge 182
           add ebx, edi
2154 serge 183
           lea ecx, [mem_block_list+ebx*8]
184
           mov edi, ecx
185
.next:
186
           mov edi, [edi+list_fd]
187
           cmp edi, ecx
188
           je .err
369 serge 189
           cmp eax, [edi+block_size]
190
           ja .next
164 serge 191
           ret
2154 serge 192
.err:
193
           xor edi, edi
194
           ret
164 serge 195
 
196
.high_mask:
197
           add esi, 4
369 serge 198
           cmp esi, mem_block_mask+8
199
           jae .err
164 serge 200
           add ebx, 32
369 serge 201
           mov edx, [esi]
202
           jmp .find
164 serge 203
 
204
 
819 serge 205
align 4
206
free_mem_block:
2154 serge 207
           mov ebx, [next_memblock]
208
           mov [eax], ebx
209
           mov [next_memblock], eax
210
           xor ebx, ebx
357 serge 211
 
2154 serge 212
           mov dword [eax+4], ebx
213
           mov dword [eax+8], ebx
214
           mov dword [eax+12], ebx
215
           mov dword [eax+16], ebx
216
;           mov dword [eax+20], 0     ;don't clear block size
217
           mov dword [eax+24], ebx
218
           mov dword [eax+28], ebx
170 serge 219
           inc [free_blocks]
164 serge 220
	   ret
221
 
222
align 4
223
proc alloc_kernel_space stdcall, size:dword
224
           local block_ind:DWORD
225
 
660 serge 226
           push ebx
227
           push esi
228
           push edi
229
 
164 serge 230
           mov eax, [size]
206 serge 231
           add eax, 4095
232
           and eax, not 4095
164 serge 233
           mov [size], eax
279 serge 234
 
170 serge 235
           cmp eax, [heap_free]
236
           ja .error
164 serge 237
 
2154 serge 238
           mov ecx, heap_mutex
239
           call mutex_lock
240
 
241
           mov eax, [size]
242
 
819 serge 243
           call get_small_block ; eax
369 serge 244
           test edi, edi
2154 serge 245
           jz .error_unlock
164 serge 246
 
247
           cmp [edi+block_flags], FREE_BLOCK
2154 serge 248
           jne .error_unlock
164 serge 249
 
250
           mov [block_ind], ebx   ;index of allocated block
251
 
252
           mov eax, [edi+block_size]
253
           cmp eax, [size]
254
           je .m_eq_size
255
 
2154 serge 256
           mov esi, [next_memblock]     ;new memory block
257
           test esi, esi
258
           jz .error_unlock
164 serge 259
 
2154 serge 260
           dec [free_blocks]
261
           mov eax, [esi]
262
           mov [next_memblock], eax
164 serge 263
 
264
           mov [esi+block_next], edi
265
           mov eax, [edi+block_prev]
266
           mov [esi+block_prev], eax
267
           mov [edi+block_prev], esi
357 serge 268
           mov [esi+list_fd], 0
269
           mov [esi+list_bk], 0
164 serge 270
           mov [eax+block_next], esi
2154 serge 271
 
164 serge 272
           mov ebx, [edi+block_base]
273
           mov [esi+block_base], ebx
274
           mov edx, [size]
275
           mov [esi+block_size], edx
276
           add [edi+block_base], edx
277
           sub [edi+block_size], edx
278
 
279
           mov eax, [edi+block_size]
2154 serge 280
           calc_index eax
164 serge 281
           cmp eax, [block_ind]
282
           je .m_eq_ind
283
 
2154 serge 284
           list_del edi
164 serge 285
 
286
           mov ecx, [block_ind]
2154 serge 287
           lea edx, [mem_block_list+ecx*8]
288
           cmp edx, [edx]
164 serge 289
           jnz @f
290
           btr [mem_block_mask], ecx
291
@@:
292
           bts [mem_block_mask], eax
2154 serge 293
           lea edx, [mem_block_list+eax*8]   ;edx= list head
294
           list_add edi, edx
164 serge 295
.m_eq_ind:
2154 serge 296
           mov ecx, mem_used.fd
357 serge 297
           mov edx, [ecx+list_fd]
298
           mov [esi+list_fd], edx
299
           mov [esi+list_bk], ecx
300
           mov [ecx+list_fd], esi
301
           mov [edx+list_bk], esi
302
 
164 serge 303
           mov [esi+block_flags], USED_BLOCK
170 serge 304
           mov ebx, [size]
305
           sub [heap_free], ebx
2129 serge 306
           mov ecx, heap_mutex
307
           call mutex_unlock
308
           mov eax, [esi+block_base]
660 serge 309
           pop edi
310
           pop esi
311
           pop ebx
164 serge 312
           ret
313
.m_eq_size:
2154 serge 314
           list_del edi
315
           lea edx, [mem_block_list+ebx*8]
316
           cmp edx, [edx]
164 serge 317
           jnz @f
192 serge 318
           btr [mem_block_mask], ebx
164 serge 319
@@:
2154 serge 320
           mov ecx, mem_used.fd
357 serge 321
           mov edx, [ecx+list_fd]
322
           mov [edi+list_fd], edx
323
           mov [edi+list_bk], ecx
324
           mov [ecx+list_fd], edi
325
           mov [edx+list_bk], edi
326
 
164 serge 327
           mov [edi+block_flags], USED_BLOCK
170 serge 328
           mov ebx, [size]
329
           sub [heap_free], ebx
2129 serge 330
           mov ecx, heap_mutex
331
           call mutex_unlock
332
           mov eax, [edi+block_base]
660 serge 333
           pop edi
334
           pop esi
335
           pop ebx
164 serge 336
           ret
2154 serge 337
 
338
.error_unlock:
2129 serge 339
           mov ecx, heap_mutex
340
           call mutex_unlock
2154 serge 341
.error:
164 serge 342
           xor eax, eax
660 serge 343
           pop edi
344
           pop esi
345
           pop ebx
164 serge 346
           ret
347
endp
348
 
349
align 4
321 diamond 350
proc free_kernel_space stdcall uses ebx ecx edx esi edi, base:dword
279 serge 351
 
2129 serge 352
           mov ecx, heap_mutex
353
           call mutex_lock
354
 
164 serge 355
           mov eax, [base]
357 serge 356
           mov esi, [mem_used.fd]
164 serge 357
@@:
2154 serge 358
           cmp esi, mem_used.fd
357 serge 359
           je .fail
164 serge 360
 
361
           cmp [esi+block_base], eax
362
           je .found
357 serge 363
           mov esi, [esi+list_fd]
164 serge 364
           jmp @b
365
.found:
366
           cmp [esi+block_flags], USED_BLOCK
367
           jne .fail
368
 
170 serge 369
           mov eax, [esi+block_size]
370
           add [heap_free], eax
371
 
164 serge 372
           mov edi, [esi+block_next]
373
           cmp [edi+block_flags], FREE_BLOCK
374
           jne .prev
375
 
2154 serge 376
           list_del edi
164 serge 377
 
378
           mov edx, [edi+block_next]
379
           mov [esi+block_next], edx
380
           mov [edx+block_prev], esi
381
           mov ecx, [edi+block_size]
382
           add [esi+block_size], ecx
383
 
2154 serge 384
           calc_index ecx
385
 
386
           lea edx, [mem_block_list+ecx*8]
387
           cmp edx, [edx]
388
           jne @F
389
           btr [mem_block_mask], ecx
390
@@:
164 serge 391
           mov eax, edi
392
           call free_mem_block
393
.prev:
394
           mov edi, [esi+block_prev]
395
           cmp [edi+block_flags], FREE_BLOCK
396
           jne .insert
397
 
398
           remove_from_used esi
399
 
400
           mov edx, [esi+block_next]
401
           mov [edi+block_next], edx
402
           mov [edx+block_prev], edi
2154 serge 403
 
164 serge 404
           mov eax, esi
405
           call free_mem_block
406
 
407
           mov ecx, [edi+block_size]
408
           mov eax, [esi+block_size]
409
           add eax, ecx
410
           mov [edi+block_size], eax
411
 
2154 serge 412
           calc_index eax                     ;new index
413
           calc_index ecx                     ;old index
164 serge 414
           cmp eax, ecx
415
           je .m_eq
416
 
417
           push ecx
2154 serge 418
           list_del edi
164 serge 419
           pop ecx
420
 
2154 serge 421
           lea edx, [mem_block_list+ecx*8]
422
           cmp edx, [edx]
423
           jne .add_block
164 serge 424
           btr [mem_block_mask], ecx
2154 serge 425
.add_block:
164 serge 426
           bts [mem_block_mask], eax
2154 serge 427
           lea edx, [mem_block_list+eax*8]
428
           list_add edi, edx
164 serge 429
.m_eq:
2129 serge 430
           mov ecx, heap_mutex
431
           call mutex_unlock
164 serge 432
           xor eax, eax
2129 serge 433
           not eax
164 serge 434
           ret
435
.insert:
436
           remove_from_used esi
2154 serge 437
           mov [esi+block_flags], FREE_BLOCK
164 serge 438
           mov eax, [esi+block_size]
439
           calc_index eax
2154 serge 440
           mov edi, esi
441
           jmp .add_block
164 serge 442
 
443
.fail:
2129 serge 444
           mov ecx, heap_mutex
445
           call mutex_unlock
164 serge 446
           xor eax, eax
447
           ret
448
endp
449
 
450
align 4
451
proc kernel_alloc stdcall, size:dword
452
           locals
453
             lin_addr    dd ?
454
             pages_count dd ?
455
           endl
456
 
662 serge 457
           push ebx
458
           push edi
459
 
164 serge 460
           mov eax, [size]
206 serge 461
           add eax, 4095
462
           and eax, not 4095;
164 serge 463
           mov [size], eax
464
           and eax, eax
357 serge 465
           jz .err
164 serge 466
           mov ebx, eax
467
           shr ebx, 12
468
           mov [pages_count], ebx
469
 
470
           stdcall alloc_kernel_space, eax
357 serge 471
           test eax, eax
472
           jz .err
164 serge 473
           mov [lin_addr], eax
474
 
475
           mov ecx, [pages_count]
476
           mov edx, eax
477
           mov ebx, ecx
478
 
479
           shr ecx, 3
480
           jz .next
481
 
482
           and ebx, not 7
483
           push ebx
484
           stdcall alloc_pages, ebx
485
           pop ecx                   ; yes ecx!!!
486
           and eax, eax
357 serge 487
           jz .err
164 serge 488
 
489
           mov edi, eax
490
           mov edx, [lin_addr]
491
@@:
492
           stdcall map_page,edx,edi,dword PG_SW
493
           add edx, 0x1000
494
           add edi, 0x1000
495
           dec ecx
496
           jnz @B
497
.next:
498
           mov ecx, [pages_count]
499
           and ecx, 7
500
           jz .end
357 serge 501
@@:
502
           push ecx
164 serge 503
           call alloc_page
504
           pop ecx
505
           test eax, eax
357 serge 506
           jz .err
164 serge 507
 
508
           stdcall map_page,edx,eax,dword PG_SW
509
           add edx, 0x1000
510
           dec ecx
511
           jnz @B
512
.end:
513
           mov eax, [lin_addr]
662 serge 514
           pop edi
515
           pop ebx
164 serge 516
           ret
357 serge 517
.err:
164 serge 518
           xor eax, eax
662 serge 519
           pop edi
520
           pop ebx
164 serge 521
           ret
522
endp
523
 
524
align 4
525
proc kernel_free stdcall, base:dword
321 diamond 526
           push ebx esi
164 serge 527
 
2129 serge 528
           mov ecx, heap_mutex
529
           call mutex_lock
279 serge 530
 
164 serge 531
           mov eax, [base]
357 serge 532
           mov esi, [mem_used.fd]
164 serge 533
@@:
2154 serge 534
           cmp esi, mem_used.fd
357 serge 535
           je .fail
164 serge 536
 
537
           cmp [esi+block_base], eax
538
           je .found
357 serge 539
           mov esi, [esi+list_fd]
164 serge 540
           jmp @b
541
.found:
542
           cmp [esi+block_flags], USED_BLOCK
543
           jne .fail
544
 
2129 serge 545
           call mutex_unlock
279 serge 546
 
164 serge 547
           mov ecx, [esi+block_size];
281 serge 548
           shr ecx, 12
279 serge 549
           call release_pages   ;eax, ecx
164 serge 550
           stdcall free_kernel_space, [base]
321 diamond 551
           pop esi ebx
279 serge 552
           ret
164 serge 553
.fail:
2129 serge 554
           call mutex_unlock
1615 serge 555
           xor eax, eax
321 diamond 556
           pop esi ebx
164 serge 557
           ret
558
endp
559
 
560
restore block_next
561
restore block_prev
562
restore block_list
563
restore block_base
564
restore block_size
565
restore block_flags
566
 
567
;;;;;;;;;;;;;;      USER     ;;;;;;;;;;;;;;;;;
568
 
188 serge 569
HEAP_TOP  equ 0x5FC00000
570
 
164 serge 571
align 4
188 serge 572
proc init_heap
164 serge 573
 
465 serge 574
           mov ebx,[current_slot]
575
           mov eax, [ebx+APPDATA.heap_top]
172 serge 576
           test eax, eax
577
           jz @F
465 serge 578
           sub eax,[ebx+APPDATA.heap_base]
172 serge 579
           sub eax, 4096
580
           ret
581
@@:
465 serge 582
           mov esi, [ebx+APPDATA.mem_size]
188 serge 583
           add esi, 4095
584
           and esi, not 4095
465 serge 585
           mov [ebx+APPDATA.mem_size], esi
188 serge 586
           mov eax, HEAP_TOP
465 serge 587
           mov [ebx+APPDATA.heap_base], esi
588
           mov [ebx+APPDATA.heap_top], eax
164 serge 589
 
188 serge 590
           sub eax, esi
591
           shr esi, 10
592
           mov ecx, eax
164 serge 593
           sub eax, 4096
188 serge 594
           or ecx, FREE_BLOCK
365 serge 595
           mov [page_tabs+esi], ecx
164 serge 596
           ret
597
endp
598
 
599
align 4
600
proc user_alloc stdcall, alloc_size:dword
601
 
662 serge 602
           push ebx
603
           push esi
604
           push edi
605
 
164 serge 606
           mov ecx, [alloc_size]
607
           add ecx, (4095+4096)
608
           and ecx, not 4095
609
 
465 serge 610
           mov ebx, [current_slot]
611
           mov esi, dword [ebx+APPDATA.heap_base]  ; heap_base
612
           mov edi, dword [ebx+APPDATA.heap_top]   ; heap_top
164 serge 613
l_0:
614
           cmp esi, edi
615
           jae m_exit
616
 
617
           mov ebx, esi
618
           shr ebx, 12
365 serge 619
           mov eax, [page_tabs+ebx*4]
620 diamond 620
           test al, FREE_BLOCK
164 serge 621
           jz test_used
622
           and eax, 0xFFFFF000
623
           cmp eax, ecx    ;alloc_size
624
           jb  m_next
940 serge 625
           jz  @f
164 serge 626
 
620 diamond 627
           lea edx, [esi+ecx]
628
           sub eax, ecx
629
           or al, FREE_BLOCK
164 serge 630
           shr edx, 12
365 serge 631
           mov [page_tabs+edx*4], eax
294 diamond 632
@@:
164 serge 633
           or ecx, USED_BLOCK
365 serge 634
           mov [page_tabs+ebx*4], ecx
164 serge 635
           shr ecx, 12
620 diamond 636
           inc ebx
164 serge 637
           dec ecx
620 diamond 638
           jz  .no
164 serge 639
@@:
365 serge 640
           mov dword [page_tabs+ebx*4], 2
164 serge 641
           inc ebx
642
           dec ecx
643
           jnz @B
620 diamond 644
.no:
164 serge 645
 
465 serge 646
           mov     edx, [current_slot]
647
           mov     ebx, [alloc_size]
648
           add     ebx, 0xFFF
649
           and     ebx, not 0xFFF
650
           add     ebx, [edx+APPDATA.mem_size]
651
           call    update_mem_size
294 diamond 652
 
620 diamond 653
           lea eax, [esi+4096]
662 serge 654
 
655
           pop edi
656
           pop esi
657
           pop ebx
164 serge 658
           ret
659
test_used:
620 diamond 660
           test al, USED_BLOCK
164 serge 661
           jz m_exit
662
 
663
           and eax, 0xFFFFF000
620 diamond 664
m_next:
164 serge 665
           add esi, eax
666
           jmp l_0
667
m_exit:
668
           xor eax, eax
662 serge 669
           pop edi
670
           pop esi
671
           pop ebx
164 serge 672
           ret
673
endp
674
 
675
align 4
1289 diamond 676
proc user_alloc_at stdcall, address:dword, alloc_size:dword
677
 
678
           push ebx
679
           push esi
680
           push edi
681
 
682
           mov ebx, [current_slot]
683
           mov edx, [address]
684
           and edx, not 0xFFF
685
           mov [address], edx
686
           sub edx, 0x1000
687
           jb  .error
688
           mov esi, [ebx+APPDATA.heap_base]
689
           mov edi, [ebx+APPDATA.heap_top]
690
           cmp edx, esi
691
           jb  .error
692
.scan:
693
           cmp esi, edi
694
           jae .error
695
           mov ebx, esi
696
           shr ebx, 12
697
           mov eax, [page_tabs+ebx*4]
698
           mov ecx, eax
699
           and ecx, 0xFFFFF000
700
           add ecx, esi
701
           cmp edx, ecx
702
           jb  .found
703
           mov esi, ecx
704
           jmp .scan
705
.error:
706
           xor eax, eax
707
           pop edi
708
           pop esi
709
           pop ebx
710
           ret
711
.found:
712
           test al, FREE_BLOCK
713
           jz  .error
714
           mov eax, ecx
715
           sub eax, edx
716
           sub eax, 0x1000
717
           cmp eax, [alloc_size]
718
           jb  .error
719
 
720
; Here we have 1 big free block which includes requested area.
721
; In general, 3 other blocks must be created instead:
722
; free at [esi, edx);
723
; busy at [edx, edx+0x1000+ALIGN_UP(alloc_size,0x1000));
724
; free at [edx+0x1000+ALIGN_UP(alloc_size,0x1000), ecx)
725
; First or third block (or both) may be absent.
726
           mov eax, edx
727
           sub eax, esi
728
           jz  .nofirst
729
           or  al, FREE_BLOCK
730
           mov [page_tabs+ebx*4], eax
731
.nofirst:
732
           mov eax, [alloc_size]
733
           add eax, 0x1FFF
734
           and eax, not 0xFFF
735
           mov ebx, edx
736
           add edx, eax
737
           shr ebx, 12
738
           or  al, USED_BLOCK
739
           mov [page_tabs+ebx*4], eax
740
           shr eax, 12
741
           dec eax
742
           jz  .second_nofill
743
           inc ebx
744
.fill:
745
           mov dword [page_tabs+ebx*4], 2
746
           inc ebx
747
           dec eax
748
           jnz .fill
749
.second_nofill:
750
           sub ecx, edx
751
           jz  .nothird
752
           or  cl, FREE_BLOCK
753
           mov [page_tabs+ebx*4], ecx
754
.nothird:
755
 
756
           mov     edx, [current_slot]
757
           mov     ebx, [alloc_size]
758
           add     ebx, 0xFFF
759
           and     ebx, not 0xFFF
760
           add     ebx, [edx+APPDATA.mem_size]
761
           call    update_mem_size
762
 
763
           mov eax, [address]
764
 
765
           pop edi
766
           pop esi
767
           pop ebx
768
           ret
769
endp
770
 
771
align 4
164 serge 772
proc user_free stdcall, base:dword
773
 
662 serge 774
           push esi
775
 
164 serge 776
           mov esi, [base]
777
           test esi, esi
778
           jz .exit
779
 
662 serge 780
           push ebx
781
 
294 diamond 782
           xor ebx, ebx
164 serge 783
           shr esi, 12
620 diamond 784
           mov eax, [page_tabs+(esi-1)*4]
546 diamond 785
           test al, USED_BLOCK
620 diamond 786
           jz .cantfree
546 diamond 787
           test al, DONT_FREE_BLOCK
788
           jnz .cantfree
164 serge 789
 
790
           and eax, not 4095
791
           mov ecx, eax
620 diamond 792
           or al, FREE_BLOCK
793
           mov [page_tabs+(esi-1)*4], eax
164 serge 794
           sub ecx, 4096
620 diamond 795
           mov ebx, ecx
164 serge 796
           shr ecx, 12
620 diamond 797
           jz .released
164 serge 798
.release:
188 serge 799
           xor eax, eax
365 serge 800
           xchg eax, [page_tabs+esi*4]
620 diamond 801
           test al, 1
188 serge 802
           jz @F
940 serge 803
           test eax, PG_SHARED
804
           jnz @F
164 serge 805
           call free_page
448 diamond 806
           mov eax, esi
807
           shl eax, 12
808
           invlpg [eax]
188 serge 809
@@:
164 serge 810
           inc esi
811
           dec ecx
812
           jnz .release
620 diamond 813
.released:
662 serge 814
           push edi
815
 
465 serge 816
           mov edx, [current_slot]
817
           mov esi, dword [edx+APPDATA.heap_base]
818
           mov edi, dword [edx+APPDATA.heap_top]
819
           sub ebx, [edx+APPDATA.mem_size]
294 diamond 820
           neg ebx
821
           call update_mem_size
448 diamond 822
           call user_normalize
662 serge 823
           pop edi
824
           pop ebx
825
           pop esi
448 diamond 826
           ret
827
.exit:
828
           xor eax, eax
829
           inc eax
662 serge 830
           pop esi
448 diamond 831
           ret
546 diamond 832
.cantfree:
833
           xor eax, eax
662 serge 834
           pop ebx
835
           pop esi
546 diamond 836
           ret
448 diamond 837
endp
838
 
839
user_normalize:
840
; in: esi=heap_base, edi=heap_top
841
; out: eax=0 <=> OK
842
; destroys: ebx,edx,esi,edi
164 serge 843
           shr esi, 12
844
           shr edi, 12
845
@@:
365 serge 846
           mov eax, [page_tabs+esi*4]
620 diamond 847
           test al, USED_BLOCK
164 serge 848
           jz .test_free
849
           shr eax, 12
850
           add esi, eax
851
           jmp @B
852
.test_free:
620 diamond 853
           test al, FREE_BLOCK
164 serge 854
           jz .err
855
           mov edx, eax
856
           shr edx, 12
857
           add edx, esi
858
           cmp edx, edi
859
           jae .exit
860
 
365 serge 861
           mov ebx, [page_tabs+edx*4]
620 diamond 862
           test bl, USED_BLOCK
164 serge 863
           jz .next_free
864
 
865
           shr ebx, 12
866
           add edx, ebx
867
           mov esi, edx
868
           jmp @B
869
.next_free:
620 diamond 870
           test bl, FREE_BLOCK
164 serge 871
           jz .err
365 serge 872
           and dword [page_tabs+edx*4], 0
164 serge 873
           add eax, ebx
874
           and eax, not 4095
875
           or eax, FREE_BLOCK
365 serge 876
           mov [page_tabs+esi*4], eax
164 serge 877
           jmp @B
878
.exit:
879
           xor eax, eax
880
           inc eax
881
           ret
882
.err:
883
           xor eax, eax
884
           ret
885
 
448 diamond 886
user_realloc:
887
; in: eax = pointer, ebx = new size
888
; out: eax = new pointer or NULL
889
        test    eax, eax
890
        jnz     @f
891
; realloc(NULL,sz) - same as malloc(sz)
892
        push    ebx
893
        call    user_alloc
894
        ret
895
@@:
896
        push    ecx edx
465 serge 897
        lea     ecx, [eax - 0x1000]
448 diamond 898
        shr     ecx, 12
899
        mov     edx, [page_tabs+ecx*4]
620 diamond 900
        test    dl, USED_BLOCK
448 diamond 901
        jnz     @f
902
; attempt to realloc invalid pointer
903
.ret0:
904
        pop     edx ecx
905
        xor     eax, eax
906
        ret
907
@@:
620 diamond 908
        test    dl, DONT_FREE_BLOCK
546 diamond 909
        jnz     .ret0
448 diamond 910
        add     ebx, 0x1FFF
911
        shr     edx, 12
912
        shr     ebx, 12
913
; edx = allocated size, ebx = new size
914
        add     edx, ecx
915
        add     ebx, ecx
916
        cmp     edx, ebx
917
        jb      .realloc_add
918
; release part of allocated memory
919
.loop:
920
        cmp     edx, ebx
921
        jz      .release_done
922
        dec     edx
923
        xor     eax, eax
924
        xchg    eax, [page_tabs+edx*4]
925
        test    al, 1
926
        jz      .loop
927
        call    free_page
928
        mov     eax, edx
929
        shl     eax, 12
930
        invlpg  [eax]
931
        jmp     .loop
932
.release_done:
933
        sub     ebx, ecx
934
        cmp     ebx, 1
935
        jnz     .nofreeall
936
        mov     eax, [page_tabs+ecx*4]
937
        and     eax, not 0xFFF
465 serge 938
        mov     edx, [current_slot]
939
        mov     ebx, [APPDATA.mem_size+edx]
448 diamond 940
        sub     ebx, eax
941
        add     ebx, 0x1000
942
        or      al, FREE_BLOCK
943
        mov     [page_tabs+ecx*4], eax
944
        push    esi edi
465 serge 945
        mov     esi, [APPDATA.heap_base+edx]
946
        mov     edi, [APPDATA.heap_top+edx]
448 diamond 947
        call    update_mem_size
948
        call    user_normalize
949
        pop     edi esi
950
        jmp     .ret0   ; all freed
951
.nofreeall:
952
        sub     edx, ecx
953
        shl     ebx, 12
954
        or      ebx, USED_BLOCK
955
        xchg    [page_tabs+ecx*4], ebx
956
        shr     ebx, 12
957
        sub     ebx, edx
958
        push    ebx ecx edx
465 serge 959
        mov     edx, [current_slot]
448 diamond 960
        shl     ebx, 12
465 serge 961
        sub     ebx, [APPDATA.mem_size+edx]
448 diamond 962
        neg     ebx
963
        call    update_mem_size
964
        pop     edx ecx ebx
465 serge 965
        lea     eax, [ecx+1]
448 diamond 966
        shl     eax, 12
967
        push    eax
823 diamond 968
        add     ecx, edx
969
        lea     edx, [ecx+ebx]
448 diamond 970
        shl     ebx, 12
971
        jz      .ret
972
        push    esi
465 serge 973
        mov     esi, [current_slot]
974
        mov     esi, [APPDATA.heap_top+esi]
448 diamond 975
        shr     esi, 12
976
@@:
977
        cmp     edx, esi
978
        jae     .merge_done
979
        mov     eax, [page_tabs+edx*4]
980
        test    al, USED_BLOCK
823 diamond 981
        jnz     .merge_done
448 diamond 982
        and     dword [page_tabs+edx*4], 0
823 diamond 983
        shr     eax, 12
984
        add     edx, eax
985
        shl     eax, 12
448 diamond 986
        add     ebx, eax
987
        jmp     @b
988
.merge_done:
989
        pop     esi
990
        or      ebx, FREE_BLOCK
991
        mov     [page_tabs+ecx*4], ebx
992
.ret:
993
        pop     eax edx ecx
994
        ret
995
.realloc_add:
996
; get some additional memory
465 serge 997
        mov     eax, [current_slot]
998
        mov     eax, [APPDATA.heap_top+eax]
448 diamond 999
        shr     eax, 12
1000
        cmp     edx, eax
1001
        jae     .cant_inplace
1002
        mov     eax, [page_tabs+edx*4]
620 diamond 1003
        test    al, FREE_BLOCK
1004
        jz      .cant_inplace
448 diamond 1005
        shr     eax, 12
1006
        add     eax, edx
620 diamond 1007
        sub     eax, ebx
448 diamond 1008
        jb      .cant_inplace
1009
        jz      @f
1010
        shl     eax, 12
1011
        or      al, FREE_BLOCK
1012
        mov     [page_tabs+ebx*4], eax
1013
@@:
1014
        mov     eax, ebx
1015
        sub     eax, ecx
1016
        shl     eax, 12
1017
        or      al, USED_BLOCK
1018
        mov     [page_tabs+ecx*4], eax
465 serge 1019
        lea     eax, [ecx+1]
448 diamond 1020
        shl     eax, 12
1021
        push    eax
1022
        push    edi
1023
        lea     edi, [page_tabs+edx*4]
1024
        mov     eax, 2
1025
        sub     ebx, edx
1026
        mov     ecx, ebx
1027
        cld
1028
        rep     stosd
1029
        pop     edi
465 serge 1030
        mov     edx, [current_slot]
448 diamond 1031
        shl     ebx, 12
465 serge 1032
        add     ebx, [APPDATA.mem_size+edx]
448 diamond 1033
        call    update_mem_size
1034
        pop     eax edx ecx
1035
        ret
1036
.cant_inplace:
1037
        push    esi edi
465 serge 1038
        mov     eax, [current_slot]
1039
        mov     esi, [APPDATA.heap_base+eax]
1040
        mov     edi, [APPDATA.heap_top+eax]
448 diamond 1041
        shr     esi, 12
1042
        shr     edi, 12
1043
        sub     ebx, ecx
1044
.find_place:
1045
        cmp     esi, edi
1046
        jae     .place_not_found
1047
        mov     eax, [page_tabs+esi*4]
1048
        test    al, FREE_BLOCK
1049
        jz      .next_place
1050
        shr     eax, 12
1051
        cmp     eax, ebx
1052
        jae     .place_found
1053
        add     esi, eax
1054
        jmp     .find_place
1055
.next_place:
1056
        shr     eax, 12
1057
        add     esi, eax
1058
        jmp     .find_place
1059
.place_not_found:
1060
        pop     edi esi
1061
        jmp     .ret0
1062
.place_found:
1063
        sub     eax, ebx
1064
        jz      @f
1065
        push    esi
620 diamond 1066
        add     esi, ebx
448 diamond 1067
        shl     eax, 12
1068
        or      al, FREE_BLOCK
1069
        mov     [page_tabs+esi*4], eax
1070
        pop     esi
1071
@@:
1072
        mov     eax, ebx
1073
        shl     eax, 12
1074
        or      al, USED_BLOCK
1075
        mov     [page_tabs+esi*4], eax
1076
        inc     esi
1077
        mov     eax, esi
1078
        shl     eax, 12
1079
        push    eax
1080
        mov     eax, [page_tabs+ecx*4]
1081
        and     eax, not 0xFFF
1082
        or      al, FREE_BLOCK
1083
        sub     edx, ecx
1084
        mov     [page_tabs+ecx*4], eax
1085
        inc     ecx
620 diamond 1086
        dec     ebx
1087
        dec     edx
1088
        jz      .no
448 diamond 1089
@@:
1090
        xor     eax, eax
1091
        xchg    eax, [page_tabs+ecx*4]
1092
        mov     [page_tabs+esi*4], eax
940 serge 1093
        mov     eax, ecx
1094
        shl     eax, 12
1095
        invlpg  [eax]
620 diamond 1096
        inc     esi
448 diamond 1097
        inc     ecx
1098
        dec     ebx
1099
        dec     edx
1100
        jnz     @b
620 diamond 1101
.no:
448 diamond 1102
        push    ebx
465 serge 1103
        mov     edx, [current_slot]
448 diamond 1104
        shl     ebx, 12
465 serge 1105
        add     ebx, [APPDATA.mem_size+edx]
448 diamond 1106
        call    update_mem_size
1107
        pop     ebx
1108
@@:
1109
        mov     dword [page_tabs+esi*4], 2
1110
        inc     esi
1111
        dec     ebx
1112
        jnz     @b
1113
        pop     eax edi esi edx ecx
1114
        ret
1115
 
278 serge 1116
if 0
164 serge 1117
align 4
1118
proc alloc_dll
1119
           pushf
1120
           cli
1121
           bsf eax, [dll_map]
1122
           jnz .find
1123
           popf
1124
           xor eax, eax
1125
           ret
1126
.find:
1127
           btr [dll_map], eax
1128
           popf
1129
           shl eax, 5
1130
           add eax, dll_tab
1131
           ret
1132
endp
1133
 
1134
align 4
1135
proc alloc_service
1136
           pushf
1137
           cli
1138
           bsf eax, [srv_map]
1139
           jnz .find
1140
           popf
1141
           xor eax, eax
1142
           ret
214 serge 1143
.find:
1144
           btr [srv_map], eax
164 serge 1145
           popf
214 serge 1146
           shl eax,0x02
1147
           lea eax,[srv_tab+eax+eax*8]   ;srv_tab+eax*36
164 serge 1148
           ret
1149
endp
278 serge 1150
 
1151
end if
940 serge 1152
 
1153
 
1154
;;;;;;;;;;;;;;      SHARED      ;;;;;;;;;;;;;;;;;
1155
 
1156
 
1157
; param
1158
;  eax= shm_map object
1159
 
1160
align 4
1161
destroy_smap:
1162
 
1163
           pushfd
1164
           cli
1165
 
945 serge 1166
           push esi
1167
           push edi
940 serge 1168
 
945 serge 1169
           mov edi, eax
1170
           mov esi, [eax+SMAP.parent]
1171
           test esi, esi
1172
           jz .done
940 serge 1173
 
945 serge 1174
           lock dec [esi+SMEM.refcount]
1175
           jnz .done
940 serge 1176
 
945 serge 1177
           mov ecx, [esi+SMEM.bk]
1178
           mov edx, [esi+SMEM.fd]
1179
 
1180
           mov [ecx+SMEM.fd], edx
1181
           mov [edx+SMEM.bk], ecx
1182
 
1183
           stdcall kernel_free, [esi+SMEM.base]
1184
           mov eax, esi
1185
           call free
1186
.done:
1187
           mov eax, edi
940 serge 1188
           call destroy_kernel_object
1189
 
945 serge 1190
           pop edi
1191
           pop esi
940 serge 1192
           popfd
1193
 
1194
           ret
1195
 
1196
E_NOTFOUND      equ  5
1197
E_ACCESS        equ 10
1198
E_NOMEM         equ 30
1199
E_PARAM         equ 33
1200
 
1201
SHM_READ        equ 0
1202
SHM_WRITE       equ 1
1203
 
1204
SHM_ACCESS_MASK equ 3
1205
 
1206
SHM_OPEN        equ (0 shl 2)
1207
SHM_OPEN_ALWAYS equ (1 shl 2)
1208
SHM_CREATE      equ (2 shl 2)
1209
 
1210
SHM_OPEN_MASK   equ (3 shl 2)
1211
 
1212
align 4
1213
proc shmem_open stdcall name:dword, size:dword, access:dword
1214
           locals
1215
              action         dd ?
1216
              owner_access   dd ?
1217
              mapped         dd ?
1218
           endl
1219
 
1220
           push ebx
1221
           push esi
1222
           push edi
1223
 
1224
           mov [mapped], 0
1225
           mov [owner_access], 0
1226
 
1227
           pushfd                      ;mutex required
1228
           cli
1229
 
1230
           mov eax, [access]
1231
           and eax, SHM_OPEN_MASK
1232
           mov [action], eax
1233
 
1213 serge 1234
           mov ebx, [name]
1235
           test ebx, ebx
940 serge 1236
           mov edx, E_PARAM
1213 serge 1237
           jz .fail
940 serge 1238
 
1239
           mov esi, [shmem_list.fd]
1240
align 4
1241
@@:
1242
           cmp esi, shmem_list
1243
           je .not_found
1244
 
943 serge 1245
           lea edx, [esi+SMEM.name] ; link , base, size
1213 serge 1246
           stdcall strncmp, edx, ebx, 32
940 serge 1247
           test eax, eax
1248
           je .found
1249
 
943 serge 1250
           mov esi, [esi+SMEM.fd]
940 serge 1251
           jmp @B
1252
 
1253
.not_found:
1254
           mov eax, [action]
1255
 
1256
           cmp eax, SHM_OPEN
1257
           mov edx, E_NOTFOUND
1213 serge 1258
           je .fail
940 serge 1259
 
1260
           cmp eax, SHM_CREATE
1261
           mov edx, E_PARAM
1262
           je .create_shm
1263
 
1264
           cmp eax, SHM_OPEN_ALWAYS
1213 serge 1265
           jne .fail
940 serge 1266
 
1267
.create_shm:
1268
 
1269
           mov ecx, [size]
1270
           test ecx, ecx
1213 serge 1271
           jz .fail
940 serge 1272
 
1273
           add ecx, 4095
1274
           and ecx, -4096
1275
           mov [size], ecx
1276
 
943 serge 1277
           mov eax, SMEM.sizeof
940 serge 1278
           call malloc
1279
           test eax, eax
1280
           mov esi, eax
1281
           mov edx, E_NOMEM
1213 serge 1282
           jz .fail
940 serge 1283
 
1284
           stdcall kernel_alloc, [size]
1285
           test eax, eax
1286
           mov [mapped], eax
1287
           mov edx, E_NOMEM
1288
           jz .cleanup
1289
 
1290
           mov ecx, [size]
1291
           mov edx, [access]
1292
           and edx, SHM_ACCESS_MASK
1293
 
943 serge 1294
           mov [esi+SMEM.base], eax
1295
           mov [esi+SMEM.size], ecx
1296
           mov [esi+SMEM.access], edx
1297
           mov [esi+SMEM.refcount], 0
1298
           mov [esi+SMEM.name+28], 0
940 serge 1299
 
943 serge 1300
           lea eax, [esi+SMEM.name]
940 serge 1301
           stdcall strncpy, eax, [name], 31
1302
 
1303
           mov eax, [shmem_list.fd]
943 serge 1304
           mov [esi+SMEM.bk], shmem_list
1305
           mov [esi+SMEM.fd], eax
940 serge 1306
 
943 serge 1307
           mov [eax+SMEM.bk], esi
940 serge 1308
           mov [shmem_list.fd], esi
1309
 
1310
           mov [action], SHM_OPEN
1311
           mov [owner_access], SHM_WRITE
1312
 
1313
.found:
1314
           mov eax, [action]
1315
 
1316
           cmp eax, SHM_CREATE
1317
           mov edx, E_ACCESS
1318
           je .exit
1319
 
1320
           cmp eax, SHM_OPEN
1321
           mov edx, E_PARAM
1322
           je .create_map
1323
 
1324
           cmp eax, SHM_OPEN_ALWAYS
1213 serge 1325
           jne .fail
940 serge 1326
 
1327
.create_map:
1328
 
1329
           mov eax, [access]
1330
           and eax, SHM_ACCESS_MASK
943 serge 1331
           cmp eax, [esi+SMEM.access]
940 serge 1332
           mov [access], eax
1333
           mov edx, E_ACCESS
1213 serge 1334
           ja .fail
940 serge 1335
 
1336
           mov ebx, [CURRENT_TASK]
1337
           shl ebx, 5
1338
           mov ebx, [CURRENT_TASK+ebx+4]
943 serge 1339
           mov eax, SMAP.sizeof
940 serge 1340
 
1341
           call create_kernel_object
1342
           test eax, eax
1343
           mov edi, eax
1344
           mov edx, E_NOMEM
1213 serge 1345
           jz .fail
940 serge 1346
 
1213 serge 1347
           inc [esi+SMEM.refcount]
1348
 
943 serge 1349
           mov [edi+SMAP.magic], 'SMAP'
1350
           mov [edi+SMAP.destroy], destroy_smap
1213 serge 1351
           mov [edi+SMAP.parent], esi
943 serge 1352
           mov [edi+SMAP.base], 0
940 serge 1353
 
943 serge 1354
           stdcall user_alloc, [esi+SMEM.size]
940 serge 1355
           test eax, eax
1356
           mov [mapped], eax
1357
           mov edx, E_NOMEM
1358
           jz .cleanup2
1359
 
943 serge 1360
           mov [edi+SMAP.base], eax
940 serge 1361
 
943 serge 1362
           mov ecx, [esi+SMEM.size]
940 serge 1363
           mov [size], ecx
1364
 
1365
           shr ecx, 12
1366
           shr eax, 10
1367
 
943 serge 1368
           mov esi, [esi+SMEM.base]
940 serge 1369
           shr esi, 10
1370
           lea edi, [page_tabs+eax]
1371
           add esi, page_tabs
1372
 
1373
           mov edx, [access]
1374
           or edx, [owner_access]
1375
           shl edx, 1
1376
           or edx, PG_USER+PG_SHARED
1377
@@:
1378
           lodsd
1379
           and eax, 0xFFFFF000
1380
           or eax, edx
1381
           stosd
1382
           loop @B
1383
 
1384
           xor edx, edx
1385
 
1386
           cmp [owner_access], 0
1213 serge 1387
           jne .fail
1388
.exit:
940 serge 1389
           mov edx, [size]
1213 serge 1390
.fail:
940 serge 1391
           mov eax, [mapped]
1392
 
1393
           popfd
1394
           pop edi
1395
           pop esi
1396
           pop ebx
1397
           ret
1398
.cleanup:
1213 serge 1399
           mov [size], edx
940 serge 1400
           mov eax, esi
1401
           call free
1402
           jmp .exit
1403
 
1404
.cleanup2:
1213 serge 1405
           mov [size], edx
940 serge 1406
           mov eax, edi
1407
           call destroy_smap
1408
           jmp .exit
1409
endp
943 serge 1410
 
1411
align 4
1412
proc shmem_close stdcall, name:dword
1413
 
1414
           mov eax, [name]
1415
           test eax, eax
1416
           jz .fail
1417
 
1418
           push esi
1419
           push edi
945 serge 1420
           pushfd
1421
           cli
943 serge 1422
 
1423
           mov esi, [current_slot]
1424
           add esi, APP_OBJ_OFFSET
1425
.next:
1426
           mov eax, [esi+APPOBJ.fd]
1427
           test eax, eax
1428
           jz @F
1429
 
1430
           cmp eax, esi
1431
           mov esi, eax
1432
           je @F
1433
 
1434
           cmp [eax+SMAP.magic], 'SMAP'
1435
           jne .next
1436
 
1437
           mov edi, [eax+SMAP.parent]
1438
           test edi, edi
1439
           jz .next
1440
 
1501 mario79 1441
           lea edi, [edi+SMEM.name]
943 serge 1442
           stdcall strncmp, [name], edi, 32
1443
           test eax, eax
1444
           jne .next
1445
 
945 serge 1446
           stdcall user_free, [esi+SMAP.base]
1447
 
1501 mario79 1448
           mov eax,esi
943 serge 1449
           call [esi+APPOBJ.destroy]
1450
@@:
945 serge 1451
           popfd
943 serge 1452
           pop edi
1453
           pop esi
1454
.fail:
1455
           ret
1456
endp