Subversion Repositories Kolibri OS

Rev

Rev 2154 | 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: 2164 $
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
 
2164 serge 547
           mov eax, [esi+block_base]
548
           mov ecx, [esi+block_size]
281 serge 549
           shr ecx, 12
279 serge 550
           call release_pages   ;eax, ecx
164 serge 551
           stdcall free_kernel_space, [base]
321 diamond 552
           pop esi ebx
279 serge 553
           ret
164 serge 554
.fail:
2129 serge 555
           call mutex_unlock
1615 serge 556
           xor eax, eax
321 diamond 557
           pop esi ebx
164 serge 558
           ret
559
endp
560
 
561
restore block_next
562
restore block_prev
563
restore block_list
564
restore block_base
565
restore block_size
566
restore block_flags
567
 
568
;;;;;;;;;;;;;;      USER     ;;;;;;;;;;;;;;;;;
569
 
188 serge 570
HEAP_TOP  equ 0x5FC00000
571
 
164 serge 572
align 4
188 serge 573
proc init_heap
164 serge 574
 
465 serge 575
           mov ebx,[current_slot]
576
           mov eax, [ebx+APPDATA.heap_top]
172 serge 577
           test eax, eax
578
           jz @F
465 serge 579
           sub eax,[ebx+APPDATA.heap_base]
172 serge 580
           sub eax, 4096
581
           ret
582
@@:
465 serge 583
           mov esi, [ebx+APPDATA.mem_size]
188 serge 584
           add esi, 4095
585
           and esi, not 4095
465 serge 586
           mov [ebx+APPDATA.mem_size], esi
188 serge 587
           mov eax, HEAP_TOP
465 serge 588
           mov [ebx+APPDATA.heap_base], esi
589
           mov [ebx+APPDATA.heap_top], eax
164 serge 590
 
188 serge 591
           sub eax, esi
592
           shr esi, 10
593
           mov ecx, eax
164 serge 594
           sub eax, 4096
188 serge 595
           or ecx, FREE_BLOCK
365 serge 596
           mov [page_tabs+esi], ecx
164 serge 597
           ret
598
endp
599
 
600
align 4
601
proc user_alloc stdcall, alloc_size:dword
602
 
662 serge 603
           push ebx
604
           push esi
605
           push edi
606
 
164 serge 607
           mov ecx, [alloc_size]
608
           add ecx, (4095+4096)
609
           and ecx, not 4095
610
 
465 serge 611
           mov ebx, [current_slot]
612
           mov esi, dword [ebx+APPDATA.heap_base]  ; heap_base
613
           mov edi, dword [ebx+APPDATA.heap_top]   ; heap_top
164 serge 614
l_0:
615
           cmp esi, edi
616
           jae m_exit
617
 
618
           mov ebx, esi
619
           shr ebx, 12
365 serge 620
           mov eax, [page_tabs+ebx*4]
620 diamond 621
           test al, FREE_BLOCK
164 serge 622
           jz test_used
623
           and eax, 0xFFFFF000
624
           cmp eax, ecx    ;alloc_size
625
           jb  m_next
940 serge 626
           jz  @f
164 serge 627
 
620 diamond 628
           lea edx, [esi+ecx]
629
           sub eax, ecx
630
           or al, FREE_BLOCK
164 serge 631
           shr edx, 12
365 serge 632
           mov [page_tabs+edx*4], eax
294 diamond 633
@@:
164 serge 634
           or ecx, USED_BLOCK
365 serge 635
           mov [page_tabs+ebx*4], ecx
164 serge 636
           shr ecx, 12
620 diamond 637
           inc ebx
164 serge 638
           dec ecx
620 diamond 639
           jz  .no
164 serge 640
@@:
365 serge 641
           mov dword [page_tabs+ebx*4], 2
164 serge 642
           inc ebx
643
           dec ecx
644
           jnz @B
620 diamond 645
.no:
164 serge 646
 
465 serge 647
           mov     edx, [current_slot]
648
           mov     ebx, [alloc_size]
649
           add     ebx, 0xFFF
650
           and     ebx, not 0xFFF
651
           add     ebx, [edx+APPDATA.mem_size]
652
           call    update_mem_size
294 diamond 653
 
620 diamond 654
           lea eax, [esi+4096]
662 serge 655
 
656
           pop edi
657
           pop esi
658
           pop ebx
164 serge 659
           ret
660
test_used:
620 diamond 661
           test al, USED_BLOCK
164 serge 662
           jz m_exit
663
 
664
           and eax, 0xFFFFF000
620 diamond 665
m_next:
164 serge 666
           add esi, eax
667
           jmp l_0
668
m_exit:
669
           xor eax, eax
662 serge 670
           pop edi
671
           pop esi
672
           pop ebx
164 serge 673
           ret
674
endp
675
 
676
align 4
1289 diamond 677
proc user_alloc_at stdcall, address:dword, alloc_size:dword
678
 
679
           push ebx
680
           push esi
681
           push edi
682
 
683
           mov ebx, [current_slot]
684
           mov edx, [address]
685
           and edx, not 0xFFF
686
           mov [address], edx
687
           sub edx, 0x1000
688
           jb  .error
689
           mov esi, [ebx+APPDATA.heap_base]
690
           mov edi, [ebx+APPDATA.heap_top]
691
           cmp edx, esi
692
           jb  .error
693
.scan:
694
           cmp esi, edi
695
           jae .error
696
           mov ebx, esi
697
           shr ebx, 12
698
           mov eax, [page_tabs+ebx*4]
699
           mov ecx, eax
700
           and ecx, 0xFFFFF000
701
           add ecx, esi
702
           cmp edx, ecx
703
           jb  .found
704
           mov esi, ecx
705
           jmp .scan
706
.error:
707
           xor eax, eax
708
           pop edi
709
           pop esi
710
           pop ebx
711
           ret
712
.found:
713
           test al, FREE_BLOCK
714
           jz  .error
715
           mov eax, ecx
716
           sub eax, edx
717
           sub eax, 0x1000
718
           cmp eax, [alloc_size]
719
           jb  .error
720
 
721
; Here we have 1 big free block which includes requested area.
722
; In general, 3 other blocks must be created instead:
723
; free at [esi, edx);
724
; busy at [edx, edx+0x1000+ALIGN_UP(alloc_size,0x1000));
725
; free at [edx+0x1000+ALIGN_UP(alloc_size,0x1000), ecx)
726
; First or third block (or both) may be absent.
727
           mov eax, edx
728
           sub eax, esi
729
           jz  .nofirst
730
           or  al, FREE_BLOCK
731
           mov [page_tabs+ebx*4], eax
732
.nofirst:
733
           mov eax, [alloc_size]
734
           add eax, 0x1FFF
735
           and eax, not 0xFFF
736
           mov ebx, edx
737
           add edx, eax
738
           shr ebx, 12
739
           or  al, USED_BLOCK
740
           mov [page_tabs+ebx*4], eax
741
           shr eax, 12
742
           dec eax
743
           jz  .second_nofill
744
           inc ebx
745
.fill:
746
           mov dword [page_tabs+ebx*4], 2
747
           inc ebx
748
           dec eax
749
           jnz .fill
750
.second_nofill:
751
           sub ecx, edx
752
           jz  .nothird
753
           or  cl, FREE_BLOCK
754
           mov [page_tabs+ebx*4], ecx
755
.nothird:
756
 
757
           mov     edx, [current_slot]
758
           mov     ebx, [alloc_size]
759
           add     ebx, 0xFFF
760
           and     ebx, not 0xFFF
761
           add     ebx, [edx+APPDATA.mem_size]
762
           call    update_mem_size
763
 
764
           mov eax, [address]
765
 
766
           pop edi
767
           pop esi
768
           pop ebx
769
           ret
770
endp
771
 
772
align 4
164 serge 773
proc user_free stdcall, base:dword
774
 
662 serge 775
           push esi
776
 
164 serge 777
           mov esi, [base]
778
           test esi, esi
779
           jz .exit
780
 
662 serge 781
           push ebx
782
 
294 diamond 783
           xor ebx, ebx
164 serge 784
           shr esi, 12
620 diamond 785
           mov eax, [page_tabs+(esi-1)*4]
546 diamond 786
           test al, USED_BLOCK
620 diamond 787
           jz .cantfree
546 diamond 788
           test al, DONT_FREE_BLOCK
789
           jnz .cantfree
164 serge 790
 
791
           and eax, not 4095
792
           mov ecx, eax
620 diamond 793
           or al, FREE_BLOCK
794
           mov [page_tabs+(esi-1)*4], eax
164 serge 795
           sub ecx, 4096
620 diamond 796
           mov ebx, ecx
164 serge 797
           shr ecx, 12
620 diamond 798
           jz .released
164 serge 799
.release:
188 serge 800
           xor eax, eax
365 serge 801
           xchg eax, [page_tabs+esi*4]
620 diamond 802
           test al, 1
188 serge 803
           jz @F
940 serge 804
           test eax, PG_SHARED
805
           jnz @F
164 serge 806
           call free_page
448 diamond 807
           mov eax, esi
808
           shl eax, 12
809
           invlpg [eax]
188 serge 810
@@:
164 serge 811
           inc esi
812
           dec ecx
813
           jnz .release
620 diamond 814
.released:
662 serge 815
           push edi
816
 
465 serge 817
           mov edx, [current_slot]
818
           mov esi, dword [edx+APPDATA.heap_base]
819
           mov edi, dword [edx+APPDATA.heap_top]
820
           sub ebx, [edx+APPDATA.mem_size]
294 diamond 821
           neg ebx
822
           call update_mem_size
448 diamond 823
           call user_normalize
662 serge 824
           pop edi
825
           pop ebx
826
           pop esi
448 diamond 827
           ret
828
.exit:
829
           xor eax, eax
830
           inc eax
662 serge 831
           pop esi
448 diamond 832
           ret
546 diamond 833
.cantfree:
834
           xor eax, eax
662 serge 835
           pop ebx
836
           pop esi
546 diamond 837
           ret
448 diamond 838
endp
839
 
840
user_normalize:
841
; in: esi=heap_base, edi=heap_top
842
; out: eax=0 <=> OK
843
; destroys: ebx,edx,esi,edi
164 serge 844
           shr esi, 12
845
           shr edi, 12
846
@@:
365 serge 847
           mov eax, [page_tabs+esi*4]
620 diamond 848
           test al, USED_BLOCK
164 serge 849
           jz .test_free
850
           shr eax, 12
851
           add esi, eax
852
           jmp @B
853
.test_free:
620 diamond 854
           test al, FREE_BLOCK
164 serge 855
           jz .err
856
           mov edx, eax
857
           shr edx, 12
858
           add edx, esi
859
           cmp edx, edi
860
           jae .exit
861
 
365 serge 862
           mov ebx, [page_tabs+edx*4]
620 diamond 863
           test bl, USED_BLOCK
164 serge 864
           jz .next_free
865
 
866
           shr ebx, 12
867
           add edx, ebx
868
           mov esi, edx
869
           jmp @B
870
.next_free:
620 diamond 871
           test bl, FREE_BLOCK
164 serge 872
           jz .err
365 serge 873
           and dword [page_tabs+edx*4], 0
164 serge 874
           add eax, ebx
875
           and eax, not 4095
876
           or eax, FREE_BLOCK
365 serge 877
           mov [page_tabs+esi*4], eax
164 serge 878
           jmp @B
879
.exit:
880
           xor eax, eax
881
           inc eax
882
           ret
883
.err:
884
           xor eax, eax
885
           ret
886
 
448 diamond 887
user_realloc:
888
; in: eax = pointer, ebx = new size
889
; out: eax = new pointer or NULL
890
        test    eax, eax
891
        jnz     @f
892
; realloc(NULL,sz) - same as malloc(sz)
893
        push    ebx
894
        call    user_alloc
895
        ret
896
@@:
897
        push    ecx edx
465 serge 898
        lea     ecx, [eax - 0x1000]
448 diamond 899
        shr     ecx, 12
900
        mov     edx, [page_tabs+ecx*4]
620 diamond 901
        test    dl, USED_BLOCK
448 diamond 902
        jnz     @f
903
; attempt to realloc invalid pointer
904
.ret0:
905
        pop     edx ecx
906
        xor     eax, eax
907
        ret
908
@@:
620 diamond 909
        test    dl, DONT_FREE_BLOCK
546 diamond 910
        jnz     .ret0
448 diamond 911
        add     ebx, 0x1FFF
912
        shr     edx, 12
913
        shr     ebx, 12
914
; edx = allocated size, ebx = new size
915
        add     edx, ecx
916
        add     ebx, ecx
917
        cmp     edx, ebx
918
        jb      .realloc_add
919
; release part of allocated memory
920
.loop:
921
        cmp     edx, ebx
922
        jz      .release_done
923
        dec     edx
924
        xor     eax, eax
925
        xchg    eax, [page_tabs+edx*4]
926
        test    al, 1
927
        jz      .loop
928
        call    free_page
929
        mov     eax, edx
930
        shl     eax, 12
931
        invlpg  [eax]
932
        jmp     .loop
933
.release_done:
934
        sub     ebx, ecx
935
        cmp     ebx, 1
936
        jnz     .nofreeall
937
        mov     eax, [page_tabs+ecx*4]
938
        and     eax, not 0xFFF
465 serge 939
        mov     edx, [current_slot]
940
        mov     ebx, [APPDATA.mem_size+edx]
448 diamond 941
        sub     ebx, eax
942
        add     ebx, 0x1000
943
        or      al, FREE_BLOCK
944
        mov     [page_tabs+ecx*4], eax
945
        push    esi edi
465 serge 946
        mov     esi, [APPDATA.heap_base+edx]
947
        mov     edi, [APPDATA.heap_top+edx]
448 diamond 948
        call    update_mem_size
949
        call    user_normalize
950
        pop     edi esi
951
        jmp     .ret0   ; all freed
952
.nofreeall:
953
        sub     edx, ecx
954
        shl     ebx, 12
955
        or      ebx, USED_BLOCK
956
        xchg    [page_tabs+ecx*4], ebx
957
        shr     ebx, 12
958
        sub     ebx, edx
959
        push    ebx ecx edx
465 serge 960
        mov     edx, [current_slot]
448 diamond 961
        shl     ebx, 12
465 serge 962
        sub     ebx, [APPDATA.mem_size+edx]
448 diamond 963
        neg     ebx
964
        call    update_mem_size
965
        pop     edx ecx ebx
465 serge 966
        lea     eax, [ecx+1]
448 diamond 967
        shl     eax, 12
968
        push    eax
823 diamond 969
        add     ecx, edx
970
        lea     edx, [ecx+ebx]
448 diamond 971
        shl     ebx, 12
972
        jz      .ret
973
        push    esi
465 serge 974
        mov     esi, [current_slot]
975
        mov     esi, [APPDATA.heap_top+esi]
448 diamond 976
        shr     esi, 12
977
@@:
978
        cmp     edx, esi
979
        jae     .merge_done
980
        mov     eax, [page_tabs+edx*4]
981
        test    al, USED_BLOCK
823 diamond 982
        jnz     .merge_done
448 diamond 983
        and     dword [page_tabs+edx*4], 0
823 diamond 984
        shr     eax, 12
985
        add     edx, eax
986
        shl     eax, 12
448 diamond 987
        add     ebx, eax
988
        jmp     @b
989
.merge_done:
990
        pop     esi
991
        or      ebx, FREE_BLOCK
992
        mov     [page_tabs+ecx*4], ebx
993
.ret:
994
        pop     eax edx ecx
995
        ret
996
.realloc_add:
997
; get some additional memory
465 serge 998
        mov     eax, [current_slot]
999
        mov     eax, [APPDATA.heap_top+eax]
448 diamond 1000
        shr     eax, 12
1001
        cmp     edx, eax
1002
        jae     .cant_inplace
1003
        mov     eax, [page_tabs+edx*4]
620 diamond 1004
        test    al, FREE_BLOCK
1005
        jz      .cant_inplace
448 diamond 1006
        shr     eax, 12
1007
        add     eax, edx
620 diamond 1008
        sub     eax, ebx
448 diamond 1009
        jb      .cant_inplace
1010
        jz      @f
1011
        shl     eax, 12
1012
        or      al, FREE_BLOCK
1013
        mov     [page_tabs+ebx*4], eax
1014
@@:
1015
        mov     eax, ebx
1016
        sub     eax, ecx
1017
        shl     eax, 12
1018
        or      al, USED_BLOCK
1019
        mov     [page_tabs+ecx*4], eax
465 serge 1020
        lea     eax, [ecx+1]
448 diamond 1021
        shl     eax, 12
1022
        push    eax
1023
        push    edi
1024
        lea     edi, [page_tabs+edx*4]
1025
        mov     eax, 2
1026
        sub     ebx, edx
1027
        mov     ecx, ebx
1028
        cld
1029
        rep     stosd
1030
        pop     edi
465 serge 1031
        mov     edx, [current_slot]
448 diamond 1032
        shl     ebx, 12
465 serge 1033
        add     ebx, [APPDATA.mem_size+edx]
448 diamond 1034
        call    update_mem_size
1035
        pop     eax edx ecx
1036
        ret
1037
.cant_inplace:
1038
        push    esi edi
465 serge 1039
        mov     eax, [current_slot]
1040
        mov     esi, [APPDATA.heap_base+eax]
1041
        mov     edi, [APPDATA.heap_top+eax]
448 diamond 1042
        shr     esi, 12
1043
        shr     edi, 12
1044
        sub     ebx, ecx
1045
.find_place:
1046
        cmp     esi, edi
1047
        jae     .place_not_found
1048
        mov     eax, [page_tabs+esi*4]
1049
        test    al, FREE_BLOCK
1050
        jz      .next_place
1051
        shr     eax, 12
1052
        cmp     eax, ebx
1053
        jae     .place_found
1054
        add     esi, eax
1055
        jmp     .find_place
1056
.next_place:
1057
        shr     eax, 12
1058
        add     esi, eax
1059
        jmp     .find_place
1060
.place_not_found:
1061
        pop     edi esi
1062
        jmp     .ret0
1063
.place_found:
1064
        sub     eax, ebx
1065
        jz      @f
1066
        push    esi
620 diamond 1067
        add     esi, ebx
448 diamond 1068
        shl     eax, 12
1069
        or      al, FREE_BLOCK
1070
        mov     [page_tabs+esi*4], eax
1071
        pop     esi
1072
@@:
1073
        mov     eax, ebx
1074
        shl     eax, 12
1075
        or      al, USED_BLOCK
1076
        mov     [page_tabs+esi*4], eax
1077
        inc     esi
1078
        mov     eax, esi
1079
        shl     eax, 12
1080
        push    eax
1081
        mov     eax, [page_tabs+ecx*4]
1082
        and     eax, not 0xFFF
1083
        or      al, FREE_BLOCK
1084
        sub     edx, ecx
1085
        mov     [page_tabs+ecx*4], eax
1086
        inc     ecx
620 diamond 1087
        dec     ebx
1088
        dec     edx
1089
        jz      .no
448 diamond 1090
@@:
1091
        xor     eax, eax
1092
        xchg    eax, [page_tabs+ecx*4]
1093
        mov     [page_tabs+esi*4], eax
940 serge 1094
        mov     eax, ecx
1095
        shl     eax, 12
1096
        invlpg  [eax]
620 diamond 1097
        inc     esi
448 diamond 1098
        inc     ecx
1099
        dec     ebx
1100
        dec     edx
1101
        jnz     @b
620 diamond 1102
.no:
448 diamond 1103
        push    ebx
465 serge 1104
        mov     edx, [current_slot]
448 diamond 1105
        shl     ebx, 12
465 serge 1106
        add     ebx, [APPDATA.mem_size+edx]
448 diamond 1107
        call    update_mem_size
1108
        pop     ebx
1109
@@:
1110
        mov     dword [page_tabs+esi*4], 2
1111
        inc     esi
1112
        dec     ebx
1113
        jnz     @b
1114
        pop     eax edi esi edx ecx
1115
        ret
1116
 
278 serge 1117
if 0
164 serge 1118
align 4
1119
proc alloc_dll
1120
           pushf
1121
           cli
1122
           bsf eax, [dll_map]
1123
           jnz .find
1124
           popf
1125
           xor eax, eax
1126
           ret
1127
.find:
1128
           btr [dll_map], eax
1129
           popf
1130
           shl eax, 5
1131
           add eax, dll_tab
1132
           ret
1133
endp
1134
 
1135
align 4
1136
proc alloc_service
1137
           pushf
1138
           cli
1139
           bsf eax, [srv_map]
1140
           jnz .find
1141
           popf
1142
           xor eax, eax
1143
           ret
214 serge 1144
.find:
1145
           btr [srv_map], eax
164 serge 1146
           popf
214 serge 1147
           shl eax,0x02
1148
           lea eax,[srv_tab+eax+eax*8]   ;srv_tab+eax*36
164 serge 1149
           ret
1150
endp
278 serge 1151
 
1152
end if
940 serge 1153
 
1154
 
1155
;;;;;;;;;;;;;;      SHARED      ;;;;;;;;;;;;;;;;;
1156
 
1157
 
1158
; param
1159
;  eax= shm_map object
1160
 
1161
align 4
1162
destroy_smap:
1163
 
1164
           pushfd
1165
           cli
1166
 
945 serge 1167
           push esi
1168
           push edi
940 serge 1169
 
945 serge 1170
           mov edi, eax
1171
           mov esi, [eax+SMAP.parent]
1172
           test esi, esi
1173
           jz .done
940 serge 1174
 
945 serge 1175
           lock dec [esi+SMEM.refcount]
1176
           jnz .done
940 serge 1177
 
945 serge 1178
           mov ecx, [esi+SMEM.bk]
1179
           mov edx, [esi+SMEM.fd]
1180
 
1181
           mov [ecx+SMEM.fd], edx
1182
           mov [edx+SMEM.bk], ecx
1183
 
1184
           stdcall kernel_free, [esi+SMEM.base]
1185
           mov eax, esi
1186
           call free
1187
.done:
1188
           mov eax, edi
940 serge 1189
           call destroy_kernel_object
1190
 
945 serge 1191
           pop edi
1192
           pop esi
940 serge 1193
           popfd
1194
 
1195
           ret
1196
 
1197
E_NOTFOUND      equ  5
1198
E_ACCESS        equ 10
1199
E_NOMEM         equ 30
1200
E_PARAM         equ 33
1201
 
1202
SHM_READ        equ 0
1203
SHM_WRITE       equ 1
1204
 
1205
SHM_ACCESS_MASK equ 3
1206
 
1207
SHM_OPEN        equ (0 shl 2)
1208
SHM_OPEN_ALWAYS equ (1 shl 2)
1209
SHM_CREATE      equ (2 shl 2)
1210
 
1211
SHM_OPEN_MASK   equ (3 shl 2)
1212
 
1213
align 4
1214
proc shmem_open stdcall name:dword, size:dword, access:dword
1215
           locals
1216
              action         dd ?
1217
              owner_access   dd ?
1218
              mapped         dd ?
1219
           endl
1220
 
1221
           push ebx
1222
           push esi
1223
           push edi
1224
 
1225
           mov [mapped], 0
1226
           mov [owner_access], 0
1227
 
1228
           pushfd                      ;mutex required
1229
           cli
1230
 
1231
           mov eax, [access]
1232
           and eax, SHM_OPEN_MASK
1233
           mov [action], eax
1234
 
1213 serge 1235
           mov ebx, [name]
1236
           test ebx, ebx
940 serge 1237
           mov edx, E_PARAM
1213 serge 1238
           jz .fail
940 serge 1239
 
1240
           mov esi, [shmem_list.fd]
1241
align 4
1242
@@:
1243
           cmp esi, shmem_list
1244
           je .not_found
1245
 
943 serge 1246
           lea edx, [esi+SMEM.name] ; link , base, size
1213 serge 1247
           stdcall strncmp, edx, ebx, 32
940 serge 1248
           test eax, eax
1249
           je .found
1250
 
943 serge 1251
           mov esi, [esi+SMEM.fd]
940 serge 1252
           jmp @B
1253
 
1254
.not_found:
1255
           mov eax, [action]
1256
 
1257
           cmp eax, SHM_OPEN
1258
           mov edx, E_NOTFOUND
1213 serge 1259
           je .fail
940 serge 1260
 
1261
           cmp eax, SHM_CREATE
1262
           mov edx, E_PARAM
1263
           je .create_shm
1264
 
1265
           cmp eax, SHM_OPEN_ALWAYS
1213 serge 1266
           jne .fail
940 serge 1267
 
1268
.create_shm:
1269
 
1270
           mov ecx, [size]
1271
           test ecx, ecx
1213 serge 1272
           jz .fail
940 serge 1273
 
1274
           add ecx, 4095
1275
           and ecx, -4096
1276
           mov [size], ecx
1277
 
943 serge 1278
           mov eax, SMEM.sizeof
940 serge 1279
           call malloc
1280
           test eax, eax
1281
           mov esi, eax
1282
           mov edx, E_NOMEM
1213 serge 1283
           jz .fail
940 serge 1284
 
1285
           stdcall kernel_alloc, [size]
1286
           test eax, eax
1287
           mov [mapped], eax
1288
           mov edx, E_NOMEM
1289
           jz .cleanup
1290
 
1291
           mov ecx, [size]
1292
           mov edx, [access]
1293
           and edx, SHM_ACCESS_MASK
1294
 
943 serge 1295
           mov [esi+SMEM.base], eax
1296
           mov [esi+SMEM.size], ecx
1297
           mov [esi+SMEM.access], edx
1298
           mov [esi+SMEM.refcount], 0
1299
           mov [esi+SMEM.name+28], 0
940 serge 1300
 
943 serge 1301
           lea eax, [esi+SMEM.name]
940 serge 1302
           stdcall strncpy, eax, [name], 31
1303
 
1304
           mov eax, [shmem_list.fd]
943 serge 1305
           mov [esi+SMEM.bk], shmem_list
1306
           mov [esi+SMEM.fd], eax
940 serge 1307
 
943 serge 1308
           mov [eax+SMEM.bk], esi
940 serge 1309
           mov [shmem_list.fd], esi
1310
 
1311
           mov [action], SHM_OPEN
1312
           mov [owner_access], SHM_WRITE
1313
 
1314
.found:
1315
           mov eax, [action]
1316
 
1317
           cmp eax, SHM_CREATE
1318
           mov edx, E_ACCESS
1319
           je .exit
1320
 
1321
           cmp eax, SHM_OPEN
1322
           mov edx, E_PARAM
1323
           je .create_map
1324
 
1325
           cmp eax, SHM_OPEN_ALWAYS
1213 serge 1326
           jne .fail
940 serge 1327
 
1328
.create_map:
1329
 
1330
           mov eax, [access]
1331
           and eax, SHM_ACCESS_MASK
943 serge 1332
           cmp eax, [esi+SMEM.access]
940 serge 1333
           mov [access], eax
1334
           mov edx, E_ACCESS
1213 serge 1335
           ja .fail
940 serge 1336
 
1337
           mov ebx, [CURRENT_TASK]
1338
           shl ebx, 5
1339
           mov ebx, [CURRENT_TASK+ebx+4]
943 serge 1340
           mov eax, SMAP.sizeof
940 serge 1341
 
1342
           call create_kernel_object
1343
           test eax, eax
1344
           mov edi, eax
1345
           mov edx, E_NOMEM
1213 serge 1346
           jz .fail
940 serge 1347
 
1213 serge 1348
           inc [esi+SMEM.refcount]
1349
 
943 serge 1350
           mov [edi+SMAP.magic], 'SMAP'
1351
           mov [edi+SMAP.destroy], destroy_smap
1213 serge 1352
           mov [edi+SMAP.parent], esi
943 serge 1353
           mov [edi+SMAP.base], 0
940 serge 1354
 
943 serge 1355
           stdcall user_alloc, [esi+SMEM.size]
940 serge 1356
           test eax, eax
1357
           mov [mapped], eax
1358
           mov edx, E_NOMEM
1359
           jz .cleanup2
1360
 
943 serge 1361
           mov [edi+SMAP.base], eax
940 serge 1362
 
943 serge 1363
           mov ecx, [esi+SMEM.size]
940 serge 1364
           mov [size], ecx
1365
 
1366
           shr ecx, 12
1367
           shr eax, 10
1368
 
943 serge 1369
           mov esi, [esi+SMEM.base]
940 serge 1370
           shr esi, 10
1371
           lea edi, [page_tabs+eax]
1372
           add esi, page_tabs
1373
 
1374
           mov edx, [access]
1375
           or edx, [owner_access]
1376
           shl edx, 1
1377
           or edx, PG_USER+PG_SHARED
1378
@@:
1379
           lodsd
1380
           and eax, 0xFFFFF000
1381
           or eax, edx
1382
           stosd
1383
           loop @B
1384
 
1385
           xor edx, edx
1386
 
1387
           cmp [owner_access], 0
1213 serge 1388
           jne .fail
1389
.exit:
940 serge 1390
           mov edx, [size]
1213 serge 1391
.fail:
940 serge 1392
           mov eax, [mapped]
1393
 
1394
           popfd
1395
           pop edi
1396
           pop esi
1397
           pop ebx
1398
           ret
1399
.cleanup:
1213 serge 1400
           mov [size], edx
940 serge 1401
           mov eax, esi
1402
           call free
1403
           jmp .exit
1404
 
1405
.cleanup2:
1213 serge 1406
           mov [size], edx
940 serge 1407
           mov eax, edi
1408
           call destroy_smap
1409
           jmp .exit
1410
endp
943 serge 1411
 
1412
align 4
1413
proc shmem_close stdcall, name:dword
1414
 
1415
           mov eax, [name]
1416
           test eax, eax
1417
           jz .fail
1418
 
1419
           push esi
1420
           push edi
945 serge 1421
           pushfd
1422
           cli
943 serge 1423
 
1424
           mov esi, [current_slot]
1425
           add esi, APP_OBJ_OFFSET
1426
.next:
1427
           mov eax, [esi+APPOBJ.fd]
1428
           test eax, eax
1429
           jz @F
1430
 
1431
           cmp eax, esi
1432
           mov esi, eax
1433
           je @F
1434
 
1435
           cmp [eax+SMAP.magic], 'SMAP'
1436
           jne .next
1437
 
1438
           mov edi, [eax+SMAP.parent]
1439
           test edi, edi
1440
           jz .next
1441
 
1501 mario79 1442
           lea edi, [edi+SMEM.name]
943 serge 1443
           stdcall strncmp, [name], edi, 32
1444
           test eax, eax
1445
           jne .next
1446
 
945 serge 1447
           stdcall user_free, [esi+SMAP.base]
1448
 
1501 mario79 1449
           mov eax,esi
943 serge 1450
           call [esi+APPOBJ.destroy]
1451
@@:
945 serge 1452
           popfd
943 serge 1453
           pop edi
1454
           pop esi
1455
.fail:
1456
           ret
1457
endp