Subversion Repositories Kolibri OS

Rev

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