Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
2288 clevermous 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
2455 mario79 3
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
2288 clevermous 4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;                                                              ;;
7
;; System service for filesystem call                           ;;
8
;; (C) 2004 Ville Turjanmaa, License: GPL                       ;;
9
;; 29.04.2006 Elimination of hangup after the                   ;;
10
;;            expiration hd_wait_timeout (for LBA) -  Mario79   ;;
11
;; 15.01.2005 get file size/attr/date,                          ;;
12
;;            file_append (only for hd) - ATV                   ;;
13
;; 23.11.2004 test if hd/partition is set - ATV                 ;;
14
;; 18.11.2004 get_disk_info and more error codes - ATV          ;;
15
;; 08.11.2004 expand_pathz and rename (only for hd) - ATV       ;;
16
;; 20.10.2004 Makedir/Removedir (only for hd) - ATV             ;;
17
;;                                                              ;;
18
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
19
 
20
$Revision: 2643 $
21
 
22
 
23
iglobal
24
dir0:
25
             db  'HARDDISK   '
26
             db  'RAMDISK    '
27
             db  'FLOPPYDISK '
28
             db  0
29
 
30
dir1:
31
             db  'FIRST      '
32
             db  'SECOND     '
33
             db  'THIRD      '
34
             db  'FOURTH     '
35
             db  0
36
 
37
not_select_IDE db 0
38
 
39
hd_address_table:
40
                   dd  0x1f0,0x00,0x1f0,0x10
41
                   dd  0x170,0x00,0x170,0x10
42
endg
43
 
44
file_system:
45
 
46
; IN:
47
;
48
; eax = 0  ; read file          /RamDisk/First  6
49
; eax = 8  ; lba read
50
; eax = 15 ; get_disk_info
51
;
52
; OUT:
53
;
54
; eax = 0  : read ok
55
; eax = 1  : no hd base and/or partition defined
56
; eax = 2  : function is unsupported for this FS
57
; eax = 3  : unknown FS
58
; eax = 4  : partition not defined at hd
59
; eax = 5  : file not found
60
; eax = 6  : end of file
61
; eax = 7  : memory pointer not in application area
62
; eax = 8  : disk full
63
; eax = 9  : fat table corrupted
64
; eax = 10 : access denied
65
; eax = 11 : disk error
66
;
67
; ebx = size
68
 
69
; \begin{diamond}[18.03.2006]
70
; for subfunction 16 (start application) error codes must be negative
71
;    because positive values are valid PIDs
72
; so possible return values are:
73
; eax > 0 : process created, eax=PID
74
 
75
; -0x10 <= eax < 0 : -eax is filesystem error code:
76
; eax = -1  = 0xFFFFFFFF : no hd base and/or partition defined
77
; eax = -3  = 0xFFFFFFFD : unknown FS
78
; eax = -5  = 0xFFFFFFFB : file not found
79
; eax = -6  = 0xFFFFFFFA : unexpected end of file (probably not executable file)
80
; eax = -9  = 0xFFFFFFF7 : fat table corrupted
81
; eax = -10 = 0xFFFFFFF6 : access denied
82
 
83
; -0x20 <= eax < -0x10: eax is process creation error code:
84
; eax = -0x20 = 0xFFFFFFE0 : too many processes
85
; eax = -0x1F = 0xFFFFFFE1 : not Menuet/Kolibri executable
86
; eax = -0x1E = 0xFFFFFFE2 : no memory
87
 
88
; ebx is not changed
89
 
90
; \end{diamond}[18.03.2006]
91
 
92
    ; Extract parameters
93
 ;   add    eax, std_application_base_address    ; abs start of info block
94
 
95
        cmp     dword [eax+0], 15; GET_DISK_INFO
96
        je      fs_info
97
 
98
        cmp     dword [CURRENT_TASK], 1; no memory checks for kernel requests
99
        jz      no_checks_for_kernel
100
        mov     edx, eax
101
        cmp     dword [eax+0], 1
102
        jnz     .usual_check
103
        mov     ebx, [eax+12]
104
 ;   add   ebx,std_application_base_address
105
        mov     ecx, [eax+8]
106
        call    check_region
107
        test    eax, eax
108
        jnz     area_in_app_mem
109
 
110
.error_output:
111
        mov     esi, buffer_failed
112
        call    sys_msg_board_str
113
;    mov   eax,7
114
        mov     dword [esp+36], 7
115
        ret
116
iglobal
117
  buffer_failed db 'K : Buffer check failed',13,10,0
118
endg
119
.usual_check:
120
        cmp     dword [eax+0], 0
121
        mov     ecx, 512
122
        jnz     .small_size
123
        mov     ecx, [eax+8]
124
        shl     ecx, 9
125
.small_size:
126
        mov     ebx, [eax+12]
127
 ;   add   ebx,std_application_base_address
128
        call    check_region
129
        test    eax, eax
130
        jz      .error_output
131
  area_in_app_mem:
132
        mov     eax, edx
133
  no_checks_for_kernel:
134
 
135
  fs_read:
136
 
137
        mov     ebx, [eax+20]   ; program wants root directory ?
138
        test    bl, bl
139
        je      fs_getroot
140
        test    bh, bh
141
        jne     fs_noroot
142
  fs_getroot:
143
; \begin{diamond}[18.03.2006]
144
; root - only read is allowed
145
; other operations return "access denied", eax=10
146
; (execute operation returns eax=-10)
147
        cmp     dword [eax], 0
148
        jz      .read_root
149
        mov     dword [esp+36], 10
150
        ret
151
.read_root:
152
; \end{diamond}[18.03.2006]
153
        mov     esi, dir0
154
        mov     edi, [eax+12]
155
 ;   add   edi,std_application_base_address
156
        mov     ecx, 11
157
        push    ecx
158
;    cld    ; already is
159
        rep movsb
160
        mov     al, 0x10
161
        stosb
162
        add     edi, 32-11-1
163
        pop     ecx
164
        rep movsb
165
        stosb
166
        and     dword [esp+36], 0; ok read
167
        mov     dword [esp+24], 32*2; size of root
168
        ret
169
 
170
  fs_info:                      ;start of code - Mihasik
171
        push    eax
172
        cmp     [eax+21], byte 'r'
173
        je      fs_info_r
174
        cmp     [eax+21], byte 'R'
175
        je      fs_info_r
176
        mov     eax, 3          ;if unknown disk
177
        xor     ebx, ebx
178
        xor     ecx, ecx
179
        xor     edx, edx
180
        jmp     fs_info1
181
  fs_info_r:
182
        call    ramdisk_free_space;if ramdisk
183
        mov     ecx, edi        ;free space in ecx
184
        shr     ecx, 9          ;free clusters
185
        mov     ebx, 2847       ;total clusters
186
        mov     edx, 512        ;cluster size
187
        xor     eax, eax        ;always 0
188
  fs_info1:
189
        pop     edi
190
        mov     [esp+36], eax
191
        mov     [esp+24], ebx    ; total clusters on disk
192
        mov     [esp+32], ecx    ; free clusters on disk
193
        mov     [edi], edx       ; cluster size in bytes
194
        ret                      ;end of code - Mihasik
195
 
196
  fs_noroot:
197
 
198
        push    dword [eax+0]   ; read/write/delete/.../makedir/rename/lba/run
199
        push    dword [eax+4]   ; 512 block number to read
200
        push    dword [eax+8]   ; bytes to write/append or 512 blocks to read
201
        mov     ebx, [eax+12]
202
 ;   add   ebx,std_application_base_address
203
        push    ebx             ; abs start of return/save area
204
 
205
        lea     esi, [eax+20]   ; abs start of dir + filename
206
        mov     edi, [eax+16]
207
 ;   add   edi,std_application_base_address    ; abs start of work area
208
 
209
        call    expand_pathz
210
 
211
        push    edi             ; dir start
212
        push    ebx             ; name of file start
213
 
214
        mov     eax, [edi+1]
215
        cmp     eax, 'RD  '
216
        je      fs_yesramdisk
217
        cmp     eax, 'RAMD'
218
        jne     fs_noramdisk
219
 
220
  fs_yesramdisk:
221
 
222
        cmp     byte [edi+1+11], 0
223
        je      fs_give_dir1
224
 
225
        mov     eax, [edi+1+12]
226
        cmp     eax, '1   '
227
        je      fs_yesramdisk_first
228
        cmp     eax, 'FIRS'
229
        jne     fs_noramdisk
230
 
231
  fs_yesramdisk_first:
232
 
233
        cmp     dword [esp+20], 8; LBA read ramdisk
234
        jne     fs_no_LBA_read_ramdisk
235
 
236
        mov     eax, [esp+16]   ; LBA block to read
237
        mov     ecx, [esp+8]    ; abs pointer to return area
238
 
239
        call    LBA_read_ramdisk
240
        jmp     file_system_return
241
 
242
 
243
  fs_no_LBA_read_ramdisk:
244
 
245
        cmp     dword [esp+20], 0; READ
246
        jne     fs_noramdisk_read
247
 
248
        mov     eax, [esp+4]    ; fname
249
        add     eax, 2*12+1
250
        mov     ebx, [esp+16]   ; block start
251
        inc     ebx
252
        mov     ecx, [esp+12]   ; block count
253
        mov     edx, [esp+8]    ; return
254
        mov     esi, [esp+0]
255
        sub     esi, eax
256
        add     esi, 12+1       ; file name length
257
        call    fileread
258
 
259
        jmp     file_system_return
260
 
261
 
262
  fs_noramdisk_read:
263
  fs_noramdisk:
264
 
265
  ;********************************************************************
266
        mov     eax, [edi+1]
267
        cmp     eax, 'FD  '
268
        je      fs_yesflpdisk
269
        cmp     eax, 'FLOP'
270
        jne     fs_noflpdisk
271
 
272
  fs_yesflpdisk:
273
        call    reserve_flp
274
 
275
        cmp     byte [edi+1+11], 0
276
        je      fs_give_dir1
277
 
278
        mov     eax, [edi+1+12]
279
        cmp     eax, '1   '
280
        je      fs_yesflpdisk_first
281
        cmp     eax, 'FIRS'
282
        je      fs_yesflpdisk_first
283
        cmp     eax, '2   '
284
        je      fs_yesflpdisk_second
285
        cmp     eax, 'SECO'
286
        jne     fs_noflpdisk
287
        jmp     fs_yesflpdisk_second
288
 
289
  fs_yesflpdisk_first:
290
        mov     [flp_number], 1
291
        jmp     fs_yesflpdisk_start
292
  fs_yesflpdisk_second:
293
        mov     [flp_number], 2
294
  fs_yesflpdisk_start:
295
        cmp     dword [esp+20], 0; READ
296
        jne     fs_noflpdisk_read
297
 
298
        mov     eax, [esp+4]    ; fname
299
        add     eax, 2*12+1
300
        mov     ebx, [esp+16]   ; block start
301
        inc     ebx
302
        mov     ecx, [esp+12]   ; block count
303
        mov     edx, [esp+8]    ; return
304
        mov     esi, [esp+0]
305
        sub     esi, eax
306
        add     esi, 12+1       ; file name length
307
        call    floppy_fileread
308
 
309
        jmp     file_system_return
310
 
311
 
312
  fs_noflpdisk_read:
313
  fs_noflpdisk:
314
  ;*****************************************************************
315
 
316
        mov     eax, [edi+1]
317
        cmp     eax, 'HD0 '
318
        je      fs_yesharddisk_IDE0
319
        cmp     eax, 'HD1 '
320
        je      fs_yesharddisk_IDE1
321
        cmp     eax, 'HD2 '
322
        je      fs_yesharddisk_IDE2
323
        cmp     eax, 'HD3 '
324
        je      fs_yesharddisk_IDE3
325
        jmp     old_path_harddisk
326
fs_yesharddisk_IDE0:
327
        call    reserve_hd1
328
        mov     [hdbase], 0x1f0
329
        mov     [hdid], 0x0
330
        mov     [hdpos], 1
331
        jmp     fs_yesharddisk_partition
332
fs_yesharddisk_IDE1:
333
        call    reserve_hd1
334
        mov     [hdbase], 0x1f0
335
        mov     [hdid], 0x10
336
        mov     [hdpos], 2
337
        jmp     fs_yesharddisk_partition
338
fs_yesharddisk_IDE2:
339
        call    reserve_hd1
340
        mov     [hdbase], 0x170
341
        mov     [hdid], 0x0
342
        mov     [hdpos], 3
343
        jmp     fs_yesharddisk_partition
344
fs_yesharddisk_IDE3:
345
        call    reserve_hd1
346
        mov     [hdbase], 0x170
347
        mov     [hdid], 0x10
348
        mov     [hdpos], 4
349
fs_yesharddisk_partition:
350
        call    reserve_hd_channel
351
;    call  choice_necessity_partition
352
;    jmp   fs_yesharddisk_all
353
        jmp     fs_for_new_semantic
354
 
355
choice_necessity_partition:
356
        mov     eax, [edi+1+12]
357
        call    StringToNumber
358
        mov     [fat32part], eax
359
choice_necessity_partition_1:
360
        mov     ecx, [hdpos]
361
        xor     eax, eax
362
        mov     [hd_entries], eax; entries in hd cache
363
        mov     edx, DRIVE_DATA+2
364
        cmp     ecx, 0x80
365
        jb      search_partition_array
366
        mov     ecx, 4
367
 search_partition_array:
368
        mov     bl, [edx]
369
        movzx   ebx, bl
370
        add     eax, ebx
371
        inc     edx
372
        loop    search_partition_array
373
        mov     ecx, [hdpos]
374
        mov     edx, BiosDiskPartitions
375
        sub     ecx, 0x80
376
        jb      .s
377
        je      .f
378
 @@:
379
        mov     ebx, [edx]
380
        add     edx, 4
381
        add     eax, ebx
382
        loop    @b
383
        jmp     .f
384
 .s:
385
        sub     eax, ebx
386
 .f:
387
        add     eax, [known_part];   add   eax,[fat32part]
388
        dec     eax
389
        xor     edx, edx
390
        imul    eax, 100
391
        add     eax, DRIVE_DATA+0xa
392
        mov     [transfer_adress], eax
393
        call    partition_data_transfer_1
394
        ret
395
 
396
 old_path_harddisk:
397
        mov     eax, [edi+1]
398
        cmp     eax, 'HD  '
399
        je      fs_yesharddisk
400
        cmp     eax, 'HARD'
401
        jne     fs_noharddisk
402
 
403
  fs_yesharddisk:
404
        cmp     dword [esp+20], 8; LBA read
405
        jne     fs_no_LBA_read
406
        mov     eax, [esp+16]   ; LBA block to read
407
        lea     ebx, [edi+1+12] ; pointer to FIRST/SECOND/THIRD/FOURTH
408
        mov     ecx, [esp+8]    ; abs pointer to return area
409
        call    LBA_read
410
        jmp     file_system_return
411
 
412
  fs_no_LBA_read:
413
 
414
        cmp     byte [edi+1+11], 0; directory read
415
        je      fs_give_dir1
416
        call    reserve_hd1
417
 fs_for_new_semantic:
418
        call    choice_necessity_partition
419
 
420
  fs_yesharddisk_all:
421
        mov     eax, 1
422
        mov     ebx, [esp+24+24]
423
        cmp     [hdpos], 0      ; is hd base set?
424
        jz      hd_err_return
425
        cmp     [fat32part], 0  ; is partition set?
426
        jnz     @f
427
hd_err_return:
428
        call    free_hd_channel
429
        and     [hd1_status], 0
430
        jmp     file_system_return
431
@@:
432
 
433
        call    free_hd_channel
434
        and     [hd1_status], 0
435
 
436
  fs_noharddisk:
437
; \begin{diamond}[18.03.2006]
438
        mov     eax, 5   ; file not found
439
; а может быть, возвращать другой код ошибки?
440
        mov     ebx, [esp+24+24]; do not change ebx in application
441
; \end{diamond}[18.03.2006]
442
 
443
  file_system_return:
444
 
445
        add     esp, 24
446
 
447
        mov     [esp+36], eax
448
        mov     [esp+24], ebx
449
        ret
450
 
451
 
452
  fs_give_dir1:
453
 
454
; \begin{diamond}[18.03.2006]
455
; /RD,/FD,/HD - only read is allowed
456
; other operations return "access denied", eax=10
457
; (execute operation returns eax=-10)
458
        cmp     dword [esp+20], 0
459
        jz      .read
460
        add     esp, 20
461
        pop     ecx
462
        mov     dword [esp+36], 10
463
        ret
464
.read:
465
; \end{diamond}[18.03.2006]
466
        mov     al, 0x10
467
        mov     ebx, 1
468
        mov     edi, [esp+8]
469
        mov     esi, dir1
470
  fs_d1_new:
471
        mov     ecx, 11
472
;    cld
473
        rep movsb
474
        stosb
475
        add     edi, 32-11-1
476
        dec     ebx
477
        jne     fs_d1_new
478
 
479
        add     esp, 24
480
 
481
        and     dword [esp+36], 0; ok read
482
        mov     dword [esp+24], 32*1; dir/data size
483
        ret
484
 
485
 
486
 
487
LBA_read_ramdisk:
488
 
489
        cmp     [lba_read_enabled], 1
490
        je      lbarrl1
491
 
492
        xor     ebx, ebx
493
        mov     eax, 2
494
        ret
495
 
496
  lbarrl1:
497
 
498
        cmp     eax, 18*2*80
499
        jb      lbarrl2
500
        xor     ebx, ebx
501
        mov     eax, 3
502
        ret
503
 
504
  lbarrl2:
505
 
506
        pushad
507
 
508
        call    restorefatchain
509
 
510
        mov     edi, ecx
511
        mov     esi, eax
512
 
513
        shl     esi, 9
514
        add     esi, RAMDISK
515
        mov     ecx, 512/4
516
;    cld
517
        rep movsd
518
 
519
        popad
520
 
521
        xor     ebx, ebx
522
        xor     eax, eax
523
        ret
524
 
525
LBA_read:
526
 
527
; IN:
528
;
529
; eax = LBA block to read
530
; ebx = pointer to FIRST/SECOND/THIRD/FOURTH
531
; ecx = abs pointer to return area
532
 
533
        cmp     [lba_read_enabled], 1
534
        je      lbarl1
535
        mov     eax, 2
536
        ret
537
 
538
  lbarl1:
539
 
540
        call    reserve_hd1
541
 
542
        push    eax
543
        push    ecx
544
 
545
        mov     edi, hd_address_table
546
        mov     esi, dir1
547
        mov     eax, [ebx]
548
        mov     edx, '1   '
549
        mov     ecx, 4
550
  blar0:
551
        cmp     eax, [esi]
552
        je      blar2
553
        cmp     eax, edx
554
        je      blar2
555
        inc     edx
556
        add     edi, 8
557
        add     esi, 11
558
        dec     ecx
559
        jnz     blar0
560
 
561
        mov     eax, 1
562
        mov     ebx, 1
563
        jmp     LBA_read_ret
564
 
565
  blar2:
566
        mov     eax, [edi+0]
567
        mov     ebx, [edi+4]
568
 
569
        mov     [hdbase], eax
570
        mov     [hdid], ebx
571
 
572
        call    wait_for_hd_idle
573
        cmp     [hd_error], 0
574
        jne     hd_lba_error
575
 
576
    ; eax = hd port
577
    ; ebx = set for primary (0x00) or slave (0x10)
578
 
579
        cli
580
 
581
        mov     edx, eax
582
        inc     edx
583
        xor     eax, eax
584
        out     dx, al
585
        inc     edx
586
        inc     eax
587
        out     dx, al
588
        inc     edx
589
        mov     eax, [esp+4]
590
        out     dx, al
591
        shr     eax, 8
592
        inc     edx
593
        out     dx, al
594
        shr     eax, 8
595
        inc     edx
596
        out     dx, al
597
        shr     eax, 8
598
        inc     edx
599
        and     al, 1+2+4+8
600
        add     al, bl
601
        add     al, 128+64+32
602
        out     dx, al
603
 
604
        inc     edx
605
        mov     al, 20h
606
        out     dx, al
607
 
608
        sti
609
 
610
        call    wait_for_sector_buffer
611
        cmp     [hd_error], 0
612
        jne     hd_lba_error
613
 
614
        cli
615
 
616
        mov     edi, [esp+0]
617
        mov     ecx, 256
618
        sub     edx, 7
619
        cld
620
        rep insw
621
 
622
        sti
623
 
624
        xor     eax, eax
625
        xor     ebx, ebx
626
 
627
  LBA_read_ret:
628
        mov     [hd_error], 0
629
        mov     [hd1_status], 0
630
        add     esp, 2*4
631
 
632
        ret
633
 
634
 
635
expand_pathz:
636
; IN:
637
;   esi = asciiz path & file
638
;   edi = buffer for path & file name
639
; OUT:
640
;   edi = directory & file : / 11 + / 11 + / 11 - zero terminated
641
;   ebx = /file name - zero terminated
642
;   esi = pointer after source
643
 
644
        push    eax
645
        push    ecx
646
        push    edi;[esp+0]
647
 
648
  pathz_start:
649
        mov     byte [edi], '/'
650
        inc     edi
651
        mov     al, 32
652
        mov     ecx, 11
653
        cld
654
        rep stosb               ; clear filename area
655
        sub     edi, 11
656
        mov     ebx, edi        ; start of dir/file name
657
 
658
  pathz_new_char:
659
        mov     al, [esi]
660
        inc     esi
661
        cmp     al, 0
662
        je      pathz_end
663
 
664
        cmp     al, '/'
665
        jne     pathz_not_path
666
        cmp     edi, ebx        ; skip first '/'
667
        jz      pathz_new_char
668
        lea     edi, [ebx+11]   ; start of next directory
669
        jmp     pathz_start
670
 
671
  pathz_not_path:
672
        cmp     al, '.'
673
        jne     pathz_not_ext
674
        lea     edi, [ebx+8]    ; start of extension
675
        jmp     pathz_new_char
676
 
677
  pathz_not_ext:
678
        cmp     al, 'a'
679
        jb      pathz_not_low
680
        cmp     al, 'z'
681
        ja      pathz_not_low
682
        sub     al, 0x20        ; char to uppercase
683
 
684
  pathz_not_low:
685
        mov     [edi], al
686
        inc     edi
687
        mov     eax, [esp+0]    ; start_of_dest_path
688
        add     eax, 512        ; keep maximum path under 512 bytes
689
        cmp     edi, eax
690
        jb      pathz_new_char
691
 
692
  pathz_end:
693
        cmp     ebx, edi        ; if path end with '/'
694
        jnz     pathz_put_zero  ; go back 1 level
695
        sub     ebx, 12
696
 
697
  pathz_put_zero:
698
        mov     byte [ebx+11], 0
699
        dec     ebx             ; include '/' char into file name
700
        pop     edi
701
        pop     ecx
702
        pop     eax
703
        ret
704
 
705
;*******************************************
706
;* string to number
707
;* input eax - 4 byte string
708
;* output eax - number
709
;*******************************************
710
StringToNumber:
711
;    ПЕРЕВОД СТРОКОВОГО ЧИСЛА В ЧИСЛОВОЙ ВИД
712
;    Вход:
713
;        EDI - адрес строки с числом. Конец числа отмечен кодом 0Dh
714
;    Выход:
715
;        CF - индикатор ошибок:
716
;            0 - ошибок нет;
717
;            1 - ошибка
718
;        Если CF=0, то AX - число.
719
 
720
        push    bx
721
        push    cx
722
        push    dx
723
        push    edi
724
        mov     [partition_string], eax
725
        mov     edi, partition_string
726
        xor     cx, cx
727
i1:
728
        mov     al, [edi]
729
        cmp     al, 32;13
730
        je      i_exit
731
;    cmp    al,'0'
732
;    jb    err
733
;    cmp    al,'9'
734
;    ja    err
735
        sub     al, 48
736
        shl     cx, 1
737
        jc      error
738
        mov     bx, cx
739
        shl     cx, 1
740
        jc      error
741
        shl     cx, 1
742
        jc      error
743
        add     cx, bx
744
        jc      error
745
        cbw
746
        add     cx, ax
747
        jc      error
748
i3:
749
        inc     edi
750
        jmp     i1
751
i_exit:
752
        mov     ax, cx
753
        clc
754
i4:
755
        movzx   eax, ax
756
        pop     edi
757
        pop     dx
758
        pop     cx
759
        pop     bx
760
        ret
761
 
762
error:
763
        stc
764
        jmp     i4
765
 
766
partition_string:
767
                  dd 0
768
                  db 32