Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
2288 clevermous 1
; Copyright (c) 2009, 
2
; All rights reserved.
3
;
4
; Redistribution and use in source and binary forms, with or without
5
; modification, are permitted provided that the following conditions are met:
6
;       * Redistributions of source code must retain the above copyright
7
;       notice, this list of conditions and the following disclaimer.
8
;       * Redistributions in binary form must reproduce the above copyright
9
;       notice, this list of conditions and the following disclaimer in the
10
;       documentation and/or other materials provided with the distribution.
11
;       * Neither the name of the  nor the
12
;       names of its contributors may be used to endorse or promote products
13
;       derived from this software without specific prior written permission.
14
;
15
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov nickname  ''AS IS'' AND ANY
16
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
; DISCLAIMED. IN NO EVENT SHALL  BE LIABLE FOR ANY
19
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
;*****************************************************************************
26
 
27
; в этой секции идет разбор параметров указатель на секцию храниться в point_default
28
;типы ошибок при обработке макроса
29
;Макрос RamdiskFS
30
;/определение флагов в записи корневой директории
31
ATTR_READ_ONLY  equ     0x01
32
ATTR_HIDDEN     equ     0x02
33
ATTR_SYSTEM     equ     0x04
34
ATTR_VOLUME_ID  equ     0x08
35
ATTR_DIRECTORY  equ     0x10
36
ATTR_ARCHIVE    equ     0x20
37
 
38
 
39
 
40
show_error_1    equ     0x1     ;кончились данные - не запланированный конец секции
41
show_error_2    equ     0x2     ;нет завершающего символа в размере рам диска.
42
show_error_3    equ     0x4     ; рам диск будет иметь размер =64 кб.
43
show_error_4    equ     0x8     ;
44
 
45
macro use_parse_def_sect
46
{
47
        mov     di, point_default
48
        push    ini_data_
49
        pop     es
50
        mov     si, point_to_point_def
51
        sub     si, 2
52
        mov     cx, [si]        ;загрузим указатель наследующию секцию
53
 
54
        xor     ax, ax  ;обнулим аx для очистки флагов
55
 
56
        sub     cx, di          ;вот теперь имеем истиный размер
57
        mov     save_cx_d, cx   ;сохраним значение cx своей переменной
58
;обнулим переменную флагов, это необходимо, для того, что бы избежать обработку повторяющихся значений
59
 
60
        mov     status_flag, ax
61
;;;;
62
;ВХод в обработку парсинга значений секций. es:di - указатель на начало секции cx размер секции доступной для парсинга
63
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
64
;соглашение не разрушаем bp, es, cs, sp
65
;use_Loader_Image       ;загрузить образ выше 1 мб
66
use_RamdiskFS
67
;проверяется самый последний.
68
use_LoaderModule    ;особенность - передает управление на загруженный модуль.
69
}
70
 
71
macro use_LoaderModule
72
;как вариант сейчас используется модель, при загрузке модуля на него передается управление, решение временое
73
;управление будет передаваться только после обработки всей секции
74
{
75
local .found_end_str
76
 
77
        mov     di, point_default  ;restore value
78
        mov     cx, save_cx_d
79
;обработка конструкции типа LoaderModule=kord/kolibri.ldm
80
.start_p_LM:
81
        call    get_firs_sym    ;get first symbol on new line
82
        test    cx, cx
83
        jz      ._afterLoaderModule     ;нету? ну ладно - следующее значение тогда )
84
        cmp     al, 'L'
85
        jnz     .start_p_LM
86
;проверка на значение LoaderModule
87
;        parse_LoaderModule
88
        mov     bx, cx
89
        mov     ax, di
90
 
91
        mov     si, parse_LoaderModule
92
        mov     cx, parse_LoaderModule_e - parse_LoaderModule
93
        repe cmpsb
94
        jnz     .rest_value_loop_LM        ;is not compare
95
 
96
        sub     bx, parse_LoaderModule_e - parse_LoaderModule;correct cx
97
        add     bx, cx
98
        mov     cx, bx
99
 
100
        test    status_flag, flag_found_LM              ;оценка флагов
101
        jz      .correct_is_not_set_LM
102
 
103
;       mov     si,found_equal_timeout                          ;мы нашли что флаг уже установлен, информируем
104
;       call    printplain
105
;       jmp     .get_next_str
106
 
107
.correct_is_not_set_LM:
108
        mov     ax, 0x3d20         ;cut al=' ' ah='='
109
        repe scasb
110
        jcxz    .rest_value_loop_LM          ;not found param timeout
111
 
112
        cmp     ah, byte [es:di-1]   ;find '='
113
        jnz     .rest_value_loop_LM
114
 
115
        repe scasb                 ;cut ' '
116
        inc     cx
117
        dec     di
118
;di указывает на начало блока информации, в cx длинна до конца секции.
119
;после загрузки заноситься значение занятой памяти.
120
;для того что бы загрузить модуль, воспользуемся callback сервисом
121
;оригинальное решение - разместим dd перед строчкой и после строчки разместим byte =0
122
;это выглядит так: в ini файле существует строчка LoaderModule = kord/kernel.loader
123
;мы ее модифицируем до такого состояния       dw,dw,db'kord/kernel.loader',0 конечно сохранив те значения которые мы заменяем
124
;сохранили певые 2 word
125
        push    dword [es:di-6]
126
        lea     si, [di-6]
127
 
128
        push    word [es:di-2]
129
        xor     ax, ax
130
        mov     word [es:di-6], ax      ;вносим нужные значения
131
;info_real_mode_size размер и указатель на область в которую можно загрузиться
132
        mov     ax, info_real_mode_size ;0x3000   ;следующий сегмент за данными
133
 
134
 
135
        mov     word [es:di-4], ax
136
        mov     word [es:di-2], 16      ;кол-во блоков по 4 кб =64 кб т.е. больше не считаем
137
;;;;;; поиск конца строчки
138
@@:
139
        mov     al, byte [es:di]
140
        cmp     al, ' '
141
        jz      .found_end_str
142
        cmp     al, 0xa
143
        jz      .found_end_str
144
        cmp     al, 0xd
145
        jz      .found_end_str
146
        inc     di
147
        dec     cx
148
        jnz     @b
149
;;;not found допустим,что это конец файла и он не имеет привычного заверешния строки
150
.found_end_str:
151
 
152
        push    word [es:di]
153
        xor     ax, ax
154
        mov     word [es:di], ax
155
;        xor     ax,ax   ; function 1 - read file
156
        mov     di, si  ;file_data
157
        inc     ax
158
        push    si
159
        push    es
160
 
161
        push    es
162
        pop     ds
163
        push    cs
164
        pop     es
165
 
166
        call    far dword [es:loader_callback]
167
 
168
        push    cs
169
        pop     ds
170
 
171
        pop     es
172
        pop     si
173
 
174
        test    bx, bx
175
        jnz     .error_LM
176
 
177
 
178
        jmp     far dword [es:si]
179
 
180
 
181
.error_LM:
182
        call    error.LoaderModule
183
.rest_value_loop_LM:
184
        mov     di, ax
185
        mov     cx, bx
186
        jmp     .start_p_LM
187
 
188
._afterLoaderModule:
189
}
190
 
191
macro use_RamdiskFS
192
; формирование рам диска, + обработка всего связанного.
193
{
194
if DEBUG
195
local ._not_memory_in_sys
196
;//////// clear window
197
        mov     ax, 3
198
        int     0x10
199
;\\\\\\\\\ clear window is end
200
        mov     si, ramdiskFS_st
201
        call    printplain
202
end if
203
; обнулим регистр состояния ошибок
204
        xor     ax, ax
205
        mov     show_errors_sect, ax
206
use_free_memory ; узнаем какого объема у нас доступна память. значение возаращается в ax
207
;узнаем сколько у нас есть памяти и сможем ли мы сформировать нужного размера рам диск.
208
use_RamdiskSize ;значение возвращается в bx
209
        cmp     free_ad_memory, bx      ; размерность в кб.
210
        jbe     ._not_memory_in_sys
211
        movzx   eax, bx
212
        shl     eax, 10 ;*1024 = get size in byte
213
        mov     save_ramdisksize, eax   ; сорханим размер в byte
214
 
215
get_type_FS     ;получим тип файловой системы + создадим ее
216
 
217
 
218
._not_memory_in_sys:
219
 
220
if DEBUG
221
;pause
222
        xor     ax, ax
223
        int     0x16
224
end if
225
}
226
macro use_RamdiskSize
227
{
228
local .start_p_RS
229
local .correct_is_not_set_RS
230
local .CS
231
local .correct_val_RS
232
local .correct_size_RS
233
local .rest_value_loop_RS
234
local .end_get_RS_ERROR_1
235
local .end_get_RS_ERROR_2
236
local ._end_parse_RS
237
;обрабатывается размер формируемого рам диска
238
;загрузим начало секции, т.к. будем просматривать с начала и всю секцию
239
        mov     di, point_default  ;restore value
240
        mov     cx, save_cx_d
241
.start_p_RS:
242
        call    get_firs_sym    ;get first symbol on new line
243
        test    cx, cx
244
        jz      ._end_parse_RS  ;нету? ну ладно - следующее значение тогда )
245
        cmp     al, 'R'
246
        jnz     .start_p_RS
247
;проверка на значения RamdiskSize
248
;        parse_RamdiskSize
249
        mov     bx, cx
250
        mov     ax, di
251
 
252
        mov     si, parse_RamdiskSize
253
        mov     cx, parse_RamdiskSize_e - parse_RamdiskSize
254
        repe cmpsb
255
        jnz     .rest_value_loop_RS    ;is not compare
256
 
257
        sub     bx, parse_RamdiskSize_e - parse_RamdiskSize;correct cx
258
        add     bx, cx
259
        mov     cx, bx
260
 
261
        test    status_flag, flag_found_RS              ;оценка флагов
262
        jz      .correct_is_not_set_RS
263
 
264
;       mov     si,found_equal_timeout                          ;мы нашли что флаг уже установлен, информируем
265
;       call    printplain
266
;       jmp     .get_next_str
267
 
268
.correct_is_not_set_RS:
269
        mov     ax, 0x3d20         ;cut al=' ' ah='='
270
        repe scasb
271
        jcxz    .end_get_RS_ERROR_1          ;not found param
272
 
273
        cmp     ah, byte [es:di-1]   ;find '='
274
        jnz     .start_p_RS                     ; перейдем на начало и попробуем найти еще секцию
275
 
276
        repe scasb                 ;cut ' '
277
        inc     cx
278
        dec     di
279
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
280
;Тут нужно преобразовывать строчку в цифровое значение.
281
;;;;;;;;;;;;;;;;;;;;;;;;;;
282
        xor     bx, bx
283
        mov     cx, 5
284
@@:
285
        mov     al, byte [es:di]
286
        cmp     al, '0'
287
        jb      .CS
288
        cmp     al, '9'
289
        jbe     .correct_val_RS
290
.CS:
291
        cmp     al, 'K'
292
        jz      .correct_size_RS
293
        jmp     .end_get_RS_ERROR_2
294
.correct_val_RS:
295
        imul    bx, 10
296
        xor     al, 0x30
297
        add     bl, al
298
        inc     di
299
        loop    @b
300
 
301
.correct_size_RS:
302
;возможен 1 вариант, когда размер задан в K киллобайтах
303
;внутренный формат данных это кол-во запрощеной памяти в кб.
304
        test    bx, bx
305
        jnz     @f      ;если значение отлично от 0
306
;;;;;сообщение об ошибке, размер "найденого" блока =0 минимально мы должны
307
;установить 64 кб размер рам диска.
308
        or      show_errors_sect, show_error_3
309
        mov     bx, 64
310
@@:
311
        jmp     ._end_parse_RS
312
 
313
 
314
.rest_value_loop_RS:
315
        mov     di, ax
316
        mov     cx, bx
317
        jmp     .start_p_RS
318
 
319
 
320
 
321
.end_get_RS_ERROR_1:
322
;сообщение об ошибке - данный участок кода не был корректно обработан :(
323
        or      show_errors_sect, show_error_1
324
        jmp     ._end_parse_RS
325
.end_get_RS_ERROR_2:
326
        or      show_errors_sect, show_error_2
327
 
328
._end_parse_RS:
329
if DEBUG
330
        pusha
331
        movzx   eax, bx
332
        mov     cx, 0x0a
333
        mov     di, RamdiskSize_msg
334
        mov     dword[ds:di], '    '
335
        mov     word [ds:di+4], '  '
336
        call    decode
337
;Show size
338
        mov     si, RamdiskSize_msg
339
        call    printplain
340
 
341
        popa
342
end if
343
 
344
}
345
 
346
macro use_free_memory
347
{
348
local _support_function_use_free_memory
349
;макрос для получения общего числа доступной памяти в кб, для формирования рам диска за пределами 1 мб.
350
;используется 0х88 функция 0х15 прерывания
351
; если поддерживается функция, то в ax значение в кб, если нет, то в ax=0
352
        mov     ah, 0x88 ;ah,0x88
353
        int     0x15
354
        jnc     ._support_function_use_free_memory
355
        xor     ax, ax
356
;возвращает в ax число в кб
357
._support_function_use_free_memory:
358
        mov     free_ad_memory, ax ; если не поддерживается биосом, то в ax=0
359
if DEBUG
360
        pushad
361
        movzx   eax, ax
362
        mov     cx, 0x0a
363
        mov     di, free_memory_msg
364
        mov     dword[ds:di], '    '
365
        mov     word [ds:di+4], '  '
366
        call    decode
367
;Show size
368
        mov     si, free_memory_msg
369
        call    printplain
370
 
371
        popad
372
end if
373
 
374
 
375
 
376
 
377
}
378
macro show_ERRORS
379
{
380
 
381
}
382
 
383
macro get_type_FS ;получить и создать образ для заданной RFS.
384
{
385
        mov     di, point_default  ;restore value
386
        mov     cx, save_cx_d
387
.start_g_tpe_RFS:
388
        call    get_firs_sym    ;get first symbol on new line
389
        test    cx, cx
390
        jz      ._end_parse_FRS ;._end_get_type_RFS     ;нету? ну ладно - следующее значение тогда )
391
        cmp     al, 'R'
392
        jnz     .start_g_tpe_RFS
393
;проверка на значения RamdiskSize
394
;        parse_RamdiskSize
395
        mov     bx, cx
396
        mov     ax, di
397
 
398
        mov     si, parse_RamdiskFS
399
        mov     cx, parse_RamdiskFS_e - parse_RamdiskFS
400
        repe cmpsb
401
        jnz     .start_g_tpe_RFS_rest_v    ;is not compare
402
 
403
        sub     bx, parse_RamdiskFS_e - parse_RamdiskFS;correct cx
404
        add     bx, cx
405
        mov     cx, bx
406
 
407
        test    status_flag, flag_found_GTRFMS          ;оценка флагов
408
        jz      .correct_is_not_set_FRS
409
 
410
;       mov     si,found_equal_timeout                          ;мы нашли что флаг уже установлен, информируем
411
;       call    printplain
412
;       jmp     .get_next_str
413
 
414
.correct_is_not_set_FRS:
415
        mov     ax, 0x3d20         ;cut al=' ' ah='='
416
        repe scasb
417
        test    cx, cx
418
        jz      .end_get_FRS_ERROR_1          ;not found param
419
 
420
        cmp     ah, byte [es:di-1]   ;find '='
421
        jnz     .start_g_tpe_RFS                        ; перейдем на начало и попробуем найти еще секцию
422
 
423
        repe scasb                 ;cut ' '
424
        inc     cx
425
        dec     di
426
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
427
;Тут нужно преобразовывать строчку в цифровое значение.
428
;;;;;;;;;;;;;;;;;;;;;;;;;;
429
        mov     bx, cx
430
        mov     ax, di
431
 
432
        mov     si, parse_RFS_FAT
433
        mov     cx, parse_RFS_FAT_e - parse_RFS_FAT
434
        repe cmpsb
435
        jnz     .krfs_cmp          ;is not compare
436
 
437
make_FAT_RamFS  ;сделать
438
 
439
if DEBUG
440
        pusha
441
        mov     si, make_fat12_RFS_msg
442
        call    printplain
443
        popa
444
end if
445
        jmp     ._end_parse_FRS
446
 
447
.krfs_cmp:
448
        mov     cx, bx
449
        mov     di, ax
450
 
451
        mov     si, parse_RFS_KRFS
452
        mov     cx, parse_RFS_KRFS_e - parse_RFS_KRFS
453
        repe cmpsb
454
;       jnz     @f         ;is not compare
455
 
456
        jmp     ._end_parse_FRS
457
 
458
 
459
.start_g_tpe_RFS_rest_v:
460
        mov     cx, bx
461
        mov     di, ax
462
        jmp     .start_g_tpe_RFS
463
 
464
 
465
 
466
.end_get_FRS_ERROR_1:
467
;сообщение об ошибке - данный участок кода не был корректно обработан :(
468
        or      show_errors_sect, show_error_1
469
        jmp     ._end_parse_FRS
470
.end_get_FRS_ERROR_2:
471
        or      show_errors_sect, show_error_2
472
 
473
._end_parse_FRS:
474
if DEBUG
475
        pusha
476
        mov     si, get_type_FS_msg
477
        call    printplain
478
        popa
479
end if
480
 
481
 
482
 
483
}
484
macro make_FAT_RamFS
485
{
486
local .RS1
487
local .fat12
488
local .fat16
489
; мы должны сформировать в начальный образ Ram FS, а потом записать его за область выше 1 мб..
490
;для случая с FAT12
491
;       mov     di,fat12_buffer ;ds должен быть = cs
492
;es:di - указывают на начало блока для формирования рам фс.
493
use_RamdiskSector       ;возращаемое значение в ax размер сектора в байтах
494
        cmp     ax, 4096;по спецификации значение должно быть в пределах от 1 до 4096
495
        ja      .RS1
496
        test    ax, ax
497
        jnz     @f      ;ошибка если сюда прыгнули все таки ...
498
 
499
.RS1:
500
        mov     word [fat12_buffer.BPB_BytsPerSec], 512
501
;;;;;;;;;;скажем что по дефолту будем юзать значение...
502
@@:
503
        mov     word [fat12_buffer.BPB_BytsPerSec], ax;тут все ок
504
 
505
;BPB_SecPerClus кол-во секторов в кластере
506
use_RamdiskCluster      ;возращаемое значение в al
507
        cmp     al, 128
508
        ja      @f
509
;       test    al,0x1  ;проверка на кратность )
510
;       jnz     @f
511
 
512
        mov     byte [fat12_buffer.BPB_SecPerClus], al
513
 
514
        ;incorrect value will be set dafault
515
 
516
;ниже некорректное значение в т.к. размер кратен 2 и в диапазоне от 1 до 128 включительно
517
; мы должны ругнуться на это
518
;@@:    ;mov    byte [fat12_buffer.BPB_SecPerClus],1
519
 
520
;;;;; определеим какая у нас будет использоваться FAT
521
;по условию, fat12<4085<=fat16<65525<=fat32
522
; fat12_buffer.BPB_BytsPerSec*fat12_buffer.BPB_SecPerClus = кол-во секторов
523
        movzx   eax, word [fat12_buffer.BPB_BytsPerSec]
524
        movzx   ebx, byte [fat12_buffer.BPB_SecPerClus]
525
 
526
        imul    ebx, eax;тут размерность сектора
527
        mov     eax, save_ramdisksize ;размер запрошенного рам диска в байтах
528
        cdq
529
        idiv    ebx
530
;;;;;;;; сейчас частное в eax, а остаток в edx
531
;получим кол-во секторов, и можем уже определить тип FAT которую нужно делать.
532
        cmp     eax, 4085
533
        jb      .fat12
534
        cmp     eax, 65525
535
        jb      .fat16
536
;;;;;;;;;;;;;;;;;;;;;;;; тут fat32
537
        mov     set_ramfs, 32   ;установим тип файловой системы
538
        mov     word [fat12_buffer.BPB_RsvdSecCnt], 32
539
        xor     eax, eax
540
        mov     word [fat12_buffer.BPB_RootEntCnt], ax
541
        mov     word [fat12_buffer.BPB_TotSec16], ax
542
        mov     dword [fat12_buffer.BPB_TotSec32], eax
543
 
544
 
545
.fat16: ;fat16
546
;Для FAT12 и FAT16 дисков это поле содержит количество секторов, а BPB_TotSec32 равно 0, если значение <умещается> (меньше 0x10000).
547
        jmp     $
548
        mov     set_ramfs, 16   ;установим тип файловой системы
549
        movzx   ebx, byte [fat12_buffer.BPB_SecPerClus]
550
        imul    eax, ebx
551
 
552
        cmp     eax, 0x10000
553
        jae     @f
554
        mov     word [fat12_buffer.BPB_TotSec16], ax
555
        mov     dword [fat12_buffer.BPB_TotSec32], 0
556
@@:
557
;количество секторов занимаемое одной копией фат
558
;       mov     word [fat12_buffer.BPB_FATSz16],0x9     ;Для FAT12/FAT16 это количество секторов одной FAT. ??
559
;;;; заполним BPB_RootEntCnt Для FAT12 и FAT16 дисков, это поле содержит число
560
;32-байтных элементов корневой директории. Для FAT32 дисков, это поле должно
561
;быть 0. Пока константа, нужно будет позже доделать.
562
        mov     eax, root_dir_entry_count
563
        mov     word [fat12_buffer.BPB_RootEntCnt], ax  ; count of 32-byte dir. entries (224*32 = 14 sectors= 7 kb)
564
;по документации рекомендуют отрезать 16 кб для рут дир но это оч много, даже для коос. имхо для начала хватит и 7 кб
565
;;;;;;;
566
;Для FAT16 это количество секторов одной FAT. Для FAT32 это значение
567
;равно 0, а количество секторов одной FAT содержится в BPB_FATSz32.
568
;RootDirSectors = ((BPB_RootEntCnt * 32) + (BPB_BytsPerSec - 1)) / BPB_BytsPerSec;
569
 
570
;TmpVal1 = DskSize - (BPB_ResvdSecCnt + RootDirSectors);
571
;TmpVal2 = (256 * BPB_SecPerClus) + BPB_NumFATs;
572
;If(FATType == FAT32)
573
;    TmpVal2 = TmpVal2 / 2;
574
;FATSz = (TMPVal1 + (TmpVal2 - 1)) / TmpVal2;
575
;If(FATType == FAT32) {
576
;    BPB_FATSz16 = 0;
577
;    BPB_FATSz32 = FATSz;
578
;} else {
579
;    BPB_FATSz16 = LOWORD(FATSz);
580
;    /* there is no BPB_FATSz32 in a FAT16 BPB */
581
;}
582
;=====================================
583
;RootDirSectors
584
        movzx   ebx, word [fat12_buffer.BPB_BytsPerSec]
585
        imul    eax, 32
586
        add     eax, ebx
587
        dec     eax
588
 
589
        cdq
590
        idiv    ebx
591
;;;;;;;; сейчас частное в eax, а остаток в edx для дискеты 1.44 у нас должно быть значение =14
592
;BPB_ResvdSecCnt + RootDirSectors
593
        movzx   ebx, word [fat12_buffer.BPB_RsvdSecCnt]
594
        add     ebx, eax
595
 
596
;DskSize у нас это значение уже получено и доступно
597
        movzx   eax, word [fat12_buffer.BPB_TotSec16]   ;должен быть в секторах
598
        sub     eax, ebx
599
 
600
 
601
;TmpVal1=eax
602
        shl     edi, 8  ;=edi*256
603
        movzx   ecx, byte [fat12_buffer.BPB_NumFATs]
604
        add     edi, ecx
605
;TmpVal2=edi
606
        add     eax, edi
607
        dec     eax
608
        cdq
609
        idiv    edi
610
;FATSz = сейчас частное в eax, а остаток в edx
611
        mov     word [fat12_buffer.BPB_FATSz16], ax
612
 
613
 
614
 
615
 
616
 
617
 
618
 
619
 
620
.fat12: ;fat12
621
if DEBUG
622
; выведем в отладке, что собираемся делать образ диска c FS=fat12
623
        pushad
624
        mov     si, start_making_FAT12_msg
625
        call    printplain
626
        popad
627
end if
628
 
629
 
630
 
631
;Для FAT12 и FAT16 дисков это поле содержит количество секторов, а BPB_TotSec32 равно 0, если значение <умещается> (меньше 0x10000).
632
        mov     set_ramfs, 12   ;установим тип файловой системы
633
        movzx   ebx, byte [fat12_buffer.BPB_SecPerClus]
634
        imul    eax, ebx
635
 
636
        cmp     eax, 0x10000
637
        jae     @f
638
        mov     word [fat12_buffer.BPB_TotSec16], ax
639
        mov     dword [fat12_buffer.BPB_TotSec32], 0
640
@@:
641
;количество секторов занимаемое одной копией фат
642
;       mov     word [fat12_buffer.BPB_FATSz16],0x9     ;Для FAT12/FAT16 это количество секторов одной FAT. ??
643
;;;; заполним BPB_RootEntCnt Для FAT12 и FAT16 дисков, это поле содержит число
644
;32-байтных элементов корневой директории. Для FAT32 дисков, это поле должно
645
;быть 0. Пока константа, нужно будет позже доделать.
646
        mov     eax, root_dir_entry_count
647
        mov     word [fat12_buffer.BPB_RootEntCnt], ax  ; count of 32-byte dir. entries (224*32 = 14 sectors= 7 kb)
648
;по документации рекомендуют отрезать 16 кб для рут дир но это оч много, даже для коос. имхо для начала хватит и 7 кб
649
;;;;;;;
650
;DskSize(в секторах)*12 (размерность файловой системы, т.е предположим сколько битов потребуется для адресации этого объема) /8 (что получить размер в байтах)
651
;полученное число округляем в большую сторону кратное сектору т.е. 512 байт Такой подход не универсален, но пока пойдет
652
;вообще у мелкософт это все считается ручками, но мы будем юзать только под коос рам диск с фат12
653
        movzx   eax, word [fat12_buffer.BPB_TotSec16]
654
        imul    eax, 12
655
        shr     eax, 3  ;делим на 8 но т.е. нам нужно делить еще и на 512 или более в зависимости от размеров кластера
656
        movzx   ebx, word [fat12_buffer.BPB_BytsPerSec] ;размер сектора
657
        cdq
658
        idiv    ebx     ;разделим на размер кластера
659
;сейчас у нас в eax значение его нужно округлить в большую сторону кратному 512 байтам
660
;применим следующее очистим and и добавим 512 байт. таким образом выравним на 512 байт
661
;но т.к. все равно делить нижний код нам не нужен
662
;       and     eax,0xfff200
663
;       add     eax,0x200       ;добавим 512 байт        для 1.44 дискеты идеально подходит ))
664
 
665
        inc     ax
666
;по идее должно на каждую фат таблицу
667
;резервироваться 9 секторов т.е. получается 2*9=18+1 =19 секторов т.е. рут дир находиться на с 20 сетора т.е. с адреса 0х2600
668
;сейчас нужно вычислить сколько будет секторов занимать фат ) нужно разделить на 512
669
;FATSz = сейчас частное в eax
670
        mov     word [fat12_buffer.BPB_FATSz16], ax
671
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
672
get_firstDataSector ;получить смещение до данных
673
;создадим певую запись в фат по определенному адресу.
674
first_create_fat_table
675
;закиним BPB файловой системы за 1 мб.
676
use_BPB_RAM
677
;
678
;копирование файла.
679
use_RamdiskFile
680
 
681
;;;; вычисляем указатель на корневую дир FirstRootDirSecNum = BPB_ResvdSecCnt + (BPB_NumFATs * BPB_FATSz16);
682
;       movzx   ebx, [fat12_buffer.BPB_NumFATs]
683
;       movzx   eax,ax
684
;       imul    eax,ebx
685
;eax=(BPB_NumFATs * BPB_FATSz16)
686
;       inc     eax
687
; BPB_ResvdSecCnt значение только 1 для fat12/16
688
;в eax указатель на root dir. для дискеты fat12 должно получиться при кол-во копий fat 1  = 1+ (1*1) =2 или 3
689
 
690
if DEBUG
691
        pusha
692
;       mov     ax,point_default
693
;        mov     ax,cx
694
        mov     cx, 0x0a
695
        mov     di, show_db1
696
;        mov     dword[ds:di],'    '
697
;       mov     word [ds:di+4],'  '
698
        call    decode
699
;Show size
700
        mov     si, show_db1
701
        call    printplain
702
;
703
;       xor     ax,ax
704
;       int     0x16
705
        popa
706
end if
707
 
708
 
709
 
710
 
711
 
712
 
713
 
714
}
715
 
716
macro use_RamdiskSector
717
{
718
;для некоторых FS будет игнорироваться
719
        mov     di, point_default  ;restore value
720
        mov     cx, save_cx_d
721
 
722
.start_RamdiskSector:
723
        call    get_firs_sym    ;get first symbol on new line
724
        test    cx, cx
725
        jz      .end_RamdiskSector      ;нету? ну ладно - следующее значение тогда )
726
 
727
        cmp     al, 'R'
728
        jnz     .start_RamdiskSector
729
;проверка на значения RamdiskSize
730
;        parse_RamdiskSize
731
 
732
        mov     bx, cx
733
        mov     ax, di
734
 
735
        mov     si, parse_RamdiskSector
736
        mov     cx, parse_RamdiskSector_e - parse_RamdiskSector
737
        repe cmpsb
738
        jnz     .RamdiskSector_rest_val    ;is not compare
739
 
740
        sub     bx, parse_RamdiskSector_e - parse_RamdiskSector;correct cx
741
        add     bx, cx
742
        mov     cx, bx
743
 
744
        test    status_flag, flag_found_RamdiskSector           ;оценка флагов
745
        jz      .correct_is_not_set_RamdiskSector
746
 
747
;       mov     si,found_equal_timeout                          ;мы нашли что флаг уже установлен, информируем
748
;       call    printplain
749
;       jmp     .get_next_str
750
 
751
.correct_is_not_set_RamdiskSector:
752
        mov     ax, 0x3d20         ;cut al=' ' ah='='
753
        repe scasb
754
        jcxz    .end_get_RamS_ERROR_1          ;not found param
755
 
756
        cmp     ah, byte [es:di-1]   ;find '='
757
        jnz     .start_RamdiskSector                    ; перейдем на начало и попробуем найти еще секцию
758
 
759
        repe scasb                 ;cut ' '
760
        inc     cx
761
        dec     di
762
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
763
        xor     bx, bx
764
        mov     cx, 4
765
@@:
766
        movzx   ax, byte [es:di]
767
        cmp     al, '0'
768
        jb      .end_RamdiskSector
769
        cmp     al, '9'
770
        ja      .end_RamdiskSector
771
;;;;;;;;;;;;;;;;;;;
772
 
773
        imul    bx, 10
774
        xor     al, 0x30
775
        add     bx, ax
776
 
777
        inc     di
778
 
779
        loop    @b
780
        jmp     .end_RamdiskSector
781
 
782
 
783
.RamdiskSector_rest_val:
784
        mov     cx, bx
785
        mov     di, ax
786
        jmp     .start_RamdiskSector
787
.end_get_RamS_ERROR_1:
788
 
789
.end_RamdiskSector:
790
        mov     ax, bx
791
 
792
if DEBUG
793
        pusha
794
        movzx   eax, bx;save_cx_d;point_default
795
        mov     cx, 0x0a
796
        mov     di, RamdiskSector_msg
797
        mov     dword[ds:di], '    '
798
        mov     dword [ds:di+4], '    '
799
        call    decode
800
;Show size
801
        mov     si, RamdiskSector_msg
802
        call    printplain
803
 
804
        popa
805
end if
806
 
807
;       pop     di
808
;       pop     es
809
}
810
 
811
macro use_RamdiskCluster
812
{
813
;для некоторых FS будет игнорироваться
814
;       push    es
815
;       push    di
816
        mov     di, point_default  ;restore value
817
        mov     cx, save_cx_d
818
;       push    ini_data_
819
;       pop     es
820
.start_RamdiskCluster:
821
        call    get_firs_sym    ;get first symbol on new line
822
        test    cx, cx
823
        jz      .end_RamdiskCluster     ;нету? ну ладно - следующее значение тогда )
824
        cmp     al, 'R'
825
        jnz     .start_RamdiskCluster
826
;проверка на значения RamdiskSize
827
;        parse_RamdiskSize
828
 
829
        mov     bx, cx
830
        mov     ax, di
831
 
832
        mov     si, parse_RamdiskCluster
833
        mov     cx, parse_RamdiskCluster_e - parse_RamdiskCluster
834
        repe cmpsb
835
        jnz     .RamdiskCluster_rest_val           ;is not compare
836
 
837
        sub     bx, parse_RamdiskCluster_e - parse_RamdiskCluster;correct cx
838
        add     bx, cx
839
        mov     cx, bx
840
 
841
        test    status_flag, flag_found_RamdiskCluster          ;оценка флагов
842
        jz      .correct_is_not_set_RamdiskCluster
843
 
844
;       mov     si,found_equal_timeout                          ;мы нашли что флаг уже установлен, информируем
845
;       call    printplain
846
;       jmp     .get_next_str
847
 
848
.correct_is_not_set_RamdiskCluster:
849
        mov     ax, 0x3d20         ;cut al=' ' ah='='
850
        repe scasb
851
        jcxz    .end_get_RamSC_ERROR_1          ;not found param
852
 
853
        cmp     ah, byte [es:di-1]   ;find '='
854
        jnz     .start_RamdiskCluster                   ; перейдем на начало и попробуем найти еще секцию
855
 
856
        repe scasb                 ;cut ' '
857
        inc     cx
858
        dec     di
859
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
860
@@:
861
        movzx   ax, byte [es:di]
862
        cmp     al, '0'
863
        jb      .end_RamdiskCluster
864
        cmp     al, '9'
865
        ja      .end_RamdiskCluster
866
;;;;;;;;;;;;;;;;;;;
867
        xor     al, 0x30
868
 
869
        jmp     .end_RamdiskCluster
870
 
871
 
872
.RamdiskCluster_rest_val:
873
        mov     cx, bx
874
        mov     di, ax
875
        jmp     .start_RamdiskCluster
876
.end_get_RamSC_ERROR_1:
877
 
878
.end_RamdiskCluster:
879
if DEBUG
880
        pusha
881
        mov     cx, 0x0a
882
        mov     di, RamdiskCluster_msg
883
;        mov     word[ds:di],'  '
884
        call    decode
885
;Show size
886
        mov     si, RamdiskCluster_msg
887
        call    printplain
888
 
889
        popa
890
end if
891
 
892
}
893
 
894
macro use_Loader_Image
895
;предназначен для загрузки образов выше 1 Мб.
896
;первоначальная версия загружает образ дискеты 1.44 мб
897
{
898
local .start_p_LI
899
local .exit
900
local .error_LI
901
local .rest_value_loop
902
local .found_end_str
903
        mov     di, point_default  ;restore value
904
        mov     cx, save_cx_d
905
;обработка конструкции типа LoaderModule=kord/kolibri.ldm
906
.start_p_LI:
907
        call    get_firs_sym    ;get first symbol on new line
908
        test    cx, cx
909
        jz      .exit   ;нету? ну ладно - следующее значение тогда )
910
        cmp     al, 'L'
911
        jnz     .start_p_LI
912
;проверка на значение LoaderModule
913
;        parse_LoaderModule
914
        mov     bx, cx
915
        mov     ax, di
916
 
917
        mov     si, parse_LoaderImage
918
        mov     cx, parse_LoaderImage_e - parse_LoaderImage
919
        repe cmpsb
920
        jnz     .rest_value_loop           ;is not compare
921
 
922
        sub     bx, parse_LoaderImage_e - parse_LoaderImage;correct cx
923
        add     bx, cx
924
        mov     cx, bx
925
 
926
;       test    status_flag,flag_found_LM               ;оценка флагов
927
;       jz      .correct_is_not_set_LI
928
 
929
;       mov     si,found_equal_timeout                          ;мы нашли что флаг уже установлен, информируем
930
;       call    printplain
931
;       jmp     .get_next_str
932
 
933
;.correct_is_not_set_LI:
934
        mov     ax, 0x3d20         ;cut al=' ' ah='='
935
        repe scasb
936
        jcxz    .rest_value_loop_LI          ;not found param timeout
937
 
938
        cmp     ah, byte [es:di-1]   ;find '='
939
        jnz     .rest_value_loop_LI
940
 
941
        repe scasb                 ;cut ' '
942
        inc     cx
943
        dec     di
944
;di указывает на начало блока информации, в cx длинна до конца секции.
945
;после загрузки заноситься значение занятой памяти.
946
;для того что бы загрузить модуль, воспользуемся callback сервисом
947
;оригинальное решение - разместим dd перед строчкой и после строчки разместим byte =0
948
;это выглядит так: в ini файле существует строчка LoaderModule = kord/kernel.loader
949
;мы ее модифицируем до такого состояния       dw,dw,db'kord/kernel.loader',0 конечно сохранив те значения которые мы заменяем
950
;сохранили певые 2 word
951
        push    dword [es:di-6]
952
        lea     si, [di-6]
953
 
954
        push    word [es:di-2]
955
        xor     ax, ax
956
        mov     word [es:di-6], ax      ;вносим нужные значения
957
;info_real_mode_size размер и указатель на область в которую можно загрузиться
958
        mov     ax, info_real_mode_size ;0x3000   ;следующий сегмент за данными
959
 
960
 
961
        mov     word [es:di-4], ax
962
        mov     word [es:di-2], 16      ;кол-во блоков по 4 кб =64 кб т.е. больше не считаем
963
;;;;;; поиск конца строчки
964
@@:
965
        mov     al, byte [es:di]
966
        cmp     al, ' '
967
        jz      .found_end_str
968
        cmp     al, 0xa
969
        jz      .found_end_str
970
        cmp     al, 0xd
971
        jz      .found_end_str
972
        inc     di
973
        dec     cx
974
        jnz     @b
975
;;;not found допустим,что это конец файла и он не имеет привычного заверешния строки
976
.found_end_str:
977
; чтение блока по 64 кб в сегмент и забрасывание его выше 1 мб.
978
        push    word [es:di]
979
        xor     ax, ax
980
        mov     word [es:di], ax
981
;        xor     ax,ax   ; function 1 - read file
982
        mov     di, si  ;file_data
983
        inc     ax
984
        push    si
985
        push    es
986
        call    far dword [loader_callback]
987
        push    cs
988
        pop     ds
989
 
990
        pop     es
991
        pop     si
992
 
993
        test    bx, bx
994
        jnz     .error_LM
995
 
996
 
997
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; забрасывание блока в 64 кб выше 1 мб.
998
        mov     si, table_15_87
999
        push    es
1000
        push    ds
1001
        pop     es
1002
        mov     cx, 256*18
1003
        mov     ah, 0x87
1004
        int     0x15
1005
        pop     es
1006
        pop     dx cx
1007
        test    ah, ah
1008
 
1009
 
1010
 
1011
        jmp     far dword [es:si]
1012
 
1013
 
1014
 
1015
 
1016
.rest_value_loop:
1017
        mov     di, ax
1018
        mov     cx, bx
1019
        jmp     .start_p_LI
1020
 
1021
.exit:
1022
 
1023
 
1024
 
1025
}
1026
 
1027
 
1028
 
1029
macro name_in_root_fat
1030
;макрос, который записывает информацию о загруженном файле в корневую фат таблицу
1031
{
1032
 
1033
}
1034
 
1035
 
1036
 
1037
macro use_RamdiskFile
1038
{
1039
;загрузка файлов с использование callback сервиса первичного загрузчика
1040
;используется только для загрузки необходимых и небольших файлов, т.к. достаточно медленно работает
1041
;для загрузки использует 0х87 функцию int 0x15 прерывания - загрузка блоков данных до 64 кб выше 1 мб
1042
local   .start_loop
1043
local   ._end
1044
local   .rest_value_loop
1045
local   .error
1046
        mov     di, point_default  ;restore value
1047
        mov     cx, save_cx_d
1048
        mov     data_offset, 0  ;clean offset
1049
;обработка конструкции типа LoaderModule=kord/kolibri.ldm
1050
.start_loop:
1051
        call    get_firs_sym    ;get first symbol on new line
1052
        test    cx, cx
1053
        jz      ._end   ;нету? ну ладно - следующее значение тогда )
1054
        cmp     al, 'R'
1055
        jnz     .start_loop
1056
;проверка на значение RamdiskFile
1057
        mov     bx, cx
1058
        mov     ax, di
1059
 
1060
        mov     si, parse_RamdiskFile
1061
        mov     cx, parse_RamdiskFile_e - parse_RamdiskFile
1062
        repe cmpsb
1063
        jnz     .rest_value_loop           ;is not compare
1064
 
1065
        sub     bx, parse_RamdiskFile_e - parse_RamdiskFile;correct cx
1066
        add     bx, cx
1067
        mov     cx, bx
1068
;       test    status_flag,flag_found_LM               ;оценка флагов
1069
;       jz      .correct_is_not_set_LM
1070
 
1071
;       mov     si,found_equal_timeout                          ;мы нашли что флаг уже установлен, информируем
1072
;       call    printplain
1073
;       jmp     .get_next_str
1074
 
1075
;.correct_is_not_set_LM:
1076
        mov     ax, 0x3d20         ;cut al=' ' ah='='
1077
        repe scasb
1078
        test    ecx, ecx
1079
        jz      .rest_value_loop   ;not found param timeout
1080
 
1081
        cmp     ah, byte [es:di-1] ;find '='
1082
        jnz     .rest_value_loop
1083
 
1084
        repe scasb                 ;cut ' '
1085
        inc     cx
1086
        dec     di
1087
 
1088
        mov     save_di_RAMDISK, di
1089
        mov     save_cx_RAMDISK, cx
1090
;di указывает на начало блока информации, в cx длинна до конца секции.
1091
;после загрузки заноситься значение занятой памяти.
1092
;для того что бы загрузить модуль, воспользуемся callback сервисом
1093
;оригинальное решение - разместим dd перед строчкой и после строчки разместим byte =0
1094
;это выглядит так: в ini файле существует строчка RamdiskFile = @menu,@menu
1095
;мы ее модифицируем до такого состояния       dw,dw,db'@menu',0 конечно сохранив те значения которые мы заменяем
1096
;сохранили певые 2 word
1097
 
1098
;
1099
@@:
1100
        mov     al, byte [es:di]
1101
        cmp     al, ','         ; т.е. ищем разделитель
1102
        jz      .found_end_str
1103
        inc     di
1104
        dec     cx
1105
        jnz     @b
1106
;;;not found допустим,что это конец файла и он не имеет привычного завершения строки
1107
.found_end_str:
1108
;        mov    al,byte [es:di]
1109
;       cmp     al,' '          ; убираем пробелы, если они есть
1110
;       jnz     @f
1111
;       inc     di
1112
;       dec     cx
1113
;       jnz     .found_end_str
1114
 
1115
;@@:
1116
        mov     point_to_dest_file_name, di
1117
        inc     di
1118
;проверка индивидуальности имени файла
1119
check_name_file
1120
;/restore di - point and cx -size section
1121
        mov     di, save_di_RAMDISK
1122
        mov     cx, save_cx_RAMDISK
1123
 
1124
        test    al, al
1125
        jnz     .start_loop     ;если в al значение не =0, то такое имя уже существует в системе.
1126
 
1127
 
1128
 
1129
        push    dword [es:di-6]
1130
        lea     si, [di-6]
1131
 
1132
        push    word [es:di-2]
1133
        push    di
1134
        xor     ax, ax
1135
        mov     word [es:di-6], ax      ;вносим нужные значения
1136
;info_real_mode_size размер и указатель на область в которую можно загрузиться
1137
        mov     ax, info_real_mode_size ;0x3000   ;следующий сегмент за данными
1138
 
1139
 
1140
        mov     word [es:di-4], ax
1141
        mov     word [es:di-2], 16      ;кол-во блоков по 4 кб =64 кб т.е. больше не читаем
1142
 
1143
        mov     di, point_to_dest_file_name
1144
 
1145
if DEBUG
1146
        pushad
1147
;       mov     ax,di
1148
        mov     cx, 0x0a
1149
        mov     di, name_of_seg_get_64
1150
        mov     dword[ds:di], '    '
1151
        mov     word[ds:di+4], '  '
1152
        call    decode
1153
;Show size
1154
        mov     si, name_of_seg_get_64
1155
        call    printplain
1156
 
1157
        popad
1158
end if
1159
 
1160
        push    word [es:di]
1161
        push    cx
1162
        xor     ax, ax
1163
        mov     word [es:di], ax
1164
;        xor     ax,ax   ; function 1 - read file
1165
        push    di
1166
        mov     di, si  ;file_data
1167
        inc     ax
1168
        push    si
1169
        push    es
1170
        push    bp
1171
 
1172
        push    es
1173
        pop     ds
1174
        push    cs
1175
        pop     es
1176
 
1177
        call    far dword [es:loader_callback]
1178
 
1179
 
1180
        push    cs
1181
        pop     ds
1182
 
1183
        pop     bp
1184
        pop     es
1185
        pop     si
1186
 
1187
        cmp     bx, 2
1188
        ja      .error
1189
; сейчас у нас в dx:ax размер файла, который мы загрузили.
1190
; возможна ситуация, когда в bx=1 т.е. есть еще данные на диске
1191
        mov     status_flag_loader_f, bx
1192
 
1193
        shl     edx, 16
1194
        mov     dx, ax
1195
;       shr     edx,10  ;размер файла в кб.
1196
;;в edx размер в байтах.
1197
        mov     save_file_size, edx
1198
        mov     eax, edx
1199
;восстановим полностью файл сценария
1200
        pop     di
1201
        pop     cx      ;длинна остатка с 2-ой частью имени т.е. с именем назначением.
1202
        pop     word [es:di]
1203
        pop     di
1204
        pop     word [es:di-2]
1205
        pop     dword [es:di-6]
1206
 
1207
 
1208
if DEBUG
1209
        pushad
1210
        mov     cx, 0x0a
1211
        mov     di, RamdiskFile_msg
1212
        mov     dword[ds:di], '    '
1213
        call    decode
1214
;Show size
1215
        mov     si, RamdiskFile_msg
1216
        call    printplain
1217
 
1218
        popad
1219
end if
1220
 
1221
 
1222
 
1223
 
1224
 
1225
 
1226
 
1227
 
1228
 
1229
 
1230
; загрузим чему у нас равен кластер
1231
;       mov     ax,word [fat12_buffer.BPB_BytsPerSec] ;кол-во байтов в секторе может быть любое 512 1024 2048 4096 2 байта
1232
;       movzx   bx,byte [fat12_buffer.BPB_SecPerClus] ;кол-во секторов в кластере
1233
;       imul    ax,bx
1234
;сейчас в eax размер кластера (512) байт
1235
;в edx длина файла в байтах до 64 кб
1236
;закиним файл за 1 мб
1237
;1 нам нужно составить фат таблицу т.е. произвести разметку рамдиска, затем перенесем по адресу файл
1238
 
1239
;записать инфорамацию о файле в корневую директорию
1240
register_file_in_fat
1241
;перенести за 1 мб содержимое файла
1242
move_file_up
1243
 
1244
;проверим, загружен ли до конца файл? т.е. если размер файла больше чем 64 кб, то будет подгружать оставшиеся блоки
1245
        cmp     status_flag_loader_f, 0x1
1246
        jnz     @f
1247
;нужно дозагузить данные файла и перенести их за 1-ый мб согласно фат структуре
1248
 
1249
 
1250
 
1251
 
1252
 
1253
 
1254
 
1255
 
1256
 
1257
@@:
1258
;тут организован цикл по загрузке файлов в корневую директорию
1259
        mov     di, save_di_RAMDISK
1260
        mov     cx, save_cx_RAMDISK
1261
if DEBUG
1262
        pusha
1263
        xor     ax, ax
1264
        int     0x16
1265
        popa
1266
end if
1267
 
1268
 
1269
        jmp     .start_loop
1270
 
1271
 
1272
.error:
1273
        ;call   error.LoaderModule
1274
;fixme!
1275
.rest_value_loop:
1276
        mov     di, ax
1277
        mov     cx, bx
1278
        jmp     .start_loop
1279
 
1280
._end:
1281
;перенесем за 1-ый мб фат и рут дир
1282
move_up_fat_and_root_d
1283
 
1284
 
1285
 
1286
 
1287
 
1288
 
1289
;загрузка блока
1290
;       mov     ah,0x87
1291
;       mov     cx,     ;size in byte
1292
 
1293
 
1294
;es:si point to descripts
1295
 
1296
 
1297
}
1298
 
1299
macro use_BPB_RAM ;закинуть самые первые 512 байт за 1-й мб
1300
;данный макрос закидывает BPB структуру т.е. первые 512 байт, пока только фат12 за 1 мб
1301
{
1302
        mov     ax, fat12_buffer
1303
        mov     si, table_15_87
1304
        add     word [si+8*2+2], ax
1305
        push    es
1306
        push    ds
1307
        pop     es
1308
        mov     cx, 256  ;бут сектор  укладывается в 512 байт 512/2=256
1309
        mov     ah, 0x87
1310
        int     0x15
1311
        pop     es
1312
;add 512 byte for destination adress
1313
;       add     dword [si+8*3+2], 512
1314
;        test    ah, ah
1315
;        jz
1316
if DEBUG
1317
        pusha
1318
        mov     ax, word [si+8*2+2]
1319
        mov     cx, 0x0a
1320
        mov     di, BPB_msg
1321
        call    decode
1322
;Show size
1323
        mov     si, BPB_msg
1324
        call    printplain
1325
        popa
1326
end if
1327
}
1328
macro first_create_fat_table
1329
;данный макрос создает оформляет 3 первых байта fat таблицы, и устанавливает указатель на следующий блок, и вносит 0 значение
1330
;для смещения в корневой таблице.
1331
{
1332
        mov     al, byte [fat12_buffer.BPB_Media]
1333
 
1334
 
1335
        push    ds
1336
 
1337
 
1338
        mov     di, info_real_mode_size
1339
        add     di, 0x1000
1340
 
1341
if DEBUG
1342
        pushad
1343
 
1344
        mov     ax, info_real_mode_size
1345
        add     ax, 0x1000
1346
;       mov     ax,ds
1347
        mov     cx, 0xa
1348
 
1349
        mov     di, first_entry_in_fat
1350
        mov     dword [di], '    '
1351
        mov     word [di+4], '  '
1352
        call    decode
1353
;Show size
1354
        mov     si, first_entry_in_fat
1355
        call    printplain
1356
 
1357
        xor     ax, ax
1358
        int     0x16
1359
 
1360
        popad
1361
end if
1362
 
1363
 
1364
        push    di   ;  push    word info_real_mode_size+0x1000   ;cледующий сегмент за загруженным участком
1365
 
1366
        xor     di, di
1367
        mov     point_to_free_root, di  ;значение смещения =0 в корневой фат таблице описания
1368
 
1369
        pop     ds   ; загружен следующий сегмент т.е. пустой сегмент
1370
 
1371
        mov     byte [di], al
1372
        or      ax, -1
1373
        inc     di
1374
        mov     word [di], ax
1375
 
1376
        pop     ds
1377
        mov     point_next_fat_str, 3
1378
 
1379
if DEBUG
1380
        pushad
1381
        mov     ax, point_next_fat_str
1382
        mov     cx, 0x0a
1383
        mov     di, fat_create_msg
1384
        call    decode
1385
;Show size
1386
        mov     si, fat_create_msg
1387
        call    printplain
1388
        popad
1389
end if
1390
 
1391
}
1392
macro register_file_in_fat
1393
;макрос регистрации файла в файловой структуре Fat
1394
;пока поддерживается только фат12, пока ))
1395
;вычисление смежных кластеров и занесение инфы в fat/
1396
{
1397
local   .step2
1398
local   .step3
1399
local   .end
1400
local   .eof_file
1401
 
1402
;di point on root dir на фри секцию.
1403
        push    es
1404
 
1405
        mov     ax, info_real_mode_size
1406
        add     ax, 0x1000
1407
        mov     es, ax ;        push    word info_real_mode_size+0x1000   ;сегмент следующий за загруженным блоком в 64 кб
1408
 
1409
; определяем тип фат пока не определяем, пока только фат 12
1410
; 12 бит, для вычесления соседних каластеров.
1411
        mov     di, firstDataSect    ;в секторах
1412
        sub     di, size_root_dir
1413
;теперь в ax размер в секторах начала рут дир
1414
        shl     di, 9;imul 512
1415
        add     di, point_to_free_root  ;смещение в уже записанных 32-х структурах.
1416
;необходимо внести значение в рут дир т.е. 32 байта
1417
if DEBUG
1418
        pushad
1419
;       mov     ax,point_default
1420
;        mov     ax,
1421
        mov     cx, 0x0a
1422
        mov     di, show_db2
1423
        mov     dword[ds:di], '    '
1424
        mov     word [ds:di+4], '  '
1425
        call    decode
1426
;Show size
1427
        mov     si, show_db2
1428
        call    printplain
1429
;
1430
;       xor     ax,ax
1431
;       int     0x16
1432
        popad
1433
end if
1434
 
1435
 
1436
 
1437
;gs:di - указатель для внесения инфорации в рут область фат таблицы инормации о файле.
1438
        mov     si, shot_name_fat
1439
        mov     cx, 11
1440
;запишем в структуру имя
1441
@@:
1442
        lodsb
1443
        stosb
1444
        loop    @b
1445
 
1446
;запишем атрибуты файла и DIR_NTRes - зарезеврированный байт =0
1447
        xor     ax, ax
1448
        mov     ah, ATTR_VOLUME_ID
1449
        mov     word [es:di], ax
1450
        add     di, 2
1451
;DIR_CrtTimeTenth
1452
        mov     byte [es:di], 100
1453
        inc     di
1454
;DIR_CrtTime
1455
        mov     word [es:di], 0x032b   ;дата
1456
        add     di, 2
1457
;DIR_CrtDate
1458
        mov     word [es:di], 0x0      ;время ><
1459
        add     di, 2
1460
;DIR_LstAccDate
1461
        mov     word [es:di], 0x032b   ;дата моего
1462
        add     di, 2
1463
;DIR_FstClusHI
1464
        mov     word [es:di], 0x0      ;время для фат12 /16 всегда 0
1465
        add     di, 2
1466
;DIR_WrtTime
1467
        mov     word [es:di], 0x0      ;время ><
1468
        add     di, 2
1469
;DIR_WrtDate
1470
        mov     word [es:di], 0x032b
1471
        add     di, 2
1472
 
1473
        mov     ax, point_next_fat_str
1474
        mov     word [es:di], ax
1475
        add     di, 2
1476
 
1477
        push    di
1478
;DIR_FstClusLO                  Младшее слово номера первого кластера.
1479
 ;       mov     ax,point_next_fat_str   ;загрузим указатель на элемент фат таблицы т.е. это номер фат записи
1480
;FATOffset = N + (N / 2) т.е. это уже у нас смещение мы знаем что -начинается все с 3-го элемента записи фат
1481
        mov     bx, ax
1482
        shr     bx, 1
1483
        add     ax, bx
1484
;в ах сейчас FATOffset
1485
;ThisFATEntOffset = BPB_ResvdSecCnt + (FATOffset / BPB_BytsPerSec);
1486
        mov     bx, word [fat12_buffer.BPB_BytsPerSec]
1487
        cwd
1488
        idiv    bx
1489
;ax=ThisFATEntOffset= rem (FATOffset / BPB_BytsPerSec) четный или нечетный указатель.
1490
        mov     si, ax
1491
;нам нужно в цикле записать все кластеры которые будут использованы для размещения файла.
1492
;узнаем размер кластера.
1493
        movzx   eax, word [fat12_buffer.BPB_BytsPerSec]
1494
        movzx   ebx, byte [fat12_buffer.BPB_SecPerClus]
1495
        imul    eax, ebx
1496
;ax - размер кластера.
1497
;сейчас будем записывать во временный буфер фат таблицу для выбранного файла. Поскольку мы его загрузили возможно не полностью
1498
;мы обработаем запись для фат полностью, в не зависимости от предела буфера где возможна часть файла.
1499
        mov     ebx, save_file_size     ;размер файла в байтах
1500
 
1501
@@:
1502
        sub     ebx, eax
1503
        cmp     ebx, eax
1504
        jbe     .eof_file
1505
 
1506
        inc     point_next_fat_str
1507
        mov     cx, point_next_fat_str  ;загрузим указатель на элемент фат таблицы т.е. это номер фат записи
1508
;FATOffset = N + (N / 2) т.е. это уже у нас смещение мы знаем что -начинается все с 3-го элемента записи фат
1509
        mov     dx, ax
1510
        shr     dx, 1
1511
        add     cx, dx
1512
 
1513
 
1514
 
1515
        test    si, 0x1
1516
        jz      .step2
1517
        shl     cx, 4
1518
        mov     word[es:si], cx
1519
        inc     si
1520
        add     cx, ax
1521
        jmp     @b
1522
 
1523
.step2:
1524
        and     cx, 0x0FFF
1525
        mov     word[es:si], cx
1526
        inc     si
1527
        add     cx, ax
1528
        jmp     @b
1529
 
1530
.eof_file:
1531
        mov     cx, 0x0fff
1532
        test    si, 0x1
1533
        jz      .step3
1534
        shl     cx, 4
1535
        mov     word[es:si], cx
1536
        jmp     .end
1537
 
1538
.step3:
1539
        and     cx, 0x0FFF
1540
        mov     word[es:si], cx
1541
 
1542
.end:
1543
        inc     point_next_fat_str
1544
 
1545
        pop     di
1546
;DIR_FileSize 32-битный DWORD содержит размер файла в байтах.
1547
        mov     eax, save_file_size
1548
        mov     dword [es:di], eax
1549
 
1550
if DEBUG
1551
        pushad
1552
 
1553
        mov     di, firstDataSect    ;в секторах
1554
        sub     di, size_root_dir
1555
;теперь в ax размер в секторах начала рут дир
1556
        shl     di, 9;imul 512
1557
        add     di, point_to_free_root  ;смещение в уже записанных 32-х структурах.
1558
 
1559
        push    di
1560
 
1561
        mov     si, dest_name_fat
1562
        mov     cx, 11
1563
 
1564
;запишем в структуру имя
1565
@@:
1566
        mov     al, byte [es:di]
1567
        inc     di
1568
        mov     byte [ds:si], al
1569
        inc     si
1570
        loop    @b
1571
 
1572
        mov     di, si
1573
        inc     di
1574
        pop     ax
1575
        mov     cx, 0xa
1576
        call    decode
1577
 
1578
        mov     si, dest_name_fat
1579
        call    printplain
1580
        popad
1581
 
1582
END IF
1583
 
1584
 
1585
 
1586
 
1587
 
1588
        add     point_to_free_root, 32  ;увелицим смещение до следующего значения.
1589
        pop     es
1590
 
1591
}
1592
 
1593
 
1594
 
1595
 
1596
 
1597
macro get_firstDataSector
1598
;макрос для вычисления певого сектора данных т.е. данных файлов в фате
1599
;вычислим FirstDataSector = BPB_ResvdSecCnt + (BPB_NumFATs * FATSz) + RootDirSectors;
1600
{
1601
        mov     ax, word [fat12_buffer.BPB_FATSz16]
1602
        movzx   bx, byte [fat12_buffer.BPB_NumFATs]
1603
        imul    ax, bx  ;9x1=9
1604
;ax=BPB_NumFATs * FATSz
1605
        mov     bx, word [fat12_buffer.BPB_RootEntCnt]  ; count of 32-byte dir. entries (224*32 = 14 sectors= 7 kb)
1606
        shr     bx, 4   ;imul bx,32 and then div 512 -> in bx size in sectors
1607
        add     ax, bx  ;9+14=23
1608
        mov     size_root_dir, bx
1609
        movzx   bx, byte [fat12_buffer.BPB_RsvdSecCnt]  ;add 1 for fat 16/12
1610
        add     ax, bx
1611
;ax=firstDataSector - где начинается первый секторо от 0 сектора в секторах. - фактически = 24 сектор
1612
        mov     firstDataSect, ax       ;сохраним для вычисления
1613
;       получимзначение кластеров, это объем в который мы можем записать данные
1614
        mov     bx, word [fat12_buffer.BPB_TotSec16]
1615
        sub     bx, ax
1616
        mov     ax, bx
1617
        movzx   bx, byte [fat12_buffer.BPB_SecPerClus]
1618
        cwd
1619
        idiv    bx
1620
        mov     DataClasters, ax
1621
 
1622
if DEBUG
1623
        pushad
1624
        mov     ax, firstDataSect       ;первый сектор данных
1625
        mov     cx, 0x0a
1626
        mov     di, firstDataSect_msg
1627
        call    decode
1628
;Show size
1629
        mov     si, firstDataSect_msg
1630
        call    printplain
1631
;;;;;;;;;;;;;;;;;;;;;;;;;;
1632
        mov     ax, size_root_dir       ;размер рут дир в сетокторах
1633
        mov     cx, 0x0a
1634
        mov     di, size_root_dir_msg
1635
        call    decode
1636
;Show size
1637
        mov     si, size_root_dir_msg
1638
        call    printplain
1639
;;;;;;;;;;;;;;;;;;;;;;;;;;
1640
        mov     ax, DataClasters;кластеры
1641
        mov     cx, 0x0a
1642
        mov     di, DataClasters_msg
1643
        call    decode
1644
;Show size
1645
        mov     si, DataClasters_msg
1646
        call    printplain
1647
        popad
1648
 
1649
end if
1650
 
1651
}
1652
 
1653
macro use_RamdiskPATHS
1654
;парсинг пути источника файлов.
1655
{
1656
 
1657
}
1658
 
1659
macro use_RamdiskPATHD
1660
;парсинг пути назначения файлов.
1661
{
1662
 
1663
}
1664
macro check_name_file
1665
;макрос проверки имени на повтор, имя должно быть уникальным.
1666
;входные данные: es- сегмент где лежит файл для парсинга т.е. startos.ini
1667
;di - указатель на имя файла т.е. es:di указывает на имя файла назначения
1668
;выходные данные eax =-1 имя совпало, eax=0 имя не совпало.
1669
{
1670
local   .no_equal
1671
local   .exit
1672
local   .loop_size_root_dir
1673
;вычислим длинну строчки имени назначения, которую будем сравнивать с уже записанными данными.
1674
;преобразуем в аналог фат записи сточку с именем назначения
1675
        convertion_file_name    ; преобразовали имя по нужным правилам
1676
        test    ax, ax
1677
        jnz     .exit
1678
 
1679
        lea     si, [shot_name_fat]     ; desination name of file
1680
 
1681
;вычислим указатель на корневую директорию
1682
        mov     di, firstDataSect
1683
        sub     di, size_root_dir
1684
;теперь в ax размер в секторах начала рут дир
1685
        shl     di, 9;imul 512
1686
;di= Это смещение от начала буфера до рут директории. в пределах 64 кб.
1687
;загрузим значение - т.е. кол-во элементов, которые мы можем просматривать.
1688
        mov     dx, root_dir_entry_count
1689
 
1690
        mov     ax, info_real_mode_size
1691
        add     ax, 0x1000
1692
 
1693
 
1694
        mov     gs, ax
1695
.loop_size_root_dir:
1696
DEBUG1 equ 0
1697
if DEBUG1
1698
        pushad
1699
        push    di
1700
        mov     eax, dword[gs:di]
1701
        lea     si, [check_root_fat_+14]
1702
        mov     dword [ds:si], '----'
1703
        mov     dword [ds:si+4], '----'
1704
        mov     dword [ds:si+8], '----'
1705
        mov     dword[ds:si], eax
1706
        mov     eax, dword[gs:di+4]
1707
        mov     dword[ds:si+4], eax
1708
        mov     eax, dword[gs:di+8]
1709
        mov     dword[ds:si+8], eax
1710
 
1711
;
1712
        xor     eax, eax
1713
        mov     ax, gs;point_next_fat_str
1714
        mov     cx, 0x0a
1715
        mov     di, check_root_fat_
1716
        mov     dword [di], '    '
1717
        mov     word [di+4], '  '
1718
        call    decode
1719
        xor     eax, eax
1720
        pop     ax
1721
        mov     di, (check_root_fat_+7)
1722
        mov     dword [di], '    '
1723
        mov     word [di+4], '  '
1724
        call    decode
1725
 
1726
;Show size
1727
        lea     si, [check_root_fat_]
1728
        call    printplain
1729
 
1730
        lea     si, [shot_name_fat]
1731
        call    printplain
1732
 
1733
        xor     ax, ax
1734
        int     0x16
1735
        popad
1736
end if
1737
 
1738
        xor     bx, bx
1739
        mov     cx, 11  ;size of name in struct FAT
1740
 
1741
@@:
1742
        mov     al, byte [ds:si+bx]     ;ds:si - point to name of convertion variable.
1743
        mov     ah, byte [gs:di+bx]     ;gs:di - point to name in fat struct
1744
        inc     bx
1745
 
1746
if DEBUG
1747
;        pushad
1748
;        lea    si,[check_root_fat_+14]
1749
;        mov     dword [ds:si],'----'
1750
;        mov    word [ds:si],ax
1751
;       call    printplain
1752
 
1753
;       xor     ax,ax
1754
;       int     0x16
1755
 
1756
;        popad
1757
end if
1758
 
1759
 
1760
 
1761
        cmp     ah, al
1762
        jnz     .no_equal
1763
 
1764
;       dec     cx
1765
;       jnz     @b
1766
        loop    @b
1767
 
1768
;.succesfuly:
1769
;печально, такое имя уже имеется :(
1770
        or      ax, -1
1771
        jmp     .exit
1772
 
1773
 
1774
.no_equal:
1775
        add     di, 32          ;fat struct =32 byte
1776
        dec     dx
1777
        jnz     .loop_size_root_dir
1778
 
1779
;.exit_check_name:
1780
        and     ax, 0
1781
 
1782
.exit:
1783
 
1784
if DEBUG
1785
        pushad
1786
;Show size
1787
        lea     si, [check_name_fat_msg_n]
1788
        test    ax, ax
1789
        jz      @f
1790
        lea     si, [check_name_fat_msg_y]
1791
        call    printplain
1792
        lea     si, [alarm_msg]
1793
@@:
1794
        call    printplain
1795
        popad
1796
end if
1797
 
1798
}
1799
 
1800
 
1801
macro convertion_file_name
1802
;макрос конвертации имени, это нужно поскольку формат представленный не соответсвует фат и напрямую редко можно когда использовать
1803
;преобразование имени типа hello.asm в 'HELLO   ASM', в соответствии с правилами fat.
1804
;входные параметры es:di указатель на имя файла которое нужно преобразовать, конечный буфер shot_name_fat
1805
{
1806
local   .next_step
1807
local   .error
1808
local   .st1
1809
local   .st2
1810
local   .st2_l
1811
local   .st3
1812
local   .st4_s
1813
local   .st4
1814
local   .st5
1815
 
1816
;вычислим длинну строчки имени назначения, которую будем сравнивать с уже записанными данными.
1817
;       mov     di,point_to_dest_file_name   входной параметр
1818
        mov     si, shot_name_fat
1819
        or      first_input, -1 ;при первом входе устанавливаем флаг
1820
        mov     cx, 11  ;длинна имени в стуктуре фат таблицы
1821
 
1822
@@:
1823
        mov     al, byte [es:di]
1824
        cmp     al, 0xa
1825
        jz      .st4_s
1826
        cmp     al, 0xd
1827
        jz      .st4_s
1828
        cmp     al, 0x20
1829
        jz      .st4_s
1830
 
1831
        cmp     al, 0x20
1832
        jb      .error
1833
        cmp     al, 0x22
1834
        jz      .error
1835
        cmp     al, 0x2a
1836
        jz      .error
1837
        cmp     al, 0x2b
1838
        jz      .error
1839
        cmp     al, 0x2c
1840
        jz      .error
1841
        cmp     al, 0x2F
1842
        jz      .error
1843
 
1844
        cmp     al, 0x3a
1845
        jz      .error
1846
        cmp     al, 0x3b
1847
        jz      .error
1848
        cmp     al, 0x3c
1849
        jz      .error
1850
        cmp     al, 0x3d
1851
        jz      .error
1852
        cmp     al, 0x3E
1853
        jz      .error
1854
        cmp     al, 0x3F
1855
        jz      .error
1856
 
1857
        cmp     al, 0x5b
1858
        jz      .error
1859
        cmp     al, 0x5c
1860
        jz      .error
1861
        cmp     al, 0x5d
1862
        jz      .error
1863
 
1864
        cmp     al, 0x7c
1865
        jz      .error
1866
 
1867
 
1868
        cmp     first_input, -1
1869
        jnz     .next_step
1870
        and     first_input, 0  ;сборосим флаг.
1871
        cmp     al, '.'
1872
        jz      .error  ;обработка точки, файл не может начинаться с точки
1873
 
1874
.next_step:
1875
        cmp     al, 0x2e
1876
        jnz     .st2            ;обработка точки, в середине файла
1877
;тут у нас установлен разделитель
1878
;все остальнео место займут пробелы
1879
        mov     al, ' '
1880
 
1881
;!fixme обработаны не все исключения :(
1882
        cmp     cl, 3   ;формат файла такой GIDGIDIIASM т.е. gidgidii.asm
1883
        jbe     .st2
1884
 
1885
 
1886
.st3:
1887
        mov     byte [si], al
1888
        inc     si
1889
        dec     cx
1890
        cmp     cx, 3
1891
        ja      .st3
1892
;       inc     cx
1893
        inc     di
1894
        jmp     @b
1895
 
1896
.st2:
1897
        cmp     al, 0x60
1898
        jbe     .st2_l
1899
 
1900
        xor     al, 0x20;сделаем заглавные буквы
1901
.st2_l:
1902
        mov     byte [si], al
1903
        inc     di
1904
        inc     si
1905
;        dec    cx
1906
;       jnz     @b
1907
        loop    @b
1908
.st5:
1909
        xor     ax, ax
1910
        jmp     @f
1911
 
1912
;;;;;;;;файл закончился, и нужно внести в конец пробелы
1913
.st4_s:
1914
        mov     al, ' '
1915
.st4:
1916
        mov     byte [si], al
1917
        inc     si
1918
        loop    .st4
1919
        jmp     .st5
1920
 
1921
.error:
1922
        or      ax, -1
1923
@@:
1924
 
1925
if DEBUG
1926
        pushad
1927
 
1928
        mov     si, convertion_file_name_msg_y
1929
        test    ax, ax
1930
        jz      @f
1931
        mov     si, convertion_file_name_msg_n
1932
@@:
1933
        call    printplain
1934
 
1935
        mov     si, shot_name_fat
1936
        mov     byte [si+12], 0
1937
        call    printplain
1938
        popad
1939
 
1940
end if
1941
}
1942
 
1943
macro move_file_up
1944
;макрос который перемещает за 1 мб с правилами фат данные файла.
1945
{
1946
local   .st1
1947
local   .correct_on_byte
1948
;сейчас имеет быть ситуация, когда BPB уже перемещен за 1 мб, фат, и рут дир будут позже перемещены,
1949
;а нам нужно вычислить место, и перенести туда содержимое файла
1950
;полученое значение указывает в байтах на начало данных
1951
 
1952
        mov     ax, info_real_mode_size ; сегмент где расположены данные
1953
        mov     si, table_15_87
1954
        mov     word [si+8*2+2], ax
1955
;смещение до данных уже за 1-м мб
1956
        movzx   eax, firstDataSect
1957
        movzx   edx, data_offset
1958
        add     eax, edx
1959
 
1960
        movzx   ebx, word [fat12_buffer.BPB_BytsPerSec]
1961
        movzx   edx, byte [fat12_buffer.BPB_SecPerClus]
1962
        imul    bx, dx  ;получим размер кластера
1963
 
1964
 
1965
 
1966
        push    ebx     ;save bx
1967
 
1968
        imul    eax, ebx
1969
;       shl     eax,9   ;умножим на 512
1970
 
1971
if DEBUG
1972
        pushad
1973
        xor     eax, eax
1974
        mov     ax, info_real_mode_size
1975
        mov     cx, 0x0a
1976
        mov     di, seg_where_get_data
1977
        mov     dword [di], '    '
1978
        mov     word [di+4], '  '
1979
        call    decode
1980
;Show size
1981
        mov     si, seg_where_get_data
1982
        call    printplain
1983
        popad
1984
 
1985
end if
1986
 
1987
;       mov     bx,word [fat12_buffer.BPB_BytsPerSec]
1988
;       movzx   dx,byte [fat12_buffer.BPB_SecPerClus]
1989
;       imul    bx,dx
1990
;       cwd
1991
;       idiv    bx
1992
 
1993
        mov     dl, 0x10
1994
 
1995
@@:
1996
        cmp     eax, 0x00010000
1997
        jb      @f
1998
 
1999
        sub     eax, 0x00010000
2000
        inc     dl
2001
        jmp     @b
2002
 
2003
 
2004
@@:
2005
        mov     byte [si+8*3+3], dl     ;куда писать
2006
        mov     word [si+8*3+2], ax
2007
 
2008
        mov     ecx, save_file_size     ;размер файла в байтах.
2009
        cmp     ecx, 0x0000ffff         ;размер блока т.е. 64 кб
2010
        jbe     .correct_on_byte        ;корректировка на байт значения
2011
 
2012
 
2013
 
2014
        mov     ecx, 0x00010000         ;65536
2015
        sub     save_file_size, ecx     ;отнимим
2016
;       jmp     .st1                    ;получим 0х8000
2017
 
2018
 
2019
 
2020
 
2021
;корректировка значения должна быть выполенена на размер кластера
2022
.correct_on_byte:
2023
;/узнаем размер кластера
2024
        pop     eax     ;restore size of claster
2025
        push    ecx
2026
@@:
2027
        inc     data_offset
2028
 
2029
        cmp     eax, ecx
2030
        jae     @f
2031
        sub     ecx, eax
2032
        jmp     @b
2033
@@:
2034
        pop     ecx
2035
 
2036
 
2037
 
2038
 
2039
        test    ecx, 0x1
2040
        jz      .st1
2041
        inc     ecx
2042
.st1:
2043
        shr     ecx, 1    ; преобразовать значение для 0x87 function
2044
 
2045
;перенесем блок за 1 мб
2046
        push    es
2047
        push    ds
2048
        pop     es
2049
 
2050
        mov     ah, 0x87
2051
        int     0x15
2052
        pop     es
2053
 
2054
if DEBUG
2055
        pusha
2056
;       mov     ax,point_next_fat_str
2057
        mov     cx, 0x0a
2058
        mov     di, return_code_af_move
2059
        call    decode
2060
;Show size
2061
        mov     si, return_code_af_move
2062
        call    printplain
2063
        popa
2064
 
2065
end if
2066
 
2067
}
2068
 
2069
 
2070
macro move_up_fat_and_root_d
2071
;макрос, который позволяет перенести выше 1 мб в структуру образа фат таблицу и рут директорию
2072
{
2073
local  .st1
2074
 
2075
        mov     ax, info_real_mode_size
2076
        add     ax, 0x1000
2077
 
2078
        mov     si, table_15_87
2079
        mov     word [si+8*2+2], ax
2080
;смещение до данных
2081
        mov     ax, 512
2082
        mov     word [si+8*3+2], ax
2083
;fixme! тут необходимо сделать подержку т.е. формировать смещение файла в уже записанных данных.
2084
 
2085
        movzx   ecx, word [fat12_buffer.BPB_FATSz16]
2086
        movzx   bx, byte [fat12_buffer.BPB_NumFATs]
2087
        imul    cx, bx  ;9x1=9
2088
 
2089
        add     cx, size_root_dir       ;размер корневой дирректории
2090
        shl     ecx, 9  ;imul 512
2091
 
2092
 
2093
;корректировка значения
2094
        test    ecx, 0x1
2095
        jz      .st1
2096
        inc     ecx
2097
.st1:
2098
        shr     ecx, 1
2099
 
2100
        push    es
2101
        push    ds
2102
        pop     es
2103
 
2104
        mov     ah, 0x87
2105
        int     0x15
2106
        pop     es
2107
 
2108
if DEBUG
2109
        pusha
2110
;       mov     ax,point_next_fat_str
2111
        mov     cx, 0x0a
2112
        mov     di, return_code_af_fat_m
2113
        call    decode
2114
;Show size
2115
        mov     si, return_code_af_fat_m
2116
        call    printplain
2117
        popa
2118
 
2119
end if
2120
 
2121
}