3adc7b1d8e
git-svn-id: svn://kolibrios.org@3555 a494cfbc-eb01-0410-851d-a64ba20cac60
2122 lines
73 KiB
HTML
2122 lines
73 KiB
HTML
; Copyright (c) 2009, <Lrz>
|
||
; All rights reserved.
|
||
;
|
||
; Redistribution and use in source and binary forms, with or without
|
||
; modification, are permitted provided that the following conditions are met:
|
||
; * Redistributions of source code must retain the above copyright
|
||
; notice, this list of conditions and the following disclaimer.
|
||
; * Redistributions in binary form must reproduce the above copyright
|
||
; notice, this list of conditions and the following disclaimer in the
|
||
; documentation and/or other materials provided with the distribution.
|
||
; * Neither the name of the <organization> nor the
|
||
; names of its contributors may be used to endorse or promote products
|
||
; derived from this software without specific prior written permission.
|
||
;
|
||
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov nickname <Lrz> ''AS IS'' AND ANY
|
||
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
|
||
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
;*****************************************************************************
|
||
|
||
; в этой секции идет разбор параметров указатель на секцию храниться в point_default
|
||
;типы ошибок при обработке макроса
|
||
;Макрос RamdiskFS
|
||
;/определение флагов в записи корневой директории
|
||
ATTR_READ_ONLY equ 0x01
|
||
ATTR_HIDDEN equ 0x02
|
||
ATTR_SYSTEM equ 0x04
|
||
ATTR_VOLUME_ID equ 0x08
|
||
ATTR_DIRECTORY equ 0x10
|
||
ATTR_ARCHIVE equ 0x20
|
||
|
||
|
||
|
||
show_error_1 equ 0x1 ;кончились данные - не запланированный конец секции
|
||
show_error_2 equ 0x2 ;нет завершающего символа в размере рам диска.
|
||
show_error_3 equ 0x4 ; рам диск будет иметь размер =64 кб.
|
||
show_error_4 equ 0x8 ;
|
||
|
||
macro use_parse_def_sect
|
||
{
|
||
mov di, point_default
|
||
push ini_data_
|
||
pop es
|
||
mov si, point_to_point_def
|
||
sub si, 2
|
||
mov cx, [si] ;загрузим указатель наследующию секцию
|
||
|
||
xor ax, ax ;обнулим аx для очистки флагов
|
||
|
||
sub cx, di ;вот теперь имеем истиный размер
|
||
mov save_cx_d, cx ;сохраним значение cx своей переменной
|
||
;обнулим переменную флагов, это необходимо, для того, что бы избежать обработку повторяющихся значений
|
||
|
||
mov status_flag, ax
|
||
;;;;
|
||
;ВХод в обработку парсинга значений секций. es:di - указатель на начало секции cx размер секции доступной для парсинга
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;соглашение не разрушаем bp, es, cs, sp
|
||
;use_Loader_Image ;загрузить образ выше 1 мб
|
||
use_RamdiskFS
|
||
;проверяется самый последний.
|
||
use_LoaderModule ;особенность - передает управление на загруженный модуль.
|
||
}
|
||
|
||
macro use_LoaderModule
|
||
;как вариант сейчас используется модель, при загрузке модуля на него передается управление, решение временое
|
||
;управление будет передаваться только после обработки всей секции
|
||
{
|
||
local .found_end_str
|
||
|
||
mov di, point_default ;restore value
|
||
mov cx, save_cx_d
|
||
;обработка конструкции типа LoaderModule=kord/kolibri.ldm
|
||
.start_p_LM:
|
||
call get_firs_sym ;get first symbol on new line
|
||
test cx, cx
|
||
jz ._afterLoaderModule ;нету? ну ладно - следующее значение тогда )
|
||
cmp al, 'L'
|
||
jnz .start_p_LM
|
||
;проверка на значение LoaderModule
|
||
; parse_LoaderModule
|
||
mov bx, cx
|
||
mov ax, di
|
||
|
||
mov si, parse_LoaderModule
|
||
mov cx, parse_LoaderModule_e - parse_LoaderModule
|
||
repe cmpsb
|
||
jnz .rest_value_loop_LM ;is not compare
|
||
|
||
sub bx, parse_LoaderModule_e - parse_LoaderModule;correct cx
|
||
add bx, cx
|
||
mov cx, bx
|
||
|
||
test status_flag, flag_found_LM ;оценка флагов
|
||
jz .correct_is_not_set_LM
|
||
|
||
; mov si,found_equal_timeout ;мы нашли что флаг уже установлен, информируем
|
||
; call printplain
|
||
; jmp .get_next_str
|
||
|
||
.correct_is_not_set_LM:
|
||
mov ax, 0x3d20 ;cut al=' ' ah='='
|
||
repe scasb
|
||
jcxz .rest_value_loop_LM ;not found param timeout
|
||
|
||
cmp ah, byte [es:di-1] ;find '='
|
||
jnz .rest_value_loop_LM
|
||
|
||
repe scasb ;cut ' '
|
||
inc cx
|
||
dec di
|
||
;di указывает на начало блока информации, в cx длинна до конца секции.
|
||
;после загрузки заноситься значение занятой памяти.
|
||
;для того что бы загрузить модуль, воспользуемся callback сервисом
|
||
;оригинальное решение - разместим dd перед строчкой и после строчки разместим byte =0
|
||
;это выглядит так: в ini файле существует строчка LoaderModule = kord/kernel.loader
|
||
;мы ее модифицируем до такого состояния dw,dw,db'kord/kernel.loader',0 конечно сохранив те значения которые мы заменяем
|
||
;сохранили певые 2 word
|
||
push dword [es:di-6]
|
||
lea si, [di-6]
|
||
|
||
push word [es:di-2]
|
||
xor ax, ax
|
||
mov word [es:di-6], ax ;вносим нужные значения
|
||
;info_real_mode_size размер и указатель на область в которую можно загрузиться
|
||
mov ax, info_real_mode_size ;0x3000 ;следующий сегмент за данными
|
||
|
||
|
||
mov word [es:di-4], ax
|
||
mov word [es:di-2], 16 ;кол-во блоков по 4 кб =64 кб т.е. больше не считаем
|
||
;;;;;; поиск конца строчки
|
||
@@:
|
||
mov al, byte [es:di]
|
||
cmp al, ' '
|
||
jz .found_end_str
|
||
cmp al, 0xa
|
||
jz .found_end_str
|
||
cmp al, 0xd
|
||
jz .found_end_str
|
||
inc di
|
||
dec cx
|
||
jnz @b
|
||
;;;not found допустим,что это конец файла и он не имеет привычного заверешния строки
|
||
.found_end_str:
|
||
|
||
push word [es:di]
|
||
xor ax, ax
|
||
mov word [es:di], ax
|
||
; xor ax,ax ; function 1 - read file
|
||
mov di, si ;file_data
|
||
inc ax
|
||
push si
|
||
push es
|
||
|
||
push es
|
||
pop ds
|
||
push cs
|
||
pop es
|
||
|
||
call far dword [es:loader_callback]
|
||
|
||
push cs
|
||
pop ds
|
||
|
||
pop es
|
||
pop si
|
||
|
||
test bx, bx
|
||
jnz .error_LM
|
||
|
||
|
||
jmp far dword [es:si]
|
||
|
||
|
||
.error_LM:
|
||
call error.LoaderModule
|
||
.rest_value_loop_LM:
|
||
mov di, ax
|
||
mov cx, bx
|
||
jmp .start_p_LM
|
||
|
||
._afterLoaderModule:
|
||
}
|
||
|
||
macro use_RamdiskFS
|
||
; формирование рам диска, + обработка всего связанного.
|
||
{
|
||
if DEBUG
|
||
local ._not_memory_in_sys
|
||
;//////// clear window
|
||
mov ax, 3
|
||
int 0x10
|
||
;\\\\\\\\\ clear window is end
|
||
mov si, ramdiskFS_st
|
||
call printplain
|
||
end if
|
||
; обнулим регистр состояния ошибок
|
||
xor ax, ax
|
||
mov show_errors_sect, ax
|
||
use_free_memory ; узнаем какого объема у нас доступна память. значение возаращается в ax
|
||
;узнаем сколько у нас есть памяти и сможем ли мы сформировать нужного размера рам диск.
|
||
use_RamdiskSize ;значение возвращается в bx
|
||
cmp free_ad_memory, bx ; размерность в кб.
|
||
jbe ._not_memory_in_sys
|
||
movzx eax, bx
|
||
shl eax, 10 ;*1024 = get size in byte
|
||
mov save_ramdisksize, eax ; сорханим размер в byte
|
||
|
||
get_type_FS ;получим тип файловой системы + создадим ее
|
||
|
||
|
||
._not_memory_in_sys:
|
||
|
||
if DEBUG
|
||
;pause
|
||
xor ax, ax
|
||
int 0x16
|
||
end if
|
||
}
|
||
macro use_RamdiskSize
|
||
{
|
||
local .start_p_RS
|
||
local .correct_is_not_set_RS
|
||
local .CS
|
||
local .correct_val_RS
|
||
local .correct_size_RS
|
||
local .rest_value_loop_RS
|
||
local .end_get_RS_ERROR_1
|
||
local .end_get_RS_ERROR_2
|
||
local ._end_parse_RS
|
||
;обрабатывается размер формируемого рам диска
|
||
;загрузим начало секции, т.к. будем просматривать с начала и всю секцию
|
||
mov di, point_default ;restore value
|
||
mov cx, save_cx_d
|
||
.start_p_RS:
|
||
call get_firs_sym ;get first symbol on new line
|
||
test cx, cx
|
||
jz ._end_parse_RS ;нету? ну ладно - следующее значение тогда )
|
||
cmp al, 'R'
|
||
jnz .start_p_RS
|
||
;проверка на значения RamdiskSize
|
||
; parse_RamdiskSize
|
||
mov bx, cx
|
||
mov ax, di
|
||
|
||
mov si, parse_RamdiskSize
|
||
mov cx, parse_RamdiskSize_e - parse_RamdiskSize
|
||
repe cmpsb
|
||
jnz .rest_value_loop_RS ;is not compare
|
||
|
||
sub bx, parse_RamdiskSize_e - parse_RamdiskSize;correct cx
|
||
add bx, cx
|
||
mov cx, bx
|
||
|
||
test status_flag, flag_found_RS ;оценка флагов
|
||
jz .correct_is_not_set_RS
|
||
|
||
; mov si,found_equal_timeout ;мы нашли что флаг уже установлен, информируем
|
||
; call printplain
|
||
; jmp .get_next_str
|
||
|
||
.correct_is_not_set_RS:
|
||
mov ax, 0x3d20 ;cut al=' ' ah='='
|
||
repe scasb
|
||
jcxz .end_get_RS_ERROR_1 ;not found param
|
||
|
||
cmp ah, byte [es:di-1] ;find '='
|
||
jnz .start_p_RS ; перейдем на начало и попробуем найти еще секцию
|
||
|
||
repe scasb ;cut ' '
|
||
inc cx
|
||
dec di
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;Тут нужно преобразовывать строчку в цифровое значение.
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
xor bx, bx
|
||
mov cx, 5
|
||
@@:
|
||
mov al, byte [es:di]
|
||
cmp al, '0'
|
||
jb .CS
|
||
cmp al, '9'
|
||
jbe .correct_val_RS
|
||
.CS:
|
||
cmp al, 'K'
|
||
jz .correct_size_RS
|
||
jmp .end_get_RS_ERROR_2
|
||
.correct_val_RS:
|
||
imul bx, 10
|
||
xor al, 0x30
|
||
add bl, al
|
||
inc di
|
||
loop @b
|
||
|
||
.correct_size_RS:
|
||
;возможен 1 вариант, когда размер задан в K киллобайтах
|
||
;внутренный формат данных это кол-во запрощеной памяти в кб.
|
||
test bx, bx
|
||
jnz @f ;если значение отлично от 0
|
||
;;;;;сообщение об ошибке, размер "найденого" блока =0 минимально мы должны
|
||
;установить 64 кб размер рам диска.
|
||
or show_errors_sect, show_error_3
|
||
mov bx, 64
|
||
@@:
|
||
jmp ._end_parse_RS
|
||
|
||
|
||
.rest_value_loop_RS:
|
||
mov di, ax
|
||
mov cx, bx
|
||
jmp .start_p_RS
|
||
|
||
|
||
|
||
.end_get_RS_ERROR_1:
|
||
;сообщение об ошибке - данный участок кода не был корректно обработан :(
|
||
or show_errors_sect, show_error_1
|
||
jmp ._end_parse_RS
|
||
.end_get_RS_ERROR_2:
|
||
or show_errors_sect, show_error_2
|
||
|
||
._end_parse_RS:
|
||
if DEBUG
|
||
pusha
|
||
movzx eax, bx
|
||
mov cx, 0x0a
|
||
mov di, RamdiskSize_msg
|
||
mov dword[ds:di], ' '
|
||
mov word [ds:di+4], ' '
|
||
call decode
|
||
;Show size
|
||
mov si, RamdiskSize_msg
|
||
call printplain
|
||
|
||
popa
|
||
end if
|
||
|
||
}
|
||
|
||
macro use_free_memory
|
||
{
|
||
local _support_function_use_free_memory
|
||
;макрос для получения общего числа доступной памяти в кб, для формирования рам диска за пределами 1 мб.
|
||
;используется 0х88 функция 0х15 прерывания
|
||
; если поддерживается функция, то в ax значение в кб, если нет, то в ax=0
|
||
mov ah, 0x88 ;ah,0x88
|
||
int 0x15
|
||
jnc ._support_function_use_free_memory
|
||
xor ax, ax
|
||
;возвращает в ax число в кб
|
||
._support_function_use_free_memory:
|
||
mov free_ad_memory, ax ; если не поддерживается биосом, то в ax=0
|
||
if DEBUG
|
||
pushad
|
||
movzx eax, ax
|
||
mov cx, 0x0a
|
||
mov di, free_memory_msg
|
||
mov dword[ds:di], ' '
|
||
mov word [ds:di+4], ' '
|
||
call decode
|
||
;Show size
|
||
mov si, free_memory_msg
|
||
call printplain
|
||
|
||
popad
|
||
end if
|
||
|
||
|
||
|
||
|
||
}
|
||
macro show_ERRORS
|
||
{
|
||
|
||
}
|
||
|
||
macro get_type_FS ;получить и создать образ для заданной RFS.
|
||
{
|
||
mov di, point_default ;restore value
|
||
mov cx, save_cx_d
|
||
.start_g_tpe_RFS:
|
||
call get_firs_sym ;get first symbol on new line
|
||
test cx, cx
|
||
jz ._end_parse_FRS ;._end_get_type_RFS ;нету? ну ладно - следующее значение тогда )
|
||
cmp al, 'R'
|
||
jnz .start_g_tpe_RFS
|
||
;проверка на значения RamdiskSize
|
||
; parse_RamdiskSize
|
||
mov bx, cx
|
||
mov ax, di
|
||
|
||
mov si, parse_RamdiskFS
|
||
mov cx, parse_RamdiskFS_e - parse_RamdiskFS
|
||
repe cmpsb
|
||
jnz .start_g_tpe_RFS_rest_v ;is not compare
|
||
|
||
sub bx, parse_RamdiskFS_e - parse_RamdiskFS;correct cx
|
||
add bx, cx
|
||
mov cx, bx
|
||
|
||
test status_flag, flag_found_GTRFMS ;оценка флагов
|
||
jz .correct_is_not_set_FRS
|
||
|
||
; mov si,found_equal_timeout ;мы нашли что флаг уже установлен, информируем
|
||
; call printplain
|
||
; jmp .get_next_str
|
||
|
||
.correct_is_not_set_FRS:
|
||
mov ax, 0x3d20 ;cut al=' ' ah='='
|
||
repe scasb
|
||
test cx, cx
|
||
jz .end_get_FRS_ERROR_1 ;not found param
|
||
|
||
cmp ah, byte [es:di-1] ;find '='
|
||
jnz .start_g_tpe_RFS ; перейдем на начало и попробуем найти еще секцию
|
||
|
||
repe scasb ;cut ' '
|
||
inc cx
|
||
dec di
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;Тут нужно преобразовывать строчку в цифровое значение.
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
mov bx, cx
|
||
mov ax, di
|
||
|
||
mov si, parse_RFS_FAT
|
||
mov cx, parse_RFS_FAT_e - parse_RFS_FAT
|
||
repe cmpsb
|
||
jnz .krfs_cmp ;is not compare
|
||
|
||
make_FAT_RamFS ;сделать
|
||
|
||
if DEBUG
|
||
pusha
|
||
mov si, make_fat12_RFS_msg
|
||
call printplain
|
||
popa
|
||
end if
|
||
jmp ._end_parse_FRS
|
||
|
||
.krfs_cmp:
|
||
mov cx, bx
|
||
mov di, ax
|
||
|
||
mov si, parse_RFS_KRFS
|
||
mov cx, parse_RFS_KRFS_e - parse_RFS_KRFS
|
||
repe cmpsb
|
||
; jnz @f ;is not compare
|
||
|
||
jmp ._end_parse_FRS
|
||
|
||
|
||
.start_g_tpe_RFS_rest_v:
|
||
mov cx, bx
|
||
mov di, ax
|
||
jmp .start_g_tpe_RFS
|
||
|
||
|
||
|
||
.end_get_FRS_ERROR_1:
|
||
;сообщение об ошибке - данный участок кода не был корректно обработан :(
|
||
or show_errors_sect, show_error_1
|
||
jmp ._end_parse_FRS
|
||
.end_get_FRS_ERROR_2:
|
||
or show_errors_sect, show_error_2
|
||
|
||
._end_parse_FRS:
|
||
if DEBUG
|
||
pusha
|
||
mov si, get_type_FS_msg
|
||
call printplain
|
||
popa
|
||
end if
|
||
|
||
|
||
|
||
}
|
||
macro make_FAT_RamFS
|
||
{
|
||
local .RS1
|
||
local .fat12
|
||
local .fat16
|
||
; мы должны сформировать в начальный образ Ram FS, а потом записать его за область выше 1 мб..
|
||
;для случая с FAT12
|
||
; mov di,fat12_buffer ;ds должен быть = cs
|
||
;es:di - указывают на начало блока для формирования рам фс.
|
||
use_RamdiskSector ;возращаемое значение в ax размер сектора в байтах
|
||
cmp ax, 4096;по спецификации значение должно быть в пределах от 1 до 4096
|
||
ja .RS1
|
||
test ax, ax
|
||
jnz @f ;ошибка если сюда прыгнули все таки ...
|
||
|
||
.RS1:
|
||
mov word [fat12_buffer.BPB_BytsPerSec], 512
|
||
;;;;;;;;;;скажем что по дефолту будем юзать значение...
|
||
@@:
|
||
mov word [fat12_buffer.BPB_BytsPerSec], ax;тут все ок
|
||
|
||
;BPB_SecPerClus кол-во секторов в кластере
|
||
use_RamdiskCluster ;возращаемое значение в al
|
||
cmp al, 128
|
||
ja @f
|
||
; test al,0x1 ;проверка на кратность )
|
||
; jnz @f
|
||
|
||
mov byte [fat12_buffer.BPB_SecPerClus], al
|
||
|
||
;incorrect value will be set dafault
|
||
|
||
;ниже некорректное значение в т.к. размер кратен 2 и в диапазоне от 1 до 128 включительно
|
||
; мы должны ругнуться на это
|
||
;@@: ;mov byte [fat12_buffer.BPB_SecPerClus],1
|
||
|
||
;;;;; определеим какая у нас будет использоваться FAT
|
||
;по условию, fat12<4085<=fat16<65525<=fat32
|
||
; fat12_buffer.BPB_BytsPerSec*fat12_buffer.BPB_SecPerClus = кол-во секторов
|
||
movzx eax, word [fat12_buffer.BPB_BytsPerSec]
|
||
movzx ebx, byte [fat12_buffer.BPB_SecPerClus]
|
||
|
||
imul ebx, eax;тут размерность сектора
|
||
mov eax, save_ramdisksize ;размер запрошенного рам диска в байтах
|
||
cdq
|
||
idiv ebx
|
||
;;;;;;;; сейчас частное в eax, а остаток в edx
|
||
;получим кол-во секторов, и можем уже определить тип FAT которую нужно делать.
|
||
cmp eax, 4085
|
||
jb .fat12
|
||
cmp eax, 65525
|
||
jb .fat16
|
||
;;;;;;;;;;;;;;;;;;;;;;;; тут fat32
|
||
mov set_ramfs, 32 ;установим тип файловой системы
|
||
mov word [fat12_buffer.BPB_RsvdSecCnt], 32
|
||
xor eax, eax
|
||
mov word [fat12_buffer.BPB_RootEntCnt], ax
|
||
mov word [fat12_buffer.BPB_TotSec16], ax
|
||
mov dword [fat12_buffer.BPB_TotSec32], eax
|
||
|
||
|
||
.fat16: ;fat16
|
||
;Для FAT12 и FAT16 дисков это поле содержит количество секторов, а BPB_TotSec32 равно 0, если значение <умещается> (меньше 0x10000).
|
||
jmp $
|
||
mov set_ramfs, 16 ;установим тип файловой системы
|
||
movzx ebx, byte [fat12_buffer.BPB_SecPerClus]
|
||
imul eax, ebx
|
||
|
||
cmp eax, 0x10000
|
||
jae @f
|
||
mov word [fat12_buffer.BPB_TotSec16], ax
|
||
mov dword [fat12_buffer.BPB_TotSec32], 0
|
||
@@:
|
||
;количество секторов занимаемое одной копией фат
|
||
; mov word [fat12_buffer.BPB_FATSz16],0x9 ;Для FAT12/FAT16 это количество секторов одной FAT. ??
|
||
;;;; заполним BPB_RootEntCnt Для FAT12 и FAT16 дисков, это поле содержит число
|
||
;32-байтных элементов корневой директории. Для FAT32 дисков, это поле должно
|
||
;быть 0. Пока константа, нужно будет позже доделать.
|
||
mov eax, root_dir_entry_count
|
||
mov word [fat12_buffer.BPB_RootEntCnt], ax ; count of 32-byte dir. entries (224*32 = 14 sectors= 7 kb)
|
||
;по документации рекомендуют отрезать 16 кб для рут дир но это оч много, даже для коос. имхо для начала хватит и 7 кб
|
||
;;;;;;;
|
||
;Для FAT16 это количество секторов одной FAT. Для FAT32 это значение
|
||
;равно 0, а количество секторов одной FAT содержится в BPB_FATSz32.
|
||
;RootDirSectors = ((BPB_RootEntCnt * 32) + (BPB_BytsPerSec - 1)) / BPB_BytsPerSec;
|
||
|
||
;TmpVal1 = DskSize - (BPB_ResvdSecCnt + RootDirSectors);
|
||
;TmpVal2 = (256 * BPB_SecPerClus) + BPB_NumFATs;
|
||
;If(FATType == FAT32)
|
||
; TmpVal2 = TmpVal2 / 2;
|
||
;FATSz = (TMPVal1 + (TmpVal2 - 1)) / TmpVal2;
|
||
;If(FATType == FAT32) {
|
||
; BPB_FATSz16 = 0;
|
||
; BPB_FATSz32 = FATSz;
|
||
;} else {
|
||
; BPB_FATSz16 = LOWORD(FATSz);
|
||
; /* there is no BPB_FATSz32 in a FAT16 BPB */
|
||
;}
|
||
;=====================================
|
||
;RootDirSectors
|
||
movzx ebx, word [fat12_buffer.BPB_BytsPerSec]
|
||
imul eax, 32
|
||
add eax, ebx
|
||
dec eax
|
||
|
||
cdq
|
||
idiv ebx
|
||
;;;;;;;; сейчас частное в eax, а остаток в edx для дискеты 1.44 у нас должно быть значение =14
|
||
;BPB_ResvdSecCnt + RootDirSectors
|
||
movzx ebx, word [fat12_buffer.BPB_RsvdSecCnt]
|
||
add ebx, eax
|
||
|
||
;DskSize у нас это значение уже получено и доступно
|
||
movzx eax, word [fat12_buffer.BPB_TotSec16] ;должен быть в секторах
|
||
sub eax, ebx
|
||
|
||
|
||
;TmpVal1=eax
|
||
shl edi, 8 ;=edi*256
|
||
movzx ecx, byte [fat12_buffer.BPB_NumFATs]
|
||
add edi, ecx
|
||
;TmpVal2=edi
|
||
add eax, edi
|
||
dec eax
|
||
cdq
|
||
idiv edi
|
||
;FATSz = сейчас частное в eax, а остаток в edx
|
||
mov word [fat12_buffer.BPB_FATSz16], ax
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
.fat12: ;fat12
|
||
if DEBUG
|
||
; выведем в отладке, что собираемся делать образ диска c FS=fat12
|
||
pushad
|
||
mov si, start_making_FAT12_msg
|
||
call printplain
|
||
popad
|
||
end if
|
||
|
||
|
||
|
||
;Для FAT12 и FAT16 дисков это поле содержит количество секторов, а BPB_TotSec32 равно 0, если значение <умещается> (меньше 0x10000).
|
||
mov set_ramfs, 12 ;установим тип файловой системы
|
||
movzx ebx, byte [fat12_buffer.BPB_SecPerClus]
|
||
imul eax, ebx
|
||
|
||
cmp eax, 0x10000
|
||
jae @f
|
||
mov word [fat12_buffer.BPB_TotSec16], ax
|
||
mov dword [fat12_buffer.BPB_TotSec32], 0
|
||
@@:
|
||
;количество секторов занимаемое одной копией фат
|
||
; mov word [fat12_buffer.BPB_FATSz16],0x9 ;Для FAT12/FAT16 это количество секторов одной FAT. ??
|
||
;;;; заполним BPB_RootEntCnt Для FAT12 и FAT16 дисков, это поле содержит число
|
||
;32-байтных элементов корневой директории. Для FAT32 дисков, это поле должно
|
||
;быть 0. Пока константа, нужно будет позже доделать.
|
||
mov eax, root_dir_entry_count
|
||
mov word [fat12_buffer.BPB_RootEntCnt], ax ; count of 32-byte dir. entries (224*32 = 14 sectors= 7 kb)
|
||
;по документации рекомендуют отрезать 16 кб для рут дир но это оч много, даже для коос. имхо для начала хватит и 7 кб
|
||
;;;;;;;
|
||
;DskSize(в секторах)*12 (размерность файловой системы, т.е предположим сколько битов потребуется для адресации этого объема) /8 (что получить размер в байтах)
|
||
;полученное число округляем в большую сторону кратное сектору т.е. 512 байт Такой подход не универсален, но пока пойдет
|
||
;вообще у мелкософт это все считается ручками, но мы будем юзать только под коос рам диск с фат12
|
||
movzx eax, word [fat12_buffer.BPB_TotSec16]
|
||
imul eax, 12
|
||
shr eax, 3 ;делим на 8 но т.е. нам нужно делить еще и на 512 или более в зависимости от размеров кластера
|
||
movzx ebx, word [fat12_buffer.BPB_BytsPerSec] ;размер сектора
|
||
cdq
|
||
idiv ebx ;разделим на размер кластера
|
||
;сейчас у нас в eax значение его нужно округлить в большую сторону кратному 512 байтам
|
||
;применим следующее очистим and и добавим 512 байт. таким образом выравним на 512 байт
|
||
;но т.к. все равно делить нижний код нам не нужен
|
||
; and eax,0xfff200
|
||
; add eax,0x200 ;добавим 512 байт для 1.44 дискеты идеально подходит ))
|
||
|
||
inc ax
|
||
;по идее должно на каждую фат таблицу
|
||
;резервироваться 9 секторов т.е. получается 2*9=18+1 =19 секторов т.е. рут дир находиться на с 20 сетора т.е. с адреса 0х2600
|
||
;сейчас нужно вычислить сколько будет секторов занимать фат ) нужно разделить на 512
|
||
;FATSz = сейчас частное в eax
|
||
mov word [fat12_buffer.BPB_FATSz16], ax
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
get_firstDataSector ;получить смещение до данных
|
||
;создадим певую запись в фат по определенному адресу.
|
||
first_create_fat_table
|
||
;закиним BPB файловой системы за 1 мб.
|
||
use_BPB_RAM
|
||
;
|
||
;копирование файла.
|
||
use_RamdiskFile
|
||
|
||
;;;; вычисляем указатель на корневую дир FirstRootDirSecNum = BPB_ResvdSecCnt + (BPB_NumFATs * BPB_FATSz16);
|
||
; movzx ebx, [fat12_buffer.BPB_NumFATs]
|
||
; movzx eax,ax
|
||
; imul eax,ebx
|
||
;eax=(BPB_NumFATs * BPB_FATSz16)
|
||
; inc eax
|
||
; BPB_ResvdSecCnt значение только 1 для fat12/16
|
||
;в eax указатель на root dir. для дискеты fat12 должно получиться при кол-во копий fat 1 = 1+ (1*1) =2 или 3
|
||
|
||
if DEBUG
|
||
pusha
|
||
; mov ax,point_default
|
||
; mov ax,cx
|
||
mov cx, 0x0a
|
||
mov di, show_db1
|
||
; mov dword[ds:di],' '
|
||
; mov word [ds:di+4],' '
|
||
call decode
|
||
;Show size
|
||
mov si, show_db1
|
||
call printplain
|
||
;
|
||
; xor ax,ax
|
||
; int 0x16
|
||
popa
|
||
end if
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
}
|
||
|
||
macro use_RamdiskSector
|
||
{
|
||
;для некоторых FS будет игнорироваться
|
||
mov di, point_default ;restore value
|
||
mov cx, save_cx_d
|
||
|
||
.start_RamdiskSector:
|
||
call get_firs_sym ;get first symbol on new line
|
||
test cx, cx
|
||
jz .end_RamdiskSector ;нету? ну ладно - следующее значение тогда )
|
||
|
||
cmp al, 'R'
|
||
jnz .start_RamdiskSector
|
||
;проверка на значения RamdiskSize
|
||
; parse_RamdiskSize
|
||
|
||
mov bx, cx
|
||
mov ax, di
|
||
|
||
mov si, parse_RamdiskSector
|
||
mov cx, parse_RamdiskSector_e - parse_RamdiskSector
|
||
repe cmpsb
|
||
jnz .RamdiskSector_rest_val ;is not compare
|
||
|
||
sub bx, parse_RamdiskSector_e - parse_RamdiskSector;correct cx
|
||
add bx, cx
|
||
mov cx, bx
|
||
|
||
test status_flag, flag_found_RamdiskSector ;оценка флагов
|
||
jz .correct_is_not_set_RamdiskSector
|
||
|
||
; mov si,found_equal_timeout ;мы нашли что флаг уже установлен, информируем
|
||
; call printplain
|
||
; jmp .get_next_str
|
||
|
||
.correct_is_not_set_RamdiskSector:
|
||
mov ax, 0x3d20 ;cut al=' ' ah='='
|
||
repe scasb
|
||
jcxz .end_get_RamS_ERROR_1 ;not found param
|
||
|
||
cmp ah, byte [es:di-1] ;find '='
|
||
jnz .start_RamdiskSector ; перейдем на начало и попробуем найти еще секцию
|
||
|
||
repe scasb ;cut ' '
|
||
inc cx
|
||
dec di
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
xor bx, bx
|
||
mov cx, 4
|
||
@@:
|
||
movzx ax, byte [es:di]
|
||
cmp al, '0'
|
||
jb .end_RamdiskSector
|
||
cmp al, '9'
|
||
ja .end_RamdiskSector
|
||
;;;;;;;;;;;;;;;;;;;
|
||
|
||
imul bx, 10
|
||
xor al, 0x30
|
||
add bx, ax
|
||
|
||
inc di
|
||
|
||
loop @b
|
||
jmp .end_RamdiskSector
|
||
|
||
|
||
.RamdiskSector_rest_val:
|
||
mov cx, bx
|
||
mov di, ax
|
||
jmp .start_RamdiskSector
|
||
.end_get_RamS_ERROR_1:
|
||
|
||
.end_RamdiskSector:
|
||
mov ax, bx
|
||
|
||
if DEBUG
|
||
pusha
|
||
movzx eax, bx;save_cx_d;point_default
|
||
mov cx, 0x0a
|
||
mov di, RamdiskSector_msg
|
||
mov dword[ds:di], ' '
|
||
mov dword [ds:di+4], ' '
|
||
call decode
|
||
;Show size
|
||
mov si, RamdiskSector_msg
|
||
call printplain
|
||
|
||
popa
|
||
end if
|
||
|
||
; pop di
|
||
; pop es
|
||
}
|
||
|
||
macro use_RamdiskCluster
|
||
{
|
||
;для некоторых FS будет игнорироваться
|
||
; push es
|
||
; push di
|
||
mov di, point_default ;restore value
|
||
mov cx, save_cx_d
|
||
; push ini_data_
|
||
; pop es
|
||
.start_RamdiskCluster:
|
||
call get_firs_sym ;get first symbol on new line
|
||
test cx, cx
|
||
jz .end_RamdiskCluster ;нету? ну ладно - следующее значение тогда )
|
||
cmp al, 'R'
|
||
jnz .start_RamdiskCluster
|
||
;проверка на значения RamdiskSize
|
||
; parse_RamdiskSize
|
||
|
||
mov bx, cx
|
||
mov ax, di
|
||
|
||
mov si, parse_RamdiskCluster
|
||
mov cx, parse_RamdiskCluster_e - parse_RamdiskCluster
|
||
repe cmpsb
|
||
jnz .RamdiskCluster_rest_val ;is not compare
|
||
|
||
sub bx, parse_RamdiskCluster_e - parse_RamdiskCluster;correct cx
|
||
add bx, cx
|
||
mov cx, bx
|
||
|
||
test status_flag, flag_found_RamdiskCluster ;оценка флагов
|
||
jz .correct_is_not_set_RamdiskCluster
|
||
|
||
; mov si,found_equal_timeout ;мы нашли что флаг уже установлен, информируем
|
||
; call printplain
|
||
; jmp .get_next_str
|
||
|
||
.correct_is_not_set_RamdiskCluster:
|
||
mov ax, 0x3d20 ;cut al=' ' ah='='
|
||
repe scasb
|
||
jcxz .end_get_RamSC_ERROR_1 ;not found param
|
||
|
||
cmp ah, byte [es:di-1] ;find '='
|
||
jnz .start_RamdiskCluster ; перейдем на начало и попробуем найти еще секцию
|
||
|
||
repe scasb ;cut ' '
|
||
inc cx
|
||
dec di
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
@@:
|
||
movzx ax, byte [es:di]
|
||
cmp al, '0'
|
||
jb .end_RamdiskCluster
|
||
cmp al, '9'
|
||
ja .end_RamdiskCluster
|
||
;;;;;;;;;;;;;;;;;;;
|
||
xor al, 0x30
|
||
|
||
jmp .end_RamdiskCluster
|
||
|
||
|
||
.RamdiskCluster_rest_val:
|
||
mov cx, bx
|
||
mov di, ax
|
||
jmp .start_RamdiskCluster
|
||
.end_get_RamSC_ERROR_1:
|
||
|
||
.end_RamdiskCluster:
|
||
if DEBUG
|
||
pusha
|
||
mov cx, 0x0a
|
||
mov di, RamdiskCluster_msg
|
||
; mov word[ds:di],' '
|
||
call decode
|
||
;Show size
|
||
mov si, RamdiskCluster_msg
|
||
call printplain
|
||
|
||
popa
|
||
end if
|
||
|
||
}
|
||
|
||
macro use_Loader_Image
|
||
;предназначен для загрузки образов выше 1 Мб.
|
||
;первоначальная версия загружает образ дискеты 1.44 мб
|
||
{
|
||
local .start_p_LI
|
||
local .exit
|
||
local .error_LI
|
||
local .rest_value_loop
|
||
local .found_end_str
|
||
mov di, point_default ;restore value
|
||
mov cx, save_cx_d
|
||
;обработка конструкции типа LoaderModule=kord/kolibri.ldm
|
||
.start_p_LI:
|
||
call get_firs_sym ;get first symbol on new line
|
||
test cx, cx
|
||
jz .exit ;нету? ну ладно - следующее значение тогда )
|
||
cmp al, 'L'
|
||
jnz .start_p_LI
|
||
;проверка на значение LoaderModule
|
||
; parse_LoaderModule
|
||
mov bx, cx
|
||
mov ax, di
|
||
|
||
mov si, parse_LoaderImage
|
||
mov cx, parse_LoaderImage_e - parse_LoaderImage
|
||
repe cmpsb
|
||
jnz .rest_value_loop ;is not compare
|
||
|
||
sub bx, parse_LoaderImage_e - parse_LoaderImage;correct cx
|
||
add bx, cx
|
||
mov cx, bx
|
||
|
||
; test status_flag,flag_found_LM ;оценка флагов
|
||
; jz .correct_is_not_set_LI
|
||
|
||
; mov si,found_equal_timeout ;мы нашли что флаг уже установлен, информируем
|
||
; call printplain
|
||
; jmp .get_next_str
|
||
|
||
;.correct_is_not_set_LI:
|
||
mov ax, 0x3d20 ;cut al=' ' ah='='
|
||
repe scasb
|
||
jcxz .rest_value_loop_LI ;not found param timeout
|
||
|
||
cmp ah, byte [es:di-1] ;find '='
|
||
jnz .rest_value_loop_LI
|
||
|
||
repe scasb ;cut ' '
|
||
inc cx
|
||
dec di
|
||
;di указывает на начало блока информации, в cx длинна до конца секции.
|
||
;после загрузки заноситься значение занятой памяти.
|
||
;для того что бы загрузить модуль, воспользуемся callback сервисом
|
||
;оригинальное решение - разместим dd перед строчкой и после строчки разместим byte =0
|
||
;это выглядит так: в ini файле существует строчка LoaderModule = kord/kernel.loader
|
||
;мы ее модифицируем до такого состояния dw,dw,db'kord/kernel.loader',0 конечно сохранив те значения которые мы заменяем
|
||
;сохранили певые 2 word
|
||
push dword [es:di-6]
|
||
lea si, [di-6]
|
||
|
||
push word [es:di-2]
|
||
xor ax, ax
|
||
mov word [es:di-6], ax ;вносим нужные значения
|
||
;info_real_mode_size размер и указатель на область в которую можно загрузиться
|
||
mov ax, info_real_mode_size ;0x3000 ;следующий сегмент за данными
|
||
|
||
|
||
mov word [es:di-4], ax
|
||
mov word [es:di-2], 16 ;кол-во блоков по 4 кб =64 кб т.е. больше не считаем
|
||
;;;;;; поиск конца строчки
|
||
@@:
|
||
mov al, byte [es:di]
|
||
cmp al, ' '
|
||
jz .found_end_str
|
||
cmp al, 0xa
|
||
jz .found_end_str
|
||
cmp al, 0xd
|
||
jz .found_end_str
|
||
inc di
|
||
dec cx
|
||
jnz @b
|
||
;;;not found допустим,что это конец файла и он не имеет привычного заверешния строки
|
||
.found_end_str:
|
||
; чтение блока по 64 кб в сегмент и забрасывание его выше 1 мб.
|
||
push word [es:di]
|
||
xor ax, ax
|
||
mov word [es:di], ax
|
||
; xor ax,ax ; function 1 - read file
|
||
mov di, si ;file_data
|
||
inc ax
|
||
push si
|
||
push es
|
||
call far dword [loader_callback]
|
||
push cs
|
||
pop ds
|
||
|
||
pop es
|
||
pop si
|
||
|
||
test bx, bx
|
||
jnz .error_LM
|
||
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; забрасывание блока в 64 кб выше 1 мб.
|
||
mov si, table_15_87
|
||
push es
|
||
push ds
|
||
pop es
|
||
mov cx, 256*18
|
||
mov ah, 0x87
|
||
int 0x15
|
||
pop es
|
||
pop dx cx
|
||
test ah, ah
|
||
|
||
|
||
|
||
jmp far dword [es:si]
|
||
|
||
|
||
|
||
|
||
.rest_value_loop:
|
||
mov di, ax
|
||
mov cx, bx
|
||
jmp .start_p_LI
|
||
|
||
.exit:
|
||
|
||
|
||
|
||
}
|
||
|
||
|
||
|
||
macro name_in_root_fat
|
||
;макрос, который записывает информацию о загруженном файле в корневую фат таблицу
|
||
{
|
||
|
||
}
|
||
|
||
|
||
|
||
macro use_RamdiskFile
|
||
{
|
||
;загрузка файлов с использование callback сервиса первичного загрузчика
|
||
;используется только для загрузки необходимых и небольших файлов, т.к. достаточно медленно работает
|
||
;для загрузки использует 0х87 функцию int 0x15 прерывания - загрузка блоков данных до 64 кб выше 1 мб
|
||
local .start_loop
|
||
local ._end
|
||
local .rest_value_loop
|
||
local .error
|
||
mov di, point_default ;restore value
|
||
mov cx, save_cx_d
|
||
mov data_offset, 0 ;clean offset
|
||
;обработка конструкции типа LoaderModule=kord/kolibri.ldm
|
||
.start_loop:
|
||
call get_firs_sym ;get first symbol on new line
|
||
test cx, cx
|
||
jz ._end ;нету? ну ладно - следующее значение тогда )
|
||
cmp al, 'R'
|
||
jnz .start_loop
|
||
;проверка на значение RamdiskFile
|
||
mov bx, cx
|
||
mov ax, di
|
||
|
||
mov si, parse_RamdiskFile
|
||
mov cx, parse_RamdiskFile_e - parse_RamdiskFile
|
||
repe cmpsb
|
||
jnz .rest_value_loop ;is not compare
|
||
|
||
sub bx, parse_RamdiskFile_e - parse_RamdiskFile;correct cx
|
||
add bx, cx
|
||
mov cx, bx
|
||
; test status_flag,flag_found_LM ;оценка флагов
|
||
; jz .correct_is_not_set_LM
|
||
|
||
; mov si,found_equal_timeout ;мы нашли что флаг уже установлен, информируем
|
||
; call printplain
|
||
; jmp .get_next_str
|
||
|
||
;.correct_is_not_set_LM:
|
||
mov ax, 0x3d20 ;cut al=' ' ah='='
|
||
repe scasb
|
||
test ecx, ecx
|
||
jz .rest_value_loop ;not found param timeout
|
||
|
||
cmp ah, byte [es:di-1] ;find '='
|
||
jnz .rest_value_loop
|
||
|
||
repe scasb ;cut ' '
|
||
inc cx
|
||
dec di
|
||
|
||
mov save_di_RAMDISK, di
|
||
mov save_cx_RAMDISK, cx
|
||
;di указывает на начало блока информации, в cx длинна до конца секции.
|
||
;после загрузки заноситься значение занятой памяти.
|
||
;для того что бы загрузить модуль, воспользуемся callback сервисом
|
||
;оригинальное решение - разместим dd перед строчкой и после строчки разместим byte =0
|
||
;это выглядит так: в ini файле существует строчка RamdiskFile = @menu,@menu
|
||
;мы ее модифицируем до такого состояния dw,dw,db'@menu',0 конечно сохранив те значения которые мы заменяем
|
||
;сохранили певые 2 word
|
||
|
||
;
|
||
@@:
|
||
mov al, byte [es:di]
|
||
cmp al, ',' ; т.е. ищем разделитель
|
||
jz .found_end_str
|
||
inc di
|
||
dec cx
|
||
jnz @b
|
||
;;;not found допустим,что это конец файла и он не имеет привычного завершения строки
|
||
.found_end_str:
|
||
; mov al,byte [es:di]
|
||
; cmp al,' ' ; убираем пробелы, если они есть
|
||
; jnz @f
|
||
; inc di
|
||
; dec cx
|
||
; jnz .found_end_str
|
||
|
||
;@@:
|
||
mov point_to_dest_file_name, di
|
||
inc di
|
||
;проверка индивидуальности имени файла
|
||
check_name_file
|
||
;/restore di - point and cx -size section
|
||
mov di, save_di_RAMDISK
|
||
mov cx, save_cx_RAMDISK
|
||
|
||
test al, al
|
||
jnz .start_loop ;если в al значение не =0, то такое имя уже существует в системе.
|
||
|
||
|
||
|
||
push dword [es:di-6]
|
||
lea si, [di-6]
|
||
|
||
push word [es:di-2]
|
||
push di
|
||
xor ax, ax
|
||
mov word [es:di-6], ax ;вносим нужные значения
|
||
;info_real_mode_size размер и указатель на область в которую можно загрузиться
|
||
mov ax, info_real_mode_size ;0x3000 ;следующий сегмент за данными
|
||
|
||
|
||
mov word [es:di-4], ax
|
||
mov word [es:di-2], 16 ;кол-во блоков по 4 кб =64 кб т.е. больше не читаем
|
||
|
||
mov di, point_to_dest_file_name
|
||
|
||
if DEBUG
|
||
pushad
|
||
; mov ax,di
|
||
mov cx, 0x0a
|
||
mov di, name_of_seg_get_64
|
||
mov dword[ds:di], ' '
|
||
mov word[ds:di+4], ' '
|
||
call decode
|
||
;Show size
|
||
mov si, name_of_seg_get_64
|
||
call printplain
|
||
|
||
popad
|
||
end if
|
||
|
||
push word [es:di]
|
||
push cx
|
||
xor ax, ax
|
||
mov word [es:di], ax
|
||
; xor ax,ax ; function 1 - read file
|
||
push di
|
||
mov di, si ;file_data
|
||
inc ax
|
||
push si
|
||
push es
|
||
push bp
|
||
|
||
push es
|
||
pop ds
|
||
push cs
|
||
pop es
|
||
|
||
call far dword [es:loader_callback]
|
||
|
||
|
||
push cs
|
||
pop ds
|
||
|
||
pop bp
|
||
pop es
|
||
pop si
|
||
|
||
cmp bx, 2
|
||
ja .error
|
||
; сейчас у нас в dx:ax размер файла, который мы загрузили.
|
||
; возможна ситуация, когда в bx=1 т.е. есть еще данные на диске
|
||
mov status_flag_loader_f, bx
|
||
|
||
shl edx, 16
|
||
mov dx, ax
|
||
; shr edx,10 ;размер файла в кб.
|
||
;;в edx размер в байтах.
|
||
mov save_file_size, edx
|
||
mov eax, edx
|
||
;восстановим полностью файл сценария
|
||
pop di
|
||
pop cx ;длинна остатка с 2-ой частью имени т.е. с именем назначением.
|
||
pop word [es:di]
|
||
pop di
|
||
pop word [es:di-2]
|
||
pop dword [es:di-6]
|
||
|
||
|
||
if DEBUG
|
||
pushad
|
||
mov cx, 0x0a
|
||
mov di, RamdiskFile_msg
|
||
mov dword[ds:di], ' '
|
||
call decode
|
||
;Show size
|
||
mov si, RamdiskFile_msg
|
||
call printplain
|
||
|
||
popad
|
||
end if
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
; загрузим чему у нас равен кластер
|
||
; mov ax,word [fat12_buffer.BPB_BytsPerSec] ;кол-во байтов в секторе может быть любое 512 1024 2048 4096 2 байта
|
||
; movzx bx,byte [fat12_buffer.BPB_SecPerClus] ;кол-во секторов в кластере
|
||
; imul ax,bx
|
||
;сейчас в eax размер кластера (512) байт
|
||
;в edx длина файла в байтах до 64 кб
|
||
;закиним файл за 1 мб
|
||
;1 нам нужно составить фат таблицу т.е. произвести разметку рамдиска, затем перенесем по адресу файл
|
||
|
||
;записать инфорамацию о файле в корневую директорию
|
||
register_file_in_fat
|
||
;перенести за 1 мб содержимое файла
|
||
move_file_up
|
||
|
||
;проверим, загружен ли до конца файл? т.е. если размер файла больше чем 64 кб, то будет подгружать оставшиеся блоки
|
||
cmp status_flag_loader_f, 0x1
|
||
jnz @f
|
||
;нужно дозагузить данные файла и перенести их за 1-ый мб согласно фат структуре
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
@@:
|
||
;тут организован цикл по загрузке файлов в корневую директорию
|
||
mov di, save_di_RAMDISK
|
||
mov cx, save_cx_RAMDISK
|
||
if DEBUG
|
||
pusha
|
||
xor ax, ax
|
||
int 0x16
|
||
popa
|
||
end if
|
||
|
||
|
||
jmp .start_loop
|
||
|
||
|
||
.error:
|
||
;call error.LoaderModule
|
||
;fixme!
|
||
.rest_value_loop:
|
||
mov di, ax
|
||
mov cx, bx
|
||
jmp .start_loop
|
||
|
||
._end:
|
||
;перенесем за 1-ый мб фат и рут дир
|
||
move_up_fat_and_root_d
|
||
|
||
|
||
|
||
|
||
|
||
|
||
;загрузка блока
|
||
; mov ah,0x87
|
||
; mov cx, ;size in byte
|
||
|
||
|
||
;es:si point to descripts
|
||
|
||
|
||
}
|
||
|
||
macro use_BPB_RAM ;закинуть самые первые 512 байт за 1-й мб
|
||
;данный макрос закидывает BPB структуру т.е. первые 512 байт, пока только фат12 за 1 мб
|
||
{
|
||
mov ax, fat12_buffer
|
||
mov si, table_15_87
|
||
add word [si+8*2+2], ax
|
||
push es
|
||
push ds
|
||
pop es
|
||
mov cx, 256 ;бут сектор укладывается в 512 байт 512/2=256
|
||
mov ah, 0x87
|
||
int 0x15
|
||
pop es
|
||
;add 512 byte for destination adress
|
||
; add dword [si+8*3+2], 512
|
||
; test ah, ah
|
||
; jz
|
||
if DEBUG
|
||
pusha
|
||
mov ax, word [si+8*2+2]
|
||
mov cx, 0x0a
|
||
mov di, BPB_msg
|
||
call decode
|
||
;Show size
|
||
mov si, BPB_msg
|
||
call printplain
|
||
popa
|
||
end if
|
||
}
|
||
macro first_create_fat_table
|
||
;данный макрос создает оформляет 3 первых байта fat таблицы, и устанавливает указатель на следующий блок, и вносит 0 значение
|
||
;для смещения в корневой таблице.
|
||
{
|
||
mov al, byte [fat12_buffer.BPB_Media]
|
||
|
||
|
||
push ds
|
||
|
||
|
||
mov di, info_real_mode_size
|
||
add di, 0x1000
|
||
|
||
if DEBUG
|
||
pushad
|
||
|
||
mov ax, info_real_mode_size
|
||
add ax, 0x1000
|
||
; mov ax,ds
|
||
mov cx, 0xa
|
||
|
||
mov di, first_entry_in_fat
|
||
mov dword [di], ' '
|
||
mov word [di+4], ' '
|
||
call decode
|
||
;Show size
|
||
mov si, first_entry_in_fat
|
||
call printplain
|
||
|
||
xor ax, ax
|
||
int 0x16
|
||
|
||
popad
|
||
end if
|
||
|
||
|
||
push di ; push word info_real_mode_size+0x1000 ;cледующий сегмент за загруженным участком
|
||
|
||
xor di, di
|
||
mov point_to_free_root, di ;значение смещения =0 в корневой фат таблице описания
|
||
|
||
pop ds ; загружен следующий сегмент т.е. пустой сегмент
|
||
|
||
mov byte [di], al
|
||
or ax, -1
|
||
inc di
|
||
mov word [di], ax
|
||
|
||
pop ds
|
||
mov point_next_fat_str, 3
|
||
|
||
if DEBUG
|
||
pushad
|
||
mov ax, point_next_fat_str
|
||
mov cx, 0x0a
|
||
mov di, fat_create_msg
|
||
call decode
|
||
;Show size
|
||
mov si, fat_create_msg
|
||
call printplain
|
||
popad
|
||
end if
|
||
|
||
}
|
||
macro register_file_in_fat
|
||
;макрос регистрации файла в файловой структуре Fat
|
||
;пока поддерживается только фат12, пока ))
|
||
;вычисление смежных кластеров и занесение инфы в fat/
|
||
{
|
||
local .step2
|
||
local .step3
|
||
local .end
|
||
local .eof_file
|
||
|
||
;di point on root dir на фри секцию.
|
||
push es
|
||
|
||
mov ax, info_real_mode_size
|
||
add ax, 0x1000
|
||
mov es, ax ; push word info_real_mode_size+0x1000 ;сегмент следующий за загруженным блоком в 64 кб
|
||
|
||
; определяем тип фат пока не определяем, пока только фат 12
|
||
; 12 бит, для вычесления соседних каластеров.
|
||
mov di, firstDataSect ;в секторах
|
||
sub di, size_root_dir
|
||
;теперь в ax размер в секторах начала рут дир
|
||
shl di, 9;imul 512
|
||
add di, point_to_free_root ;смещение в уже записанных 32-х структурах.
|
||
;необходимо внести значение в рут дир т.е. 32 байта
|
||
if DEBUG
|
||
pushad
|
||
; mov ax,point_default
|
||
; mov ax,
|
||
mov cx, 0x0a
|
||
mov di, show_db2
|
||
mov dword[ds:di], ' '
|
||
mov word [ds:di+4], ' '
|
||
call decode
|
||
;Show size
|
||
mov si, show_db2
|
||
call printplain
|
||
;
|
||
; xor ax,ax
|
||
; int 0x16
|
||
popad
|
||
end if
|
||
|
||
|
||
|
||
;gs:di - указатель для внесения инфорации в рут область фат таблицы инормации о файле.
|
||
mov si, shot_name_fat
|
||
mov cx, 11
|
||
;запишем в структуру имя
|
||
@@:
|
||
lodsb
|
||
stosb
|
||
loop @b
|
||
|
||
;запишем атрибуты файла и DIR_NTRes - зарезеврированный байт =0
|
||
xor ax, ax
|
||
mov ah, ATTR_VOLUME_ID
|
||
mov word [es:di], ax
|
||
add di, 2
|
||
;DIR_CrtTimeTenth
|
||
mov byte [es:di], 100
|
||
inc di
|
||
;DIR_CrtTime
|
||
mov word [es:di], 0x032b ;дата
|
||
add di, 2
|
||
;DIR_CrtDate
|
||
mov word [es:di], 0x0 ;время ><
|
||
add di, 2
|
||
;DIR_LstAccDate
|
||
mov word [es:di], 0x032b ;дата моего
|
||
add di, 2
|
||
;DIR_FstClusHI
|
||
mov word [es:di], 0x0 ;время для фат12 /16 всегда 0
|
||
add di, 2
|
||
;DIR_WrtTime
|
||
mov word [es:di], 0x0 ;время ><
|
||
add di, 2
|
||
;DIR_WrtDate
|
||
mov word [es:di], 0x032b
|
||
add di, 2
|
||
|
||
mov ax, point_next_fat_str
|
||
mov word [es:di], ax
|
||
add di, 2
|
||
|
||
push di
|
||
;DIR_FstClusLO Младшее слово номера первого кластера.
|
||
; mov ax,point_next_fat_str ;загрузим указатель на элемент фат таблицы т.е. это номер фат записи
|
||
;FATOffset = N + (N / 2) т.е. это уже у нас смещение мы знаем что -начинается все с 3-го элемента записи фат
|
||
mov bx, ax
|
||
shr bx, 1
|
||
add ax, bx
|
||
;в ах сейчас FATOffset
|
||
;ThisFATEntOffset = BPB_ResvdSecCnt + (FATOffset / BPB_BytsPerSec);
|
||
mov bx, word [fat12_buffer.BPB_BytsPerSec]
|
||
cwd
|
||
idiv bx
|
||
;ax=ThisFATEntOffset= rem (FATOffset / BPB_BytsPerSec) четный или нечетный указатель.
|
||
mov si, ax
|
||
;нам нужно в цикле записать все кластеры которые будут использованы для размещения файла.
|
||
;узнаем размер кластера.
|
||
movzx eax, word [fat12_buffer.BPB_BytsPerSec]
|
||
movzx ebx, byte [fat12_buffer.BPB_SecPerClus]
|
||
imul eax, ebx
|
||
;ax - размер кластера.
|
||
;сейчас будем записывать во временный буфер фат таблицу для выбранного файла. Поскольку мы его загрузили возможно не полностью
|
||
;мы обработаем запись для фат полностью, в не зависимости от предела буфера где возможна часть файла.
|
||
mov ebx, save_file_size ;размер файла в байтах
|
||
|
||
@@:
|
||
sub ebx, eax
|
||
cmp ebx, eax
|
||
jbe .eof_file
|
||
|
||
inc point_next_fat_str
|
||
mov cx, point_next_fat_str ;загрузим указатель на элемент фат таблицы т.е. это номер фат записи
|
||
;FATOffset = N + (N / 2) т.е. это уже у нас смещение мы знаем что -начинается все с 3-го элемента записи фат
|
||
mov dx, ax
|
||
shr dx, 1
|
||
add cx, dx
|
||
|
||
|
||
|
||
test si, 0x1
|
||
jz .step2
|
||
shl cx, 4
|
||
mov word[es:si], cx
|
||
inc si
|
||
add cx, ax
|
||
jmp @b
|
||
|
||
.step2:
|
||
and cx, 0x0FFF
|
||
mov word[es:si], cx
|
||
inc si
|
||
add cx, ax
|
||
jmp @b
|
||
|
||
.eof_file:
|
||
mov cx, 0x0fff
|
||
test si, 0x1
|
||
jz .step3
|
||
shl cx, 4
|
||
mov word[es:si], cx
|
||
jmp .end
|
||
|
||
.step3:
|
||
and cx, 0x0FFF
|
||
mov word[es:si], cx
|
||
|
||
.end:
|
||
inc point_next_fat_str
|
||
|
||
pop di
|
||
;DIR_FileSize 32-битный DWORD содержит размер файла в байтах.
|
||
mov eax, save_file_size
|
||
mov dword [es:di], eax
|
||
|
||
if DEBUG
|
||
pushad
|
||
|
||
mov di, firstDataSect ;в секторах
|
||
sub di, size_root_dir
|
||
;теперь в ax размер в секторах начала рут дир
|
||
shl di, 9;imul 512
|
||
add di, point_to_free_root ;смещение в уже записанных 32-х структурах.
|
||
|
||
push di
|
||
|
||
mov si, dest_name_fat
|
||
mov cx, 11
|
||
|
||
;запишем в структуру имя
|
||
@@:
|
||
mov al, byte [es:di]
|
||
inc di
|
||
mov byte [ds:si], al
|
||
inc si
|
||
loop @b
|
||
|
||
mov di, si
|
||
inc di
|
||
pop ax
|
||
mov cx, 0xa
|
||
call decode
|
||
|
||
mov si, dest_name_fat
|
||
call printplain
|
||
popad
|
||
|
||
END IF
|
||
|
||
|
||
|
||
|
||
|
||
add point_to_free_root, 32 ;увелицим смещение до следующего значения.
|
||
pop es
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
macro get_firstDataSector
|
||
;макрос для вычисления певого сектора данных т.е. данных файлов в фате
|
||
;вычислим FirstDataSector = BPB_ResvdSecCnt + (BPB_NumFATs * FATSz) + RootDirSectors;
|
||
{
|
||
mov ax, word [fat12_buffer.BPB_FATSz16]
|
||
movzx bx, byte [fat12_buffer.BPB_NumFATs]
|
||
imul ax, bx ;9x1=9
|
||
;ax=BPB_NumFATs * FATSz
|
||
mov bx, word [fat12_buffer.BPB_RootEntCnt] ; count of 32-byte dir. entries (224*32 = 14 sectors= 7 kb)
|
||
shr bx, 4 ;imul bx,32 and then div 512 -> in bx size in sectors
|
||
add ax, bx ;9+14=23
|
||
mov size_root_dir, bx
|
||
movzx bx, byte [fat12_buffer.BPB_RsvdSecCnt] ;add 1 for fat 16/12
|
||
add ax, bx
|
||
;ax=firstDataSector - где начинается первый секторо от 0 сектора в секторах. - фактически = 24 сектор
|
||
mov firstDataSect, ax ;сохраним для вычисления
|
||
; получимзначение кластеров, это объем в который мы можем записать данные
|
||
mov bx, word [fat12_buffer.BPB_TotSec16]
|
||
sub bx, ax
|
||
mov ax, bx
|
||
movzx bx, byte [fat12_buffer.BPB_SecPerClus]
|
||
cwd
|
||
idiv bx
|
||
mov DataClasters, ax
|
||
|
||
if DEBUG
|
||
pushad
|
||
mov ax, firstDataSect ;первый сектор данных
|
||
mov cx, 0x0a
|
||
mov di, firstDataSect_msg
|
||
call decode
|
||
;Show size
|
||
mov si, firstDataSect_msg
|
||
call printplain
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
mov ax, size_root_dir ;размер рут дир в сетокторах
|
||
mov cx, 0x0a
|
||
mov di, size_root_dir_msg
|
||
call decode
|
||
;Show size
|
||
mov si, size_root_dir_msg
|
||
call printplain
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
mov ax, DataClasters;кластеры
|
||
mov cx, 0x0a
|
||
mov di, DataClasters_msg
|
||
call decode
|
||
;Show size
|
||
mov si, DataClasters_msg
|
||
call printplain
|
||
popad
|
||
|
||
end if
|
||
|
||
}
|
||
|
||
macro use_RamdiskPATHS
|
||
;парсинг пути источника файлов.
|
||
{
|
||
|
||
}
|
||
|
||
macro use_RamdiskPATHD
|
||
;парсинг пути назначения файлов.
|
||
{
|
||
|
||
}
|
||
macro check_name_file
|
||
;макрос проверки имени на повтор, имя должно быть уникальным.
|
||
;входные данные: es- сегмент где лежит файл для парсинга т.е. startos.ini
|
||
;di - указатель на имя файла т.е. es:di указывает на имя файла назначения
|
||
;выходные данные eax =-1 имя совпало, eax=0 имя не совпало.
|
||
{
|
||
local .no_equal
|
||
local .exit
|
||
local .loop_size_root_dir
|
||
;вычислим длинну строчки имени назначения, которую будем сравнивать с уже записанными данными.
|
||
;преобразуем в аналог фат записи сточку с именем назначения
|
||
convertion_file_name ; преобразовали имя по нужным правилам
|
||
test ax, ax
|
||
jnz .exit
|
||
|
||
lea si, [shot_name_fat] ; desination name of file
|
||
|
||
;вычислим указатель на корневую директорию
|
||
mov di, firstDataSect
|
||
sub di, size_root_dir
|
||
;теперь в ax размер в секторах начала рут дир
|
||
shl di, 9;imul 512
|
||
;di= Это смещение от начала буфера до рут директории. в пределах 64 кб.
|
||
;загрузим значение - т.е. кол-во элементов, которые мы можем просматривать.
|
||
mov dx, root_dir_entry_count
|
||
|
||
mov ax, info_real_mode_size
|
||
add ax, 0x1000
|
||
|
||
|
||
mov gs, ax
|
||
.loop_size_root_dir:
|
||
DEBUG1 equ 0
|
||
if DEBUG1
|
||
pushad
|
||
push di
|
||
mov eax, dword[gs:di]
|
||
lea si, [check_root_fat_+14]
|
||
mov dword [ds:si], '----'
|
||
mov dword [ds:si+4], '----'
|
||
mov dword [ds:si+8], '----'
|
||
mov dword[ds:si], eax
|
||
mov eax, dword[gs:di+4]
|
||
mov dword[ds:si+4], eax
|
||
mov eax, dword[gs:di+8]
|
||
mov dword[ds:si+8], eax
|
||
|
||
;
|
||
xor eax, eax
|
||
mov ax, gs;point_next_fat_str
|
||
mov cx, 0x0a
|
||
mov di, check_root_fat_
|
||
mov dword [di], ' '
|
||
mov word [di+4], ' '
|
||
call decode
|
||
xor eax, eax
|
||
pop ax
|
||
mov di, (check_root_fat_+7)
|
||
mov dword [di], ' '
|
||
mov word [di+4], ' '
|
||
call decode
|
||
|
||
;Show size
|
||
lea si, [check_root_fat_]
|
||
call printplain
|
||
|
||
lea si, [shot_name_fat]
|
||
call printplain
|
||
|
||
xor ax, ax
|
||
int 0x16
|
||
popad
|
||
end if
|
||
|
||
xor bx, bx
|
||
mov cx, 11 ;size of name in struct FAT
|
||
|
||
@@:
|
||
mov al, byte [ds:si+bx] ;ds:si - point to name of convertion variable.
|
||
mov ah, byte [gs:di+bx] ;gs:di - point to name in fat struct
|
||
inc bx
|
||
|
||
if DEBUG
|
||
; pushad
|
||
; lea si,[check_root_fat_+14]
|
||
; mov dword [ds:si],'----'
|
||
; mov word [ds:si],ax
|
||
; call printplain
|
||
|
||
; xor ax,ax
|
||
; int 0x16
|
||
|
||
; popad
|
||
end if
|
||
|
||
|
||
|
||
cmp ah, al
|
||
jnz .no_equal
|
||
|
||
; dec cx
|
||
; jnz @b
|
||
loop @b
|
||
|
||
;.succesfuly:
|
||
;печально, такое имя уже имеется :(
|
||
or ax, -1
|
||
jmp .exit
|
||
|
||
|
||
.no_equal:
|
||
add di, 32 ;fat struct =32 byte
|
||
dec dx
|
||
jnz .loop_size_root_dir
|
||
|
||
;.exit_check_name:
|
||
and ax, 0
|
||
|
||
.exit:
|
||
|
||
if DEBUG
|
||
pushad
|
||
;Show size
|
||
lea si, [check_name_fat_msg_n]
|
||
test ax, ax
|
||
jz @f
|
||
lea si, [check_name_fat_msg_y]
|
||
call printplain
|
||
lea si, [alarm_msg]
|
||
@@:
|
||
call printplain
|
||
popad
|
||
end if
|
||
|
||
}
|
||
|
||
|
||
macro convertion_file_name
|
||
;макрос конвертации имени, это нужно поскольку формат представленный не соответсвует фат и напрямую редко можно когда использовать
|
||
;преобразование имени типа hello.asm в 'HELLO ASM', в соответствии с правилами fat.
|
||
;входные параметры es:di указатель на имя файла которое нужно преобразовать, конечный буфер shot_name_fat
|
||
{
|
||
local .next_step
|
||
local .error
|
||
local .st1
|
||
local .st2
|
||
local .st2_l
|
||
local .st3
|
||
local .st4_s
|
||
local .st4
|
||
local .st5
|
||
|
||
;вычислим длинну строчки имени назначения, которую будем сравнивать с уже записанными данными.
|
||
; mov di,point_to_dest_file_name входной параметр
|
||
mov si, shot_name_fat
|
||
or first_input, -1 ;при первом входе устанавливаем флаг
|
||
mov cx, 11 ;длинна имени в стуктуре фат таблицы
|
||
|
||
@@:
|
||
mov al, byte [es:di]
|
||
cmp al, 0xa
|
||
jz .st4_s
|
||
cmp al, 0xd
|
||
jz .st4_s
|
||
cmp al, 0x20
|
||
jz .st4_s
|
||
|
||
cmp al, 0x20
|
||
jb .error
|
||
cmp al, 0x22
|
||
jz .error
|
||
cmp al, 0x2a
|
||
jz .error
|
||
cmp al, 0x2b
|
||
jz .error
|
||
cmp al, 0x2c
|
||
jz .error
|
||
cmp al, 0x2F
|
||
jz .error
|
||
|
||
cmp al, 0x3a
|
||
jz .error
|
||
cmp al, 0x3b
|
||
jz .error
|
||
cmp al, 0x3c
|
||
jz .error
|
||
cmp al, 0x3d
|
||
jz .error
|
||
cmp al, 0x3E
|
||
jz .error
|
||
cmp al, 0x3F
|
||
jz .error
|
||
|
||
cmp al, 0x5b
|
||
jz .error
|
||
cmp al, 0x5c
|
||
jz .error
|
||
cmp al, 0x5d
|
||
jz .error
|
||
|
||
cmp al, 0x7c
|
||
jz .error
|
||
|
||
|
||
cmp first_input, -1
|
||
jnz .next_step
|
||
and first_input, 0 ;сборосим флаг.
|
||
cmp al, '.'
|
||
jz .error ;обработка точки, файл не может начинаться с точки
|
||
|
||
.next_step:
|
||
cmp al, 0x2e
|
||
jnz .st2 ;обработка точки, в середине файла
|
||
;тут у нас установлен разделитель
|
||
;все остальнео место займут пробелы
|
||
mov al, ' '
|
||
|
||
;!fixme обработаны не все исключения :(
|
||
cmp cl, 3 ;формат файла такой GIDGIDIIASM т.е. gidgidii.asm
|
||
jbe .st2
|
||
|
||
|
||
.st3:
|
||
mov byte [si], al
|
||
inc si
|
||
dec cx
|
||
cmp cx, 3
|
||
ja .st3
|
||
; inc cx
|
||
inc di
|
||
jmp @b
|
||
|
||
.st2:
|
||
cmp al, 0x60
|
||
jbe .st2_l
|
||
|
||
xor al, 0x20;сделаем заглавные буквы
|
||
.st2_l:
|
||
mov byte [si], al
|
||
inc di
|
||
inc si
|
||
; dec cx
|
||
; jnz @b
|
||
loop @b
|
||
.st5:
|
||
xor ax, ax
|
||
jmp @f
|
||
|
||
;;;;;;;;файл закончился, и нужно внести в конец пробелы
|
||
.st4_s:
|
||
mov al, ' '
|
||
.st4:
|
||
mov byte [si], al
|
||
inc si
|
||
loop .st4
|
||
jmp .st5
|
||
|
||
.error:
|
||
or ax, -1
|
||
@@:
|
||
|
||
if DEBUG
|
||
pushad
|
||
|
||
mov si, convertion_file_name_msg_y
|
||
test ax, ax
|
||
jz @f
|
||
mov si, convertion_file_name_msg_n
|
||
@@:
|
||
call printplain
|
||
|
||
mov si, shot_name_fat
|
||
mov byte [si+12], 0
|
||
call printplain
|
||
popad
|
||
|
||
end if
|
||
}
|
||
|
||
macro move_file_up
|
||
;макрос который перемещает за 1 мб с правилами фат данные файла.
|
||
{
|
||
local .st1
|
||
local .correct_on_byte
|
||
;сейчас имеет быть ситуация, когда BPB уже перемещен за 1 мб, фат, и рут дир будут позже перемещены,
|
||
;а нам нужно вычислить место, и перенести туда содержимое файла
|
||
;полученое значение указывает в байтах на начало данных
|
||
|
||
mov ax, info_real_mode_size ; сегмент где расположены данные
|
||
mov si, table_15_87
|
||
mov word [si+8*2+2], ax
|
||
;смещение до данных уже за 1-м мб
|
||
movzx eax, firstDataSect
|
||
movzx edx, data_offset
|
||
add eax, edx
|
||
|
||
movzx ebx, word [fat12_buffer.BPB_BytsPerSec]
|
||
movzx edx, byte [fat12_buffer.BPB_SecPerClus]
|
||
imul bx, dx ;получим размер кластера
|
||
|
||
|
||
|
||
push ebx ;save bx
|
||
|
||
imul eax, ebx
|
||
; shl eax,9 ;умножим на 512
|
||
|
||
if DEBUG
|
||
pushad
|
||
xor eax, eax
|
||
mov ax, info_real_mode_size
|
||
mov cx, 0x0a
|
||
mov di, seg_where_get_data
|
||
mov dword [di], ' '
|
||
mov word [di+4], ' '
|
||
call decode
|
||
;Show size
|
||
mov si, seg_where_get_data
|
||
call printplain
|
||
popad
|
||
|
||
end if
|
||
|
||
; mov bx,word [fat12_buffer.BPB_BytsPerSec]
|
||
; movzx dx,byte [fat12_buffer.BPB_SecPerClus]
|
||
; imul bx,dx
|
||
; cwd
|
||
; idiv bx
|
||
|
||
mov dl, 0x10
|
||
|
||
@@:
|
||
cmp eax, 0x00010000
|
||
jb @f
|
||
|
||
sub eax, 0x00010000
|
||
inc dl
|
||
jmp @b
|
||
|
||
|
||
@@:
|
||
mov byte [si+8*3+3], dl ;куда писать
|
||
mov word [si+8*3+2], ax
|
||
|
||
mov ecx, save_file_size ;размер файла в байтах.
|
||
cmp ecx, 0x0000ffff ;размер блока т.е. 64 кб
|
||
jbe .correct_on_byte ;корректировка на байт значения
|
||
|
||
|
||
|
||
mov ecx, 0x00010000 ;65536
|
||
sub save_file_size, ecx ;отнимим
|
||
; jmp .st1 ;получим 0х8000
|
||
|
||
|
||
|
||
|
||
;корректировка значения должна быть выполенена на размер кластера
|
||
.correct_on_byte:
|
||
;/узнаем размер кластера
|
||
pop eax ;restore size of claster
|
||
push ecx
|
||
@@:
|
||
inc data_offset
|
||
|
||
cmp eax, ecx
|
||
jae @f
|
||
sub ecx, eax
|
||
jmp @b
|
||
@@:
|
||
pop ecx
|
||
|
||
|
||
|
||
|
||
test ecx, 0x1
|
||
jz .st1
|
||
inc ecx
|
||
.st1:
|
||
shr ecx, 1 ; преобразовать значение для 0x87 function
|
||
|
||
;перенесем блок за 1 мб
|
||
push es
|
||
push ds
|
||
pop es
|
||
|
||
mov ah, 0x87
|
||
int 0x15
|
||
pop es
|
||
|
||
if DEBUG
|
||
pusha
|
||
; mov ax,point_next_fat_str
|
||
mov cx, 0x0a
|
||
mov di, return_code_af_move
|
||
call decode
|
||
;Show size
|
||
mov si, return_code_af_move
|
||
call printplain
|
||
popa
|
||
|
||
end if
|
||
|
||
}
|
||
|
||
|
||
macro move_up_fat_and_root_d
|
||
;макрос, который позволяет перенести выше 1 мб в структуру образа фат таблицу и рут директорию
|
||
{
|
||
local .st1
|
||
|
||
mov ax, info_real_mode_size
|
||
add ax, 0x1000
|
||
|
||
mov si, table_15_87
|
||
mov word [si+8*2+2], ax
|
||
;смещение до данных
|
||
mov ax, 512
|
||
mov word [si+8*3+2], ax
|
||
;fixme! тут необходимо сделать подержку т.е. формировать смещение файла в уже записанных данных.
|
||
|
||
movzx ecx, word [fat12_buffer.BPB_FATSz16]
|
||
movzx bx, byte [fat12_buffer.BPB_NumFATs]
|
||
imul cx, bx ;9x1=9
|
||
|
||
add cx, size_root_dir ;размер корневой дирректории
|
||
shl ecx, 9 ;imul 512
|
||
|
||
|
||
;корректировка значения
|
||
test ecx, 0x1
|
||
jz .st1
|
||
inc ecx
|
||
.st1:
|
||
shr ecx, 1
|
||
|
||
push es
|
||
push ds
|
||
pop es
|
||
|
||
mov ah, 0x87
|
||
int 0x15
|
||
pop es
|
||
|
||
if DEBUG
|
||
pusha
|
||
; mov ax,point_next_fat_str
|
||
mov cx, 0x0a
|
||
mov di, return_code_af_fat_m
|
||
call decode
|
||
;Show size
|
||
mov si, return_code_af_fat_m
|
||
call printplain
|
||
popa
|
||
|
||
end if
|
||
|
||
}
|