Subversion Repositories Kolibri OS

Rev

Rev 1311 | Rev 1316 | 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: 1314 $
9
 
10
 
164 serge 11
align 4
12
proc alloc_page
13
 
14
           pushfd
15
           cli
660 serge 16
           push ebx
164 serge 17
           mov ebx, [page_start]
18
           mov ecx, [page_end]
19
.l1:
20
           bsf eax,[ebx];
21
           jnz .found
22
           add ebx,4
23
           cmp ebx, ecx
24
           jb .l1
660 serge 25
           pop ebx
164 serge 26
           popfd
27
           xor eax,eax
28
           ret
29
.found:
30
           btr [ebx], eax
31
           mov [page_start],ebx
32
           sub ebx, sys_pgmap
254 serge 33
           lea eax, [eax+ebx*8]
164 serge 34
           shl eax, 12
35
           dec [pg_data.pages_free]
660 serge 36
           pop ebx
164 serge 37
           popfd
38
           ret
39
endp
40
 
41
align 4
42
proc alloc_pages stdcall, count:dword
43
           pushfd
660 serge 44
           push ebx
45
           push edi
164 serge 46
           cli
47
           mov eax, [count]
48
           add eax, 7
49
           shr eax, 3
50
           mov [count], eax
51
           cmp eax, [pg_data.pages_free]
52
           ja .fail
53
 
54
           mov ecx, [page_start]
55
           mov ebx, [page_end]
56
.find:
57
           mov edx, [count]
58
           mov edi, ecx
59
.match:
60
           cmp byte [ecx], 0xFF
61
           jne .next
62
           dec edx
63
           jz .ok
64
           inc ecx
65
           cmp ecx,ebx
66
           jb .match
660 serge 67
.fail:
68
           xor eax, eax
69
           pop edi
70
           pop ebx
164 serge 71
           popfd
72
           ret
73
.next:
74
           inc ecx
75
           cmp ecx, ebx
76
           jb .find
660 serge 77
           pop edi
78
           pop ebx
164 serge 79
           popfd
80
           xor eax, eax
81
           ret
82
.ok:
83
           sub ecx, edi
84
           inc ecx
663 serge 85
           push esi
164 serge 86
           mov esi, edi
87
           xor eax, eax
88
           rep stosb
89
           sub esi, sys_pgmap
90
           shl esi, 3+12
91
           mov eax, esi
92
           mov ebx, [count]
93
           shl ebx, 3
94
           sub [pg_data.pages_free], ebx
663 serge 95
           pop esi
660 serge 96
           pop edi
97
           pop ebx
164 serge 98
           popfd
99
           ret
100
endp
101
 
102
align 4
103
proc map_page stdcall,lin_addr:dword,phis_addr:dword,flags:dword
321 diamond 104
           push ebx
164 serge 105
           mov eax, [phis_addr]
106
           and eax, not 0xFFF
107
           or eax, [flags]
108
           mov ebx, [lin_addr]
109
           shr ebx, 12
365 serge 110
           mov [page_tabs+ebx*4], eax
164 serge 111
           mov eax, [lin_addr]
112
           invlpg [eax]
321 diamond 113
           pop ebx
164 serge 114
           ret
115
endp
116
 
117
align 4
281 serge 118
map_space:    ;not implemented
119
 
120
 
121
           ret
122
 
123
 
124
align 4
164 serge 125
proc free_page
126
;arg:  eax  page address
127
           pushfd
128
           cli
819 serge 129
           shr eax, 12                        ;page index
130
           bts dword [sys_pgmap], eax         ;that's all!
291 serge 131
           cmc
328 serge 132
           adc [pg_data.pages_free], 0
164 serge 133
           shr eax, 3
819 serge 134
           and eax, not 3                     ;dword offset from page_map
448 diamond 135
           add eax, sys_pgmap
164 serge 136
           cmp [page_start], eax
137
           ja @f
138
           popfd
139
           ret
140
@@:
141
           mov [page_start], eax
142
           popfd
143
           ret
144
endp
145
 
741 serge 146
proc map_io_mem stdcall, base:dword, size:dword, flags:dword
147
 
148
           push ebx
149
           push edi
150
           mov eax, [size]
151
           add eax, 4095
152
           and eax, -4096
153
           mov [size], eax
154
           stdcall alloc_kernel_space, eax
155
           test eax, eax
156
           jz .fail
157
           push eax
158
 
159
           mov edi, 0x1000
160
           mov ebx, eax
161
           mov ecx,[size]
162
           mov edx, [base]
163
           shr eax, 12
164
           shr ecx, 12
165
           and edx, -4096
166
           or edx, [flags]
167
@@:
168
           mov [page_tabs+eax*4], edx
819 serge 169
          ; push eax
1275 serge 170
           invlpg [ebx]
819 serge 171
          ; pop eax
741 serge 172
           inc eax
173
           add ebx, edi
174
           add edx, edi
175
           loop @B
176
 
177
           pop eax
178
           mov edx, [base]
179
           and edx, 4095
180
           add eax, edx
181
.fail:
182
           pop edi
183
           pop ebx
184
           ret
185
endp
186
 
279 serge 187
; param
328 serge 188
;  eax= page base + page flags
819 serge 189
;  ebx= linear address
281 serge 190
;  ecx= count
191
 
192
align 4
328 serge 193
commit_pages:
741 serge 194
           push edi
328 serge 195
           test ecx, ecx
196
           jz .fail
281 serge 197
 
328 serge 198
           mov edi, ebx
199
           mov ebx, pg_data.pg_mutex
200
           call wait_mutex      ;ebx
201
 
202
           mov edx, 0x1000
203
           mov ebx, edi
204
           shr ebx, 12
205
@@:
365 serge 206
           mov [page_tabs+ebx*4], eax
819 serge 207
          ; push eax
1275 serge 208
           invlpg [edi]
819 serge 209
          ; pop eax
328 serge 210
           add edi, edx
211
           add eax, edx
212
           inc ebx
213
           dec ecx
214
           jnz @B
215
           mov [pg_data.pg_mutex],ecx
216
.fail:
741 serge 217
           pop edi
281 serge 218
           ret
219
 
328 serge 220
 
281 serge 221
; param
279 serge 222
;  eax= base
281 serge 223
;  ecx= count
279 serge 224
 
164 serge 225
align 4
279 serge 226
release_pages:
321 diamond 227
 
228
           pushad
279 serge 229
           mov ebx, pg_data.pg_mutex
230
           call wait_mutex      ;ebx
231
 
232
           mov esi, eax
233
           mov edi, eax
234
 
235
           shr esi, 10
365 serge 236
           add esi, page_tabs
328 serge 237
 
238
           mov ebp, [pg_data.pages_free]
279 serge 239
           mov ebx, [page_start]
240
           mov edx, sys_pgmap
241
@@:
242
           xor eax, eax
243
           xchg eax, [esi]
924 serge 244
           push eax
279 serge 245
           invlpg [edi]
924 serge 246
           pop eax
279 serge 247
 
248
           test eax, 1
249
           jz .next
250
 
251
           shr eax, 12
252
           bts [edx], eax
291 serge 253
           cmc
328 serge 254
           adc ebp, 0
279 serge 255
           shr eax, 3
256
           and eax, -4
257
           add eax, edx
258
           cmp eax, ebx
259
           jae .next
260
 
261
           mov ebx, eax
262
.next:
263
           add edi, 0x1000
264
           add esi, 4
265
           dec ecx
266
           jnz @B
328 serge 267
           mov [pg_data.pages_free], ebp
279 serge 268
           and [pg_data.pg_mutex],0
321 diamond 269
           popad
279 serge 270
           ret
271
 
819 serge 272
; param
273
;  eax= base
274
;  ecx= count
275
 
279 serge 276
align 4
819 serge 277
unmap_pages:
278
 
279
           push edi
280
 
281
           mov edi, eax
282
           mov edx, eax
283
 
284
           shr edi, 10
285
           add edi, page_tabs
286
 
287
           xor eax, eax
288
@@:
289
           stosd
290
           invlpg [edx]
291
           add edx, 0x1000
292
           loop @b
293
 
294
           pop edi
295
           ret
296
 
297
 
298
align 4
188 serge 299
proc map_page_table stdcall, lin_addr:dword, phis_addr:dword
321 diamond 300
           push ebx
164 serge 301
           mov ebx, [lin_addr]
302
           shr ebx, 22
303
           mov eax, [phis_addr]
304
           and eax, not 0xFFF
305
           or eax, PG_UW          ;+PG_NOCACHE
378 serge 306
           mov dword [master_tab+ebx*4], eax
164 serge 307
           mov eax, [lin_addr]
308
           shr eax, 10
365 serge 309
           add eax, page_tabs
164 serge 310
           invlpg [eax]
321 diamond 311
           pop ebx
164 serge 312
           ret
313
endp
314
 
315
align 4
316
proc init_LFB
378 serge 317
           locals
318
             pg_count dd ?
319
           endl
320
 
164 serge 321
           cmp dword [LFBAddress], -1
322
           jne @f
412 serge 323
           mov [BOOT_VAR+0x901c],byte 2
1300 serge 324
           stdcall alloc_pages, (0x280000 / 4096)
325
 
326
           push eax
327
           call alloc_page
328
           stdcall map_page_table, LFB_BASE, eax
329
           pop eax
330
           or eax, PG_UW
331
           mov ebx, LFB_BASE
332
           mov ecx, 0x280000 / 4096
333
           call commit_pages
334
           mov [LFBAddress], dword LFB_BASE
164 serge 335
           ret
336
@@:
337
           test [SCR_MODE],word 0100000000000000b
211 serge 338
           jnz @f
412 serge 339
           mov [BOOT_VAR+0x901c],byte 2
211 serge 340
           ret
341
@@:
490 serge 342
           call init_mtrr
343
 
378 serge 344
           mov edx, LFB_BASE
345
           mov esi, [LFBAddress]
1300 serge 346
           mov edi, 0x00C00000
379 serge 347
           mov dword [exp_lfb+4], edx
214 serge 348
 
164 serge 349
           shr edi, 12
350
           mov [pg_count], edi
351
           shr edi, 10
352
 
353
           bt [cpu_caps], CAPS_PSE
354
           jnc .map_page_tables
355
           or esi, PG_LARGE+PG_UW
465 serge 356
           mov edx, sys_pgdir+(LFB_BASE shr 20)
164 serge 357
@@:
465 serge 358
           mov [edx], esi
378 serge 359
           add edx, 4
164 serge 360
           add esi, 0x00400000
361
           dec edi
362
           jnz @B
363
 
207 serge 364
           bt [cpu_caps], CAPS_PGE
365
           jnc @F
465 serge 366
           or dword [sys_pgdir+(LFB_BASE shr 20)], PG_GLOBAL
207 serge 367
@@:
378 serge 368
           mov dword [LFBAddress], LFB_BASE
164 serge 369
           mov eax, cr3       ;flush TLB
370
           mov cr3, eax
371
           ret
372
 
373
.map_page_tables:
374
 
465 serge 375
@@:
164 serge 376
           call alloc_page
378 serge 377
           stdcall map_page_table, edx, eax
389 serge 378
           add edx, 0x00400000
164 serge 379
           dec edi
465 serge 380
           jnz @B
164 serge 381
 
382
           mov eax, [LFBAddress]
378 serge 383
           mov edi, page_tabs + (LFB_BASE shr 10)
164 serge 384
           or eax, PG_UW
385
           mov ecx, [pg_count]
378 serge 386
           cld
389 serge 387
@@:
388
           stosd
389
           add eax, 0x1000
390
           dec ecx
391
           jnz @B
164 serge 392
 
378 serge 393
           mov dword [LFBAddress], LFB_BASE
164 serge 394
           mov eax, cr3       ;flush TLB
395
           mov cr3, eax
396
 
397
           ret
398
endp
399
 
400
align 4
401
proc new_mem_resize stdcall, new_size:dword
402
 
276 serge 403
           mov ebx, pg_data.pg_mutex
404
           call wait_mutex    ;ebx
164 serge 405
 
406
           mov edi, [new_size]
407
           add edi,4095
408
           and edi,not 4095
409
           mov [new_size], edi
410
 
465 serge 411
           mov edx,[current_slot]
412
           cmp [edx+APPDATA.heap_base],0
172 serge 413
           jne .exit
414
 
465 serge 415
           mov esi, [edx+APPDATA.mem_size]
164 serge 416
           add esi, 4095
417
           and esi, not 4095
418
 
419
           cmp edi, esi
420
           jae .expand
421
 
422
           shr edi, 12
423
           shr esi, 12
424
@@:
378 serge 425
           mov eax, [app_page_tabs+edi*4]
164 serge 426
           test eax, 1
427
           jz .next
378 serge 428
           mov dword [app_page_tabs+edi*4], 2
164 serge 429
           mov ebx, edi
430
           shl ebx, 12
924 serge 431
           push eax
659 serge 432
           invlpg [ebx]
924 serge 433
           pop eax
164 serge 434
           call free_page
435
 
436
.next:     add edi, 1
437
           cmp edi, esi
438
           jb @B
439
 
440
.update_size:
465 serge 441
           mov     ebx, [new_size]
442
           call    update_mem_size
164 serge 443
 
444
           xor eax, eax
445
           dec [pg_data.pg_mutex]
446
           ret
447
.expand:
448
 
449
           push esi
450
           push edi
451
 
452
           add edi, 0x3FFFFF
453
           and edi, not(0x3FFFFF)
454
           add esi, 0x3FFFFF
455
           and esi, not(0x3FFFFF)
456
 
457
           cmp esi, edi
458
           jae .grow
459
 
460
           xchg esi, edi
461
 
462
@@:
463
           call alloc_page
464
           test eax, eax
1103 diamond 465
           jz .exit_pop
164 serge 466
 
188 serge 467
           stdcall map_page_table, edi, eax
164 serge 468
 
469
           push edi
470
           shr edi, 10
365 serge 471
           add edi, page_tabs
164 serge 472
           mov ecx, 1024
473
           xor eax, eax
474
           cld
475
           rep stosd
476
           pop edi
477
 
478
           add edi, 0x00400000
479
           cmp edi, esi
480
           jb @B
481
.grow:
482
           pop edi
483
           pop esi
484
@@:
485
           call alloc_page
486
           test eax, eax
487
           jz .exit
488
           stdcall map_page,esi,eax,dword PG_UW
489
 
490
           push edi
491
           mov edi, esi
492
           xor eax, eax
493
           mov ecx, 1024
494
           cld
495
           rep stosd
496
           pop edi
497
 
498
           add esi, 0x1000
499
           cmp esi, edi
294 diamond 500
           jb  @B
164 serge 501
 
502
           jmp .update_size
1103 diamond 503
.exit_pop:
504
           pop edi
505
           pop esi
164 serge 506
.exit:
507
           xor eax, eax
508
           inc eax
509
           dec [pg_data.pg_mutex]
510
           ret
511
endp
512
 
294 diamond 513
update_mem_size:
465 serge 514
; in: edx = slot base
294 diamond 515
;     ebx = new memory size
516
; destroys eax,ecx,edx
517
 
465 serge 518
           mov    [APPDATA.mem_size+edx],ebx
294 diamond 519
;search threads and update
520
;application memory size infomation
465 serge 521
           mov    ecx,[APPDATA.dir_table+edx]
294 diamond 522
           mov    eax,2
523
 
524
.search_threads:
525
;eax = current slot
526
;ebx = new memory size
527
;ecx = page directory
528
           cmp    eax,[TASK_COUNT]
529
           jg     .search_threads_end
530
           mov    edx,eax
531
           shl    edx,5
532
           cmp    word [CURRENT_TASK+edx+TASKDATA.state],9 ;if slot empty?
533
           jz     .search_threads_next
534
           shl    edx,3
380 serge 535
           cmp    [SLOT_BASE+edx+APPDATA.dir_table],ecx     ;if it is our thread?
294 diamond 536
           jnz    .search_threads_next
380 serge 537
           mov    [SLOT_BASE+edx+APPDATA.mem_size],ebx     ;update memory size
294 diamond 538
.search_threads_next:
539
           inc    eax
540
           jmp    .search_threads
541
.search_threads_end:
542
           ret
543
 
285 serge 544
; param
545
;  eax= linear address
546
;
547
; retval
548
;  eax= phisical page address
549
 
164 serge 550
align 4
285 serge 551
get_pg_addr:
552
           shr eax, 12
365 serge 553
           mov eax, [page_tabs+eax*4]
164 serge 554
           and eax, 0xFFFFF000
555
           ret
556
 
465 serge 557
 
188 serge 558
align 4
1105 Galkov 559
; Now it is called from core/sys32::exc_c (see stack frame there)
164 serge 560
proc page_fault_handler
465 serge 561
 
1056 Galkov 562
    .err_addr   equ ebp-4
709 diamond 563
 
1105 Galkov 564
        push    ebx               ;save exception number (#PF)
1056 Galkov 565
        mov     ebp, esp
566
        mov     ebx, cr2
1105 Galkov 567
        push    ebx               ;that is locals: .err_addr = cr2
1056 Galkov 568
        inc     [pg_data.pages_faults]
465 serge 569
 
1056 Galkov 570
        mov     eax, [pf_err_code]
164 serge 571
 
1056 Galkov 572
        cmp     ebx, OS_BASE      ;ebx == .err_addr
573
        jb      .user_space       ;ñòðàíèöà â ïàìÿòè ïðèëîæåíèÿ ;
188 serge 574
 
1056 Galkov 575
        cmp     ebx, page_tabs
576
        jb      .kernel_space     ;ñòðàíèöà â ïàìÿòè ÿäðà
164 serge 577
 
1056 Galkov 578
        cmp     ebx, kernel_tabs
579
        jb      .alloc;.app_tabs  ;òàáëèöû ñòðàíèö ïðèëîæåíèÿ ;
580
                                  ;ïðîñòî ñîçäàäèì îäíó
581
if 0 ;ïîêà ýòî ïðîñòî ëèøíåå
582
        cmp     ebx, LFB_BASE
583
        jb      .core_tabs        ;òàáëèöû ñòðàíèö ÿäðà
584
                                  ;Îøèáêà
585
  .lfb:
586
                                  ;îáëàñòü LFB
587
                                  ;Îøèáêà
588
        jmp     .fail
589
end if
590
.core_tabs:
591
.fail:  ;simply return to caller
592
        mov     esp, ebp
1105 Galkov 593
        pop     ebx               ;restore exception number (#PF)
1056 Galkov 594
        ret
378 serge 595
 
1300 serge 596
;        xchg bx, bx
597
;        add     esp,12 ;clear in stack: locals(.err_addr) + #PF + ret_to_caller
598
;        restore_ring3_context
599
;        iretd
600
 
164 serge 601
.user_space:
1056 Galkov 602
        test    eax, PG_MAP
603
        jnz     .err_access       ;Ñòðàíèöà ïðèñóòñòâóåò
604
                                  ;Îøèáêà äîñòóïà ?
465 serge 605
 
1056 Galkov 606
        shr     ebx, 12
607
        mov     ecx, ebx
608
        shr     ecx, 10
609
        mov     edx, [master_tab+ecx*4]
610
        test    edx, PG_MAP
611
        jz      .fail             ;òàáëèöà ñòðàíèö íå ñîçäàíà
612
                                  ;íåâåðíûé àäðåñ â ïðîãðàììå
172 serge 613
 
1056 Galkov 614
        mov     eax, [page_tabs+ebx*4]
615
        test    eax, 2
616
        jz      .fail             ;àäðåñ íå çàðåçåðâèðîâàí äëÿ ;
617
                                  ;èñïîëüçîâàíèÿ. Îøèáêà
188 serge 618
.alloc:
1056 Galkov 619
        call    alloc_page
620
        test    eax, eax
621
        jz      .fail
164 serge 622
 
1289 diamond 623
        stdcall map_page,[.err_addr],eax,PG_UW
164 serge 624
 
1056 Galkov 625
        mov     edi, [.err_addr]
626
        and     edi, 0xFFFFF000
627
        mov     ecx, 1024
628
        xor     eax, eax
629
       ;cld     ;caller is duty for this
630
        rep     stosd
631
.exit:  ;iret with repeat fault instruction
1105 Galkov 632
        add     esp,12 ;clear in stack: locals(.err_addr) + #PF + ret_to_caller
1056 Galkov 633
        restore_ring3_context
634
        iretd
465 serge 635
 
1289 diamond 636
.err_access:
637
; access denied? this may be a result of copy-on-write protection for DLL
638
; check list of HDLLs
639
        and     ebx, not 0xFFF
640
        mov     eax, [CURRENT_TASK]
641
        shl     eax, 8
1311 diamond 642
        mov     eax, [SLOT_BASE+eax+APPDATA.dlls_list_ptr]
643
        test    eax, eax
644
        jz      .fail
645
        mov     esi, [eax+HDLL.fd]
1289 diamond 646
.scan_hdll:
647
        cmp     esi, eax
648
        jz      .fail
649
        mov     edx, ebx
650
        sub     edx, [esi+HDLL.base]
651
        cmp     edx, [esi+HDLL.size]
652
        jb      .fault_in_hdll
653
.scan_hdll.next:
1311 diamond 654
        mov     esi, [esi+HDLL.fd]
1289 diamond 655
        jmp     .scan_hdll
656
.fault_in_hdll:
657
; allocate new page, map it as rw and copy data
658
        call    alloc_page
659
        test    eax, eax
660
        jz      .fail
661
        stdcall map_page,ebx,eax,PG_UW
662
        mov     edi, ebx
663
        mov     ecx, 1024
664
        sub     ebx, [esi+HDLL.base]
665
        mov     esi, [esi+HDLL.parent]
666
        mov     esi, [esi+DLLDESCR.data]
667
        add     esi, ebx
668
        rep     movsd
669
        jmp     .exit
465 serge 670
 
671
.kernel_space:
1056 Galkov 672
        test    eax, PG_MAP
673
        jz      .fail   ;ñòðàíèöà íå ïðèñóòñòâóåò
465 serge 674
 
1056 Galkov 675
        test    eax,12  ;U/S (+below)
676
        jnz     .fail   ;ïðèëîæåíèå îáðàòèëîñü ê ïàìÿòè
677
                        ;ÿäðà
678
       ;test    eax, 8
679
       ;jnz     .fail   ;óñòàíîâëåí çàðåçåðâèðîâàííûé áèò
680
                        ;â òàáëèöàõ ñòðàíèö. äîáàâëåíî â P4/Xeon
465 serge 681
 
682
;ïîïûòêà çàïèñè â çàùèù¸ííóþ ñòðàíèöó ÿäðà
683
 
1056 Galkov 684
        cmp     ebx, tss._io_map_0
685
        jb      .fail
465 serge 686
 
1056 Galkov 687
        cmp     ebx, tss._io_map_0+8192
688
        jae     .fail
465 serge 689
 
690
; io permission map
691
; copy-on-write protection
692
 
1056 Galkov 693
        call    alloc_page
694
        test    eax, eax
695
        jz      .fail
465 serge 696
 
1056 Galkov 697
        push    eax
698
        stdcall map_page,[.err_addr],eax,dword PG_SW
699
        pop     eax
700
        mov     edi, [.err_addr]
701
        and     edi, -4096
702
        lea     esi, [edi+(not tss._io_map_0)+1]; -tss._io_map_0
465 serge 703
 
1056 Galkov 704
        mov     ebx, esi
705
        shr     ebx, 12
706
        mov     edx, [current_slot]
707
        or      eax, PG_SW
708
        mov     [edx+APPDATA.io_map+ebx*4], eax
465 serge 709
 
1056 Galkov 710
        add     esi, [default_io_map]
711
        mov     ecx, 4096/4
712
       ;cld     ;caller is duty for this
713
        rep     movsd
714
        jmp     .exit
164 serge 715
endp
716
 
1314 diamond 717
; returns number of mapped bytes
718
proc map_mem stdcall, lin_addr:dword,slot:dword,\
719
                      ofs:dword,buf_size:dword,req_access:dword
720
           push 0 ; initialize number of mapped bytes
721
 
722
           cmp [buf_size], 0
164 serge 723
           jz .exit
724
 
1314 diamond 725
           mov eax, [slot]
726
           shl eax, 8
727
           mov eax, [SLOT_BASE+eax+APPDATA.dir_table]
164 serge 728
           and eax, 0xFFFFF000
729
 
536 diamond 730
           stdcall map_page,[ipc_pdir],eax,PG_UW
164 serge 731
           mov ebx, [ofs]
732
           shr ebx, 22
733
           mov esi, [ipc_pdir]
734
           mov edi, [ipc_ptab]
735
           mov eax, [esi+ebx*4]
736
           and eax, 0xFFFFF000
737
           jz .exit
536 diamond 738
           stdcall map_page,edi,eax,PG_UW
164 serge 739
;           inc ebx
740
;           add edi, 0x1000
741
;           mov eax, [esi+ebx*4]
742
;           test eax, eax
743
;           jz @f
744
;          and eax, 0xFFFFF000
745
;           stdcall map_page, edi, eax
746
 
747
@@:        mov edi, [lin_addr]
748
           and edi, 0xFFFFF000
749
           mov ecx, [buf_size]
750
           add ecx, 4095
751
           shr ecx, 12
752
           inc ecx
753
 
754
           mov edx, [ofs]
755
           shr edx, 12
756
           and edx, 0x3FF
757
           mov esi, [ipc_ptab]
758
 
1314 diamond 759
.map:
760
           stdcall safe_map_page,[slot],[req_access],[ofs]
761
           jnc .exit
762
           add dword [ebp-4], 4096
763
           add [ofs], 4096
536 diamond 764
           dec ecx
765
           jz  .exit
164 serge 766
           add edi, 0x1000
767
           inc edx
536 diamond 768
           cmp edx, 0x400
164 serge 769
           jnz .map
536 diamond 770
           inc ebx
771
           mov eax, [ipc_pdir]
772
           mov eax, [eax+ebx*4]
773
           and eax, 0xFFFFF000
774
           jz  .exit
775
           stdcall map_page,esi,eax,PG_UW
776
           xor edx, edx
777
           jmp .map
164 serge 778
 
779
.exit:
1314 diamond 780
           pop eax
164 serge 781
           ret
782
endp
783
 
1314 diamond 784
proc map_memEx stdcall, lin_addr:dword,slot:dword,\
785
                        ofs:dword,buf_size:dword,req_access:dword
786
           push 0 ; initialize number of mapped bytes
787
 
788
           cmp [buf_size], 0
164 serge 789
           jz .exit
790
 
1314 diamond 791
           mov eax, [slot]
792
           shl eax, 8
793
           mov eax, [SLOT_BASE+eax+APPDATA.dir_table]
164 serge 794
           and eax, 0xFFFFF000
795
 
1314 diamond 796
           stdcall map_page,[proc_mem_pdir],eax,PG_UW
164 serge 797
           mov ebx, [ofs]
798
           shr ebx, 22
799
           mov esi, [proc_mem_pdir]
800
           mov edi, [proc_mem_tab]
801
           mov eax, [esi+ebx*4]
802
           and eax, 0xFFFFF000
803
           test eax, eax
804
           jz .exit
1314 diamond 805
           stdcall map_page,edi,eax,PG_UW
164 serge 806
 
807
@@:        mov edi, [lin_addr]
808
           and edi, 0xFFFFF000
809
           mov ecx, [buf_size]
810
           add ecx, 4095
811
           shr ecx, 12
812
           inc ecx
813
 
814
           mov edx, [ofs]
815
           shr edx, 12
816
           and edx, 0x3FF
817
           mov esi, [proc_mem_tab]
818
 
1314 diamond 819
.map:
820
           stdcall safe_map_page,[slot],[req_access],[ofs]
821
           jnc .exit
822
           add dword [ebp-4], 0x1000
164 serge 823
           add edi, 0x1000
1314 diamond 824
           add [ofs], 0x1000
164 serge 825
           inc edx
826
           dec ecx
827
           jnz .map
828
.exit:
1314 diamond 829
           pop eax
164 serge 830
           ret
831
endp
832
 
1314 diamond 833
; in: esi+edx*4 = pointer to page table entry
834
; in: [slot], [req_access], [ofs] on the stack
835
; in: edi = linear address to map
836
; out: CF cleared <=> failed
837
; destroys: only eax
838
proc safe_map_page stdcall, slot:dword, req_access:dword, ofs:dword
839
	mov	eax, [esi+edx*4]
840
	test	al, PG_MAP
841
	jz	.not_present
842
	test	al, PG_WRITE
843
	jz	.resolve_readonly
844
; normal case: writable page, just map with requested access
845
.map:
846
	stdcall	map_page, edi, eax, [req_access]
847
	stc
848
.fail:
849
	ret
850
.not_present:
851
; check for alloc-on-demand page
852
	test	al, 2
853
	jz	.fail
854
; allocate new page, save it to source page table
855
	push	ecx
856
	call	alloc_page
857
	pop	ecx
858
	test	eax, eax
859
	jz	.fail
860
	or	al, PG_UW
861
	mov	[esi+edx*4], eax
862
	jmp	.map
863
.resolve_readonly:
864
; readonly page, probably copy-on-write
865
; check: readonly request of readonly page is ok
866
	test	[req_access], PG_WRITE
867
	jz	.map
868
; find control structure for this page
869
	pushf
870
	cli
871
	cld
872
	push	ebx ecx
873
	mov	eax, [slot]
874
	shl	eax, 8
875
	mov	eax, [SLOT_BASE+eax+APPDATA.dlls_list_ptr]
876
	test	eax, eax
877
	jz	.no_hdll
878
	mov	ecx, [eax+HDLL.fd]
879
.scan_hdll:
880
	cmp	ecx, eax
881
	jz	.no_hdll
882
	mov	ebx, [ofs]
883
	and	ebx, not 0xFFF
884
	sub	ebx, [ecx+HDLL.base]
885
	cmp	ebx, [ecx+HDLL.size]
886
	jb	.hdll_found
887
	mov	ecx, [ecx+HDLL.fd]
888
	jmp	.scan_hdll
889
.no_hdll:
890
	pop	ecx ebx
891
	popf
892
	clc
893
	ret
894
.hdll_found:
895
; allocate page, save it in page table, map it, copy contents from base
896
	mov	eax, [ecx+HDLL.parent]
897
	add	ebx, [eax+DLLDESCR.data]
898
	call	alloc_page
899
	test	eax, eax
900
	jz	.no_hdll
901
	or	al, PG_UW
902
	mov	[esi+edx*4], eax
903
	stdcall	map_page, edi, eax, [req_access]
904
	push	esi edi
905
	mov	esi, ebx
906
	mov	ecx, 4096/4
907
	rep	movsd
908
	pop	edi esi
909
	pop	ecx ebx
910
	popf
911
	stc
912
	ret
913
endp
164 serge 914
 
915
sys_IPC:
916
;input:
917
;  eax=1 - set ipc buffer area
918
;    ebx=address of buffer
919
;    ecx=size of buffer
920
;  eax=2 - send message
921
;    ebx=PID
922
;    ecx=address of message
923
;    edx=size of message
924
 
925
           cmp  eax,1
926
           jne @f
927
           call set_ipc_buff
928
           mov [esp+36], eax
929
           ret
930
@@:
931
           cmp eax, 2
932
           jne @f
933
           stdcall sys_ipc_send, ebx, ecx, edx
934
           mov [esp+36], eax
935
           ret
936
@@:
937
           xor eax, eax
938
           not eax
939
           mov [esp+36], eax
940
           ret
941
 
942
align 4
943
proc set_ipc_buff
944
 
465 serge 945
           mov  eax,[current_slot]
164 serge 946
           pushf
947
           cli
465 serge 948
           mov  [eax+APPDATA.ipc_start],ebx     ;set fields in extended information area
949
           mov  [eax+APPDATA.ipc_size],ecx
164 serge 950
 
951
           add ecx, ebx
952
           add ecx, 4095
953
           and ecx, not 4095
954
 
955
.touch:    mov eax, [ebx]
956
           add ebx, 0x1000
957
           cmp ebx, ecx
536 diamond 958
           jb  .touch
164 serge 959
 
960
           popf
961
           xor eax, eax
962
           ret
963
endp
964
 
965
proc sys_ipc_send stdcall, PID:dword, msg_addr:dword, msg_size:dword
966
           locals
967
             dst_slot   dd ?
968
             dst_offset dd ?
969
             buf_size   dd ?
536 diamond 970
             used_buf   dd ?
164 serge 971
           endl
972
 
973
           pushf
974
           cli
975
 
976
           mov  eax, [PID]
977
           call pid_to_slot
978
           test eax,eax
979
           jz   .no_pid
980
 
981
           mov [dst_slot], eax
982
           shl  eax,8
380 serge 983
           mov  edi,[eax+SLOT_BASE+0xa0]  ;is ipc area defined?
164 serge 984
           test edi,edi
985
           jz   .no_ipc_area
986
 
987
           mov ebx, edi
988
           and ebx, 0xFFF
989
           mov [dst_offset], ebx
990
 
380 serge 991
           mov esi, [eax+SLOT_BASE+0xa4]
164 serge 992
           mov [buf_size], esi
993
 
536 diamond 994
           mov ecx, [ipc_tmp]
995
           cmp esi, 0x40000-0x1000 ; size of [ipc_tmp] minus one page
996
           jbe @f
1314 diamond 997
           push esi edi
536 diamond 998
           add esi,0x1000
999
           stdcall alloc_kernel_space,esi
1000
           mov ecx, eax
1314 diamond 1001
           pop edi esi
536 diamond 1002
@@:
1003
           mov [used_buf], ecx
1314 diamond 1004
           stdcall map_mem, ecx, [dst_slot],\
1005
                             edi, esi, PG_SW
164 serge 1006
 
1007
           mov edi, [dst_offset]
536 diamond 1008
           add edi, [used_buf]
164 serge 1009
           cmp dword [edi], 0
1010
           jnz  .ipc_blocked          ;if dword [buffer]<>0 - ipc blocked now
227 serge 1011
 
566 serge 1012
           mov edx, dword [edi+4]
1013
           lea ebx, [edx+8]
164 serge 1014
           add ebx, [msg_size]
1015
           cmp ebx, [buf_size]
1016
           ja .buffer_overflow         ;esi<0 - not enough memory in buffer
227 serge 1017
 
164 serge 1018
           mov dword [edi+4], ebx
1019
           mov eax,[TASK_BASE]
1020
           mov eax, [eax+0x04]         ;eax - our PID
1021
           add edi, edx
1022
           mov [edi], eax
1023
           mov ecx, [msg_size]
1024
 
1025
           mov [edi+4], ecx
1026
           add edi, 8
1027
           mov esi, [msg_addr]
465 serge 1028
       ;    add esi, new_app_base
164 serge 1029
           cld
1030
           rep movsb
1031
 
1032
           mov ebx, [ipc_tmp]
1033
           mov edx, ebx
1034
           shr ebx, 12
1035
           xor eax, eax
365 serge 1036
           mov [page_tabs+ebx*4], eax
164 serge 1037
           invlpg [edx]
1038
 
1039
           mov ebx, [ipc_pdir]
1040
           mov edx, ebx
1041
           shr ebx, 12
1042
           xor eax, eax
365 serge 1043
           mov [page_tabs+ebx*4], eax
164 serge 1044
           invlpg [edx]
1045
 
1046
           mov ebx, [ipc_ptab]
1047
           mov edx, ebx
1048
           shr ebx, 12
1049
           xor eax, eax
365 serge 1050
           mov [page_tabs+ebx*4], eax
164 serge 1051
           invlpg [edx]
1052
 
1053
           mov  eax, [dst_slot]
1054
           shl eax, 8
380 serge 1055
           or   [eax+SLOT_BASE+0xA8],dword 0x40
164 serge 1056
           cmp  dword [check_idle_semaphore],20
1057
           jge  .ipc_no_cis
1058
 
1059
           mov  dword [check_idle_semaphore],5
1060
.ipc_no_cis:
536 diamond 1061
           push 0
1062
           jmp .ret
164 serge 1063
.no_pid:
1064
           popf
536 diamond 1065
           mov eax, 4
164 serge 1066
           ret
1067
.no_ipc_area:
1068
           popf
1069
           xor eax, eax
1070
           inc eax
1071
           ret
1072
.ipc_blocked:
536 diamond 1073
           push 2
1074
           jmp .ret
164 serge 1075
.buffer_overflow:
536 diamond 1076
           push 3
1077
.ret:
1078
           mov eax, [used_buf]
1079
           cmp eax, [ipc_tmp]
1080
           jz @f
1081
           stdcall free_kernel_space,eax
1082
@@:
1083
           pop eax
164 serge 1084
           popf
1085
           ret
1086
endp
1087
 
1088
align 4
170 serge 1089
sysfn_meminfo:
164 serge 1090
 
1072 diamond 1091
        ;   add ecx, new_app_base
1092
           cmp ecx, OS_BASE
465 serge 1093
           jae .fail
172 serge 1094
 
164 serge 1095
           mov eax, [pg_data.pages_count]
1072 diamond 1096
           mov [ecx], eax
172 serge 1097
           shl eax, 12
1072 diamond 1098
           mov [esp+32], eax
1099
           mov eax, [pg_data.pages_free]
1100
           mov [ecx+4], eax
1101
           mov eax, [pg_data.pages_faults]
1102
           mov [ecx+8], eax
1103
           mov eax, [heap_size]
1104
           mov [ecx+12], eax
1105
           mov eax, [heap_free]
1106
           mov [ecx+16], eax
170 serge 1107
           mov eax, [heap_blocks]
1072 diamond 1108
           mov [ecx+20], eax
1109
           mov eax, [free_blocks]
1110
           mov [ecx+24], eax
164 serge 1111
           ret
172 serge 1112
.fail:
1276 Lrz 1113
           or dword [esp+32], -1
172 serge 1114
           ret
1276 Lrz 1115
iglobal
164 serge 1116
align 4
940 serge 1117
f68call:
1275 serge 1118
           dd f68.11   ; init_heap
1119
           dd f68.12   ; user_alloc
1120
           dd f68.13   ; user_free
1121
           dd f68.14   ; get_event_ex
1077 Galkov 1122
           dd f68.fail ;moved to f68.24
1275 serge 1123
           dd f68.16   ; get_service
1124
           dd f68.17   ; call_service
1077 Galkov 1125
           dd f68.fail ;moved to f68.25
1275 serge 1126
           dd f68.19   ; load_dll
1127
           dd f68.20   ; user_realloc
1128
           dd f68.21   ; load_driver
1129
           dd f68.22   ; shmem_open
1130
           dd f68.23   ; shmem_close
1077 Galkov 1131
           dd f68.24
1132
           dd f68.25
1276 Lrz 1133
endg
940 serge 1134
align 4
1135
f68:
164 serge 1136
           cmp  eax,4
1137
           jle  sys_sheduler
1138
 
170 serge 1139
           cmp eax, 11
164 serge 1140
           jb .fail
1141
 
1077 Galkov 1142
           cmp eax, 25
940 serge 1143
           ja .fail
1144
 
1145
           jmp dword [f68call+eax*4-11*4]
1146
.11:
188 serge 1147
           call init_heap
164 serge 1148
           mov [esp+36], eax
1149
           ret
940 serge 1150
.12:
164 serge 1151
           stdcall user_alloc, ebx
1152
           mov [esp+36], eax
1153
           ret
940 serge 1154
.13:
164 serge 1155
           stdcall user_free, ebx
1156
           mov [esp+36], eax
1157
           ret
940 serge 1158
.14:
465 serge 1159
           cmp ebx, OS_BASE
1160
           jae .fail
1055 Galkov 1161
           mov edi,ebx
1162
           call get_event_ex
227 serge 1163
           mov [esp+36], eax
164 serge 1164
           ret
940 serge 1165
.16:
188 serge 1166
           test ebx, ebx
1167
           jz .fail
465 serge 1168
           cmp ebx, OS_BASE
1169
           jae .fail
164 serge 1170
           stdcall get_service, ebx
1171
           mov [esp+36], eax
1172
           ret
940 serge 1173
.17:
378 serge 1174
           call srv_handlerEx   ;ebx
164 serge 1175
           mov [esp+36], eax
1176
           ret
940 serge 1177
.19:
465 serge 1178
           cmp ebx, OS_BASE
1179
           jae .fail
198 serge 1180
           stdcall load_library, ebx
1181
           mov [esp+36], eax
1182
           ret
940 serge 1183
.20:
490 serge 1184
           mov     eax, ecx
1185
           call    user_realloc
1186
           mov     [esp+36], eax
1187
           ret
940 serge 1188
.21:
740 serge 1189
           cmp ebx, OS_BASE
1190
           jae .fail
1191
 
1192
           stdcall load_PE, ebx
1193
 
1194
           test eax, eax
1195
           jz @F
1196
 
1197
           mov esi, eax
1198
           stdcall eax, DRV_ENTRY
1199
 
1200
           test eax, eax
1201
           jz @F
1202
 
1203
           mov [eax+SRV.entry], esi
1204
 
1205
@@:
1206
           mov [esp+36], eax
1207
           ret
940 serge 1208
.22:
1209
           cmp ebx, OS_BASE
1210
           jae .fail
740 serge 1211
 
940 serge 1212
           stdcall shmem_open, ebx, ecx, edx
1213
           mov [esp+28], edx
1214
           mov [esp+36], eax
1215
           ret
740 serge 1216
 
943 serge 1217
.23:
1218
           cmp ebx, OS_BASE
1219
           jae .fail
1220
 
1221
           stdcall shmem_close, ebx
1222
           mov [esp+36], eax
1223
           ret
1275 serge 1224
.24:
1225
           mov  eax, [current_slot]
1226
           xchg ebx, [eax+APPDATA.exc_handler]
1227
           xchg ecx, [eax+APPDATA.except_mask]
1228
           mov  [esp+36], ebx ; reg_eax+8
1229
           mov  [esp+24], ecx ; reg_ebx+8
1230
           ret
1231
.25:
1232
           cmp ebx,32
1233
           jae .fail
1234
           mov  eax, [current_slot]
1235
           btr  [eax+APPDATA.except_mask],ebx
1236
           setc byte[esp+36]
1237
           jecxz @f
1238
           bts  [eax+APPDATA.except_mask],ebx
1239
@@:
1240
           ret
943 serge 1241
 
164 serge 1242
.fail:
1243
           xor eax, eax
1244
           mov [esp+36], eax
1245
           ret
1246
 
1247
align 4
819 serge 1248
proc load_pe_driver stdcall, file:dword
1249
 
1250
           stdcall load_PE, [file]
1251
           test eax, eax
1252
           jz .fail
1253
 
1254
           mov esi, eax
1255
           stdcall eax, DRV_ENTRY
1256
           test eax, eax
1257
           jz .fail
1258
 
1259
           mov [eax+SRV.entry], esi
1260
           ret
1261
 
1262
.fail:
1263
           xor eax, eax
1264
           ret
1265
endp
1266
 
1267
 
1268
align 4
164 serge 1269
proc init_mtrr
1270
 
412 serge 1271
           cmp [BOOT_VAR+0x901c],byte 2
164 serge 1272
           je  .exit
1273
 
211 serge 1274
           bt [cpu_caps], CAPS_MTRR
1275
           jnc .exit
1276
 
164 serge 1277
           mov eax, cr0
1278
           or eax, 0x60000000   ;disable caching
1279
           mov cr0, eax
1280
           wbinvd               ;invalidate cache
1281
 
1282
           mov ecx, 0x2FF
1283
           rdmsr                ;
1030 diamond 1284
; has BIOS already initialized MTRRs?
1285
           test ah, 8
1286
           jnz .skip_init
1287
; rarely needed, so mainly placeholder
1288
; main memory - cached
164 serge 1289
           push eax
1290
 
821 diamond 1291
           mov eax, [MEM_AMOUNT]
1292
; round eax up to next power of 2
1293
           dec eax
1294
           bsr ecx, eax
1030 diamond 1295
           mov ebx, 2
1296
           shl ebx, cl
1297
           dec ebx
1298
; base of memory range = 0, type of memory range = MEM_WB
164 serge 1299
           xor edx, edx
1030 diamond 1300
           mov eax, MEM_WB
1301
           mov ecx, 0x200
1302
           wrmsr
1303
; mask of memory range = 0xFFFFFFFFF - (size - 1), ebx = size - 1
1304
           mov eax, 0xFFFFFFFF
1305
           mov edx, 0x0000000F
1306
           sub eax, ebx
1307
           sbb edx, 0
1308
           or eax, 0x800
1309
           inc ecx
1310
           wrmsr
1311
; clear unused MTRRs
164 serge 1312
           xor eax, eax
1030 diamond 1313
           xor edx, edx
164 serge 1314
@@:
1030 diamond 1315
           wrmsr
164 serge 1316
           inc ecx
1030 diamond 1317
           cmp ecx, 0x210
1318
           jb @b
1319
; enable MTRRs
1320
           pop eax
1321
           or ah, 8
1322
           and al, 0xF0 ; default memtype = UC
1323
           mov ecx, 0x2FF
164 serge 1324
           wrmsr
1030 diamond 1325
.skip_init:
1326
           stdcall set_mtrr, [LFBAddress],[LFBSize],MEM_WC
164 serge 1327
 
1328
           wbinvd               ;again invalidate
1329
 
1330
           mov eax, cr0
1331
           and eax, not 0x60000000
1332
           mov cr0, eax         ; enable caching
1333
.exit:
1334
           ret
1335
endp
1336
 
1337
align 4
1030 diamond 1338
proc set_mtrr stdcall, base:dword,size:dword,mem_type:dword
1339
; find unused register
1340
           mov ecx, 0x201
1341
@@:
1342
           rdmsr
1343
           dec ecx
1344
           test ah, 8
1345
           jz .found
1346
           rdmsr
1347
           mov al, 0 ; clear memory type field
1348
           cmp eax, [base]
1349
           jz .ret
1350
           add ecx, 3
1351
           cmp ecx, 0x210
1352
           jb @b
1353
; no free registers, ignore the call
1354
.ret:
1355
           ret
1356
.found:
1357
; found, write values
164 serge 1358
           xor edx, edx
1359
           mov eax, [base]
1360
           or eax, [mem_type]
1361
           wrmsr
1362
 
1363
           mov ebx, [size]
1364
           dec ebx
1365
           mov eax, 0xFFFFFFFF
1366
           mov edx, 0x0000000F
1367
           sub eax, ebx
1368
           sbb edx, 0
1369
           or eax, 0x800
1370
           inc ecx
1371
           wrmsr
1372
           ret
1373
endp
1374
 
465 serge 1375
align 4
172 serge 1376
proc stall stdcall, delay:dword
1377
           push ecx
1378
           push edx
1379
           push ebx
1380
           push eax
1381
 
1382
           mov eax, [delay]
1383
           mul [stall_mcs]
1384
           mov ebx, eax       ;low
1385
           mov ecx, edx       ;high
1386
           rdtsc
1387
           add ebx, eax
1388
           adc ecx,edx
1389
@@:
1390
           rdtsc
1391
           sub eax, ebx
1392
           sbb edx, ecx
1393
           jb @B
1394
 
1395
           pop eax
1396
           pop ebx
1397
           pop edx
1398
           pop ecx
1399
           ret
1400
endp
1401
 
520 serge 1402
align 4
1403
proc create_ring_buffer stdcall, size:dword, flags:dword
1404
           locals
1405
             buf_ptr  dd ?
1406
           endl
237 serge 1407
 
520 serge 1408
           mov eax, [size]
1409
           test eax, eax
1410
           jz .fail
1411
 
1412
           add eax, eax
1413
           stdcall alloc_kernel_space, eax
1414
           test eax, eax
1415
           jz .fail
1416
 
662 serge 1417
           push ebx
1418
 
520 serge 1419
           mov [buf_ptr], eax
1420
 
1421
           mov ebx, [size]
1422
           shr ebx, 12
1423
           push ebx
1424
 
1425
           stdcall alloc_pages, ebx
1426
           pop ecx
1427
 
1428
           test eax, eax
1429
           jz .mm_fail
1430
 
662 serge 1431
           push edi
1432
 
520 serge 1433
           or eax, [flags]
1434
           mov edi, [buf_ptr]
1435
           mov ebx, [buf_ptr]
1436
           mov edx, ecx
566 serge 1437
           shl edx, 2
520 serge 1438
           shr edi, 10
1439
@@:
1440
           mov [page_tabs+edi], eax
1441
           mov [page_tabs+edi+edx], eax
924 serge 1442
           invlpg [ebx]
1443
           invlpg [ebx+0x10000]
520 serge 1444
           add eax, 0x1000
1445
           add ebx, 0x1000
566 serge 1446
           add edi, 4
520 serge 1447
           dec ecx
1448
           jnz @B
1449
 
1450
           mov eax, [buf_ptr]
662 serge 1451
           pop edi
1452
           pop ebx
520 serge 1453
           ret
1454
.mm_fail:
1455
           stdcall free_kernel_space, [buf_ptr]
1456
           xor eax, eax
662 serge 1457
           pop ebx
520 serge 1458
.fail:
1459
           ret
1460
endp