Rev 1065 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1065 | Lrz | 1 | ; Copyright (c) 2008-2009, diamond |
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 |
||
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 aka |
||
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 |
||
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 | |||
3539 | clevermous | 27 | Читай между строк - там никогда не бывает опечаток. |
1065 | Lrz | 28 | |
3539 | clevermous | 29 | Бутсектор для FAT32-тома на носителе с размером сектора 0x200 = 512 байт. |
1065 | Lrz | 30 | |
31 | ===================================================================== |
||
32 | |||
3539 | clevermous | 33 | Есть две версии в зависимости от того, поддерживает ли носитель LBA, |
34 | выбор осуществляется установкой константы use_lba в первой строке исходника. |
||
35 | Требования для работы: |
||
36 | 1) Сам бутсектор, первая копия FAT и все используемые файлы |
||
37 | должны быть читабельны. (Если дело происходит на носителе с разбиением на |
||
38 | разделы и загрузочный код в MBR достаточно умный, то читабельности резервной |
||
39 | копии бутсектора (сектор номер 6 на томе) достаточно вместо читабельности |
||
40 | самого бутсектора). |
||
41 | 2) Минимальный процессор - 80386. |
||
42 | 3) В системе должно быть как минимум 584K свободной базовой памяти. |
||
1065 | Lrz | 43 | |
44 | ===================================================================== |
||
45 | |||
3539 | clevermous | 46 | Документация в тему (ссылки проверялись на валидность 15.05.2008): |
47 | официальная спецификация FAT: http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx |
||
48 | в формате PDF: http://staff.washington.edu/dittrich/misc/fatgen103.pdf |
||
49 | русский перевод: http://wasm.ru/docs/11/fatgen103-rus.zip |
||
50 | официальная спецификация расширения EDD BIOS 3.0: http://www.phoenix.com/NR/rdonlyres/19FEBD17-DB40-413C-A0B1-1F3F560E222F/0/specsedd30.pdf |
||
51 | то же, версия 1.1: http://www.phoenix.com/NR/rdonlyres/9BEDED98-6B3F-4DAC-BBB7-FA89FA5C30F0/0/specsedd11.pdf |
||
52 | описание функций BIOS: Interrupt List by Ralf Brown: http://www.cs.cmu.edu/~ralf/files.html |
||
53 | официальная спецификация Boot BIOS: http://www.phoenix.com/NR/rdonlyres/56E38DE2-3E6F-4743-835F-B4A53726ABED/0/specsbbs101.pdf |
||
1065 | Lrz | 54 | |
55 | ===================================================================== |
||
56 | |||
3539 | clevermous | 57 | Схема используемой памяти: |
58 | ...-7C00 стек |
||
59 | 7C00-7E00 код бутсектора |
||
60 | 7E00-8200 вспомогательный файл загрузчика (kordldr.f32) |
||
61 | 8400-8C00 информация о кэше для таблицы FAT: 100h входов по 8 |
||
62 | байт: 4 байта (две ссылки - вперёд и назад) для |
||
63 | организации L2-списка всех прочитанных секторов в |
||
64 | порядке возрастания последнего времени использования |
||
65 | + 4 байта для номера сектора; при переполнении кэша |
||
66 | выкидывается элемент из головы списка, то есть тот, |
||
67 | к которому дольше всех не было обращений |
||
68 | 60000-80000 кэш для таблицы FAT (100h секторов) |
||
69 | 80000-90000 текущий кластер текущей рассматриваемой папки |
||
70 | 90000-... кэш для содержимого папок (каждой папке отводится |
||
71 | 2000h байт = 100h входов, одновременно в кэше |
||
72 | может находиться не более 8 папок; |
||
73 | точный размер определяется размером доступной |
||
74 | физической памяти - как правило, непосредственно |
||
75 | перед A0000 размещается EBDA, Extended BIOS Data Area) |
||
1065 | Lrz | 76 | |
77 | ===================================================================== |
||
78 | |||
3539 | clevermous | 79 | Основной процесс загрузки. |
80 | Точка входа (start): получает управление от BIOS при загрузке, при этом |
||
81 | dl содержит идентификатор диска, с которого идёт загрузка |
||
82 | 1. Настраивает стек ss:sp = 0:7C00 (стек располагается непосредственно перед |
||
83 | кодом), сегмент данных ds = 0, и устанавливает ss:bp на начало |
||
84 | бутсектора (в дальнейшем данные будут адресоваться через [bp+N] - |
||
85 | это освобождает ds и экономит на размере кода). Сохраняет в стеке |
||
86 | идентификатор загрузочного диска для последующего обращения |
||
87 | через byte [bp-2]. |
||
88 | 2. LBA-версия: проверяет, поддерживает ли носитель LBA, вызовом функции 41h |
||
89 | прерывания 13h. Если нет, переходит на код обработки ошибок с |
||
90 | сообщением об отсутствии LBA. |
||
91 | CHS-версия: определяет геометрию носителя вызовом функции 8 прерывания 13h и |
||
92 | записывает полученные данные поверх BPB. Если вызов завершился ошибкой, |
||
93 | предполагает уже существующие данные корректными. |
||
94 | 3. Вычисляет начало данных FAT-тома, сохраняет его в стек для последующего |
||
95 | обращения через dword [bp-10]. В процессе вычисления узнаёт начало |
||
96 | первой FAT, сохраняет и его в стек для последующего обращения через |
||
1065 | Lrz | 97 | dword [bp-6]. |
3539 | clevermous | 98 | 4. (Заканчивая тему параметров в стеке) Помещает в стек dword-значение -1 |
99 | для последующего обращения через dword [bp-14] - инициализация |
||
100 | переменной, содержащей текущий сектор, находящийся в кэше FAT |
||
101 | (-1 не является валидным значением для номера сектора FAT). |
||
102 | 5. Ищет в корневой папке элемент kordldr.f32. Если не находит - переходит на |
||
103 | код обработки ошибок с сообщением о ненайденном загрузчике. |
||
104 | Замечание: на этом этапе загрузки искать можно только в корневой |
||
105 | папке и только имена, заданные в формате файловой системе FAT |
||
106 | (8+3 - 8 байт на имя, 3 байта на расширение, все буквы должны |
||
107 | быть заглавными, при необходимости имя и расширение дополняются |
||
108 | пробелами, разделяющей точки нет, завершающего нуля нет). |
||
109 | 6. Загружает первый кластер файла kordldr.f32 по адресу 0:7E00 и передаёт |
||
110 | ему управление. При этом в регистре eax оказывается абсолютный |
||
111 | номер первого сектора kordldr.f32, а в cx - число считанных секторов |
||
112 | (равное размеру кластера). |
||
1065 | Lrz | 113 | |
3539 | clevermous | 114 | Вспомогательные процедуры бутсектора. |
115 | Код обработки ошибок (err): |
||
116 | 1. Выводит строку с сообщением об ошибке. |
||
117 | 2. Выводит строку "Press any key...". |
||
118 | 3. Ждёт нажатия any key. |
||
119 | 4. Вызывает int 18h, давая шанс BIOSу попытаться загрузиться откуда-нибудь ещё. |
||
120 | 5. Для подстраховки зацикливается. |
||
1065 | Lrz | 121 | |
3539 | clevermous | 122 | Процедура чтения кластера (read_cluster): |
123 | на входе должно быть установлено: |
||
1065 | Lrz | 124 | ss:bp = 0:7C00 |
3539 | clevermous | 125 | es:bx = указатель на начало буфера, куда будут прочитаны данные |
126 | eax = номер кластера |
||
127 | на выходе: ecx = число прочитанных секторов (размер кластера), |
||
128 | es:bx указывает на конец буфера, в который были прочитаны данные, |
||
129 | eax и старшие слова других 32-битных регистров разрушаются |
||
130 | Загружает в ecx размер кластера, перекодирует номер кластера в номер сектора |
||
131 | и переходит к следующей процедуре. |
||
1065 | Lrz | 132 | |
3539 | clevermous | 133 | Процедура чтения секторов (read_sectors32 и read_sectors2): |
134 | на входе должно быть установлено: |
||
1065 | Lrz | 135 | ss:bp = 0:7C00 |
3539 | clevermous | 136 | es:bx = указатель на начало буфера, куда будут прочитаны данные |
137 | eax = стартовый сектор (относительно начала логического диска |
||
138 | для read_sectors32, относительно начала данных |
||
139 | для read_sectors2) |
||
140 | cx = число секторов (должно быть больше нуля) |
||
141 | на выходе: es:bx указывает на конец буфера, в который были прочитаны данные |
||
142 | старшие слова 32-битных регистров могут разрушиться |
||
143 | 0. Если вызывается read_sectors2, она переводит указанный ей номер сектора |
||
144 | в номер относительно начала логического диска, прибавляя номер сектора |
||
145 | начала данных, хранящийся в стеке как [bp-10]. |
||
146 | 1. Переводит стартовый сектор (отсчитываемый от начала тома) в сектор на |
||
147 | устройстве, прибавляя значение соответствующего поля из BPB. |
||
148 | 2. В цикле (шаги 3-6) читает секторы, следит за тем, чтобы на каждой итерации |
||
149 | CHS-версия: все читаемые секторы были на одной дорожке. |
||
150 | LBA-версия: число читаемых секторов не превосходило 7Fh (требование |
||
151 | спецификации EDD BIOS). |
||
152 | CHS-версия: |
||
153 | 3. Переводит абсолютный номер сектора в CHS-систему: сектор рассчитывается как |
||
154 | единица плюс остаток от деления абсолютного номера на число секторов |
||
155 | на дорожке; дорожка рассчитывается как остаток от деления частного, |
||
156 | полученного на предыдущем шаге, на число дорожек, а цилиндр - как |
||
157 | частное от этого же деления. Если число секторов для чтения больше, |
||
158 | чем число секторов до конца дорожки, уменьшает число секторов для |
||
159 | чтения. |
||
160 | 4. Формирует данные для вызова int 13h (ah=2 - чтение, al=число секторов, |
||
161 | dh=головка, (младшие 6 бит cl)=сектор, |
||
162 | (старшие 2 бита cl и весь ch)=дорожка, dl=диск, es:bx->буфер). |
||
163 | 5. Вызывает BIOS. Если BIOS рапортует об ошибке, выполняет сброс диска |
||
164 | и повторяет попытку чтения, всего делается не более трёх попыток |
||
165 | (несколько попыток нужно в случае дискеты для гарантии того, что |
||
166 | мотор раскрутился). Если все три раза происходит ошибка чтения, |
||
167 | переходит на код обработки ошибок с сообщением "Read error". |
||
168 | 6. В соответствии с числом прочитанных на текущей итерации секторов |
||
169 | корректирует текущий сектор, число оставшихся секторов и указатель на |
||
170 | буфер (в паре es:bx корректируется es). Если всё прочитано, заканчивает |
||
171 | работу, иначе возвращается на шаг 3. |
||
172 | LBA-версия: |
||
173 | 3. Если число секторов для чтения больше 7Fh, уменьшает его (для текущей |
||
174 | итерации) до 7Fh. |
||
175 | 4. Формирует в стеке пакет для int 13h (кладёт все нужные данные командами |
||
176 | push, причём в обратном порядке: стек - структура LIFO, и данные в |
||
177 | стеке хранятся в обратном порядке по отношению к тому, как их туда |
||
178 | клали). |
||
179 | 5. Вызывает BIOS. Если BIOS рапортует об ошибке, переходит на код обработки |
||
180 | ошибок с сообщением "Read error". Очищает стек от пакета, |
||
181 | сформированного на предыдущем шаге. |
||
182 | 6. В соответствии с числом прочитанных на текущей итерации секторов |
||
183 | корректирует текущий сектор, число оставшихся секторов и указатель на |
||
184 | буфер (в паре es:bx корректируется es). Если всё прочитано, заканчивает |
||
185 | работу, иначе возвращается на шаг 3. |
||
1065 | Lrz | 186 | |
3539 | clevermous | 187 | Процедура поиска элемента в папке (lookup_in_dir): |
188 | на входе должно быть установлено: |
||
1065 | Lrz | 189 | ss:bp = 0:7C00 |
3539 | clevermous | 190 | ds:si = указатель на имя файла в формате FAT (см. выше) |
191 | eax = начальный кластер папки |
||
1065 | Lrz | 192 | bx = 0 |
3539 | clevermous | 193 | на выходе: флаг CF определяет, удалось ли найти файл; если удалось, то |
194 | CF сброшен и es:di указывает на элемент папки |
||
195 | В цикле считывает кластеры папки и ищет запрошенный элемент в прочитанных |
||
196 | данных. Для чтения кластера использует уже описанную процедуру read_clusters, |
||
197 | для продвижения по цепочке кластеров - описанную далее процедуру |
||
198 | get_next_clusters. Данные читаются в область памяти, начинающуюся с адреса |
||
199 | 8000:0000, при этом первые 2000h байт из данных папки (может быть, меньше, |
||
200 | если чтение прервётся раньше) не перекрываются последующими чтениями |
||
201 | (это будет использовано позднее, в системе кэширования из kordldr.f32). |
||
202 | Выход осуществляется в любом из следующих случаев: найден запрошенный элемент; |
||
203 | кончились элементы в папке (первый байт очередного элемента нулевой); |
||
204 | кончились данные папки в соответствии с цепочкой кластеров из FAT. |
||
1065 | Lrz | 205 | |
3539 | clevermous | 206 | Процедура вывода на экран ASCIIZ-строки (out_string): |
207 | на входе: ds:si -> строка |
||
208 | В цикле, пока не достигнут завершающий ноль, вызывает функцию int 10h/ah=0Eh. |
||
1065 | Lrz | 209 | |
210 | ===================================================================== |
||
211 | |||
3539 | clevermous | 212 | Работа вспомогательного загрузчика kordldr.f32: |
213 | 1. Определяет, был ли он загружен CHS- или LBA-версией бутсектора. |
||
214 | В зависимости от этого устанавливает смещения используемых процедур |
||
215 | бутсектора. Критерий проверки: в CHS-версии по адресу err находится |
||
216 | байт 0xE8 (машинная команда call), в LBA-версии по тому же адресу |
||
217 | находится байт 0x14, а адрес процедуры err другой. |
||
218 | 2. Узнаёт размер свободной базовой памяти (т.е. свободного непрерывного куска |
||
219 | адресов памяти, начинающегося с 0) вызовом int 12h. В соответствии с |
||
220 | ним вычисляет число элементов в кэше папок. Хотя бы для одного элемента |
||
221 | место должно быть, отсюда ограничение в 592 Kb (94000h байт). |
||
222 | Замечание: этот размер не может превосходить 0A0000h байт и |
||
223 | на практике оказывается немного (на 1-2 килобайта) меньшим из-за |
||
224 | наличия дополнительной области данных BIOS "вверху" базовой памяти. |
||
225 | 3. Инициализирует кэширование папок. Бутсектор уже загрузил какую-то часть |
||
226 | данных корневой папки; копирует загруженные данные в кэш и запоминает, |
||
227 | что в кэше есть корневая папка. |
||
228 | 4. Инициализирует кэширование FAT. Бутсектор имеет дело с FAT в том и только |
||
229 | том случае, когда ему приходится загружать данные корневой папки, |
||
230 | не поместившиеся в один кластер. В этом случае в памяти присутствует |
||
231 | один сектор FAT (если было несколько обращений - последний из |
||
232 | использованных). |
||
233 | 5. Если кластер равен сектору, то бутсектор загрузил только часть файла |
||
234 | kordldr.f32, и загрузчик подгружает вторую свою часть, используя |
||
235 | значения регистров на входе в kordldr.f32. |
||
236 | 6. Загружает вторичный загрузчик kord/loader по адресу 1000:0000. Если файл не |
||
237 | найден, или оказался папкой, или оказался слишком большим, то переходит |
||
238 | на код обработки ошибок из бутсектора с сообщением |
||
1065 | Lrz | 239 | "Fatal error: cannot load the secondary loader". |
3539 | clevermous | 240 | Замечание: на этом этапе имя файла уже можно указывать вместе с путём |
241 | и в формате ASCIIZ, хотя поддержки длинных имён и неанглийских символов |
||
242 | по-прежнему нет. |
||
243 | 7. Изменяет код обработки ошибок бутсектора на переход на метку hooked_err. |
||
244 | Это нужно, чтобы последующие обращения к коду бутсектора в случае |
||
245 | ошибок чтения не выводил соответствующее сообщение с последующей |
||
246 | перезагрузкой, а рапортовал об ошибке чтения, которую могло бы |
||
247 | как-нибудь обработать ядро. |
||
248 | 8. Если загрузочный диск имеет идентификатор меньше 0x80, |
||
249 | то устанавливает al='f' ("floppy"), ah=идентификатор диска, |
||
250 | иначе al='h' ("hard"), ah=идентификатор диска-0x80 (номер диска). |
||
251 | (Говорите, дискеток с FAT32 не бывает? В чём-то Вы правы... но |
||
252 | уверены ли Вы, что нет загрузочных устройств, подобных дискетам, |
||
253 | но большего размера, и для которых BIOS-идентификатор меньше 0x80?) |
||
254 | Устанавливает bx='32' (тип файловой системы - FAT32). |
||
255 | Устанавливает si=смещение функции обратного вызова. Поскольку в этот |
||
256 | момент ds=0, то ds:si образуют полный адрес. |
||
257 | 9. Передаёт управление по адресу 1000:0000. |
||
1065 | Lrz | 258 | |
3539 | clevermous | 259 | Функция обратного вызова для вторичного загрузчика: |
260 | предоставляет возможность чтения файла. |
||
261 | Вход и выход описаны в спецификации на загрузчик. |
||
262 | 1. Сохраняет стек вызывающего кода и устанавливает свой стек: |
||
263 | ss:sp = 0:(7C00-10), bp=7C00: пара ss:bp при работе с остальным |
||
264 | кодом должна указывать на 0:7C00, а -10 берётся от того, что |
||
265 | инициализирующий код бутсектора уже поместил в стек 10 байт параметров, |
||
266 | и они должны сохраняться в неизменности. (Значение [ebp-14], |
||
267 | "текущий сектор, находящийся в кэше FAT", не используется после |
||
268 | инициализации кэширования в kordldr.f32.) |
||
269 | 2. Разбирает переданные параметры и вызывает нужную из вспомогательных |
||
270 | процедур (загрузки файла либо продолжения загрузки файла). |
||
271 | 3. Восстанавливает стек вызывающего кода и возвращает управление. |
||
1065 | Lrz | 272 | |
3539 | clevermous | 273 | Вспомогательные процедуры kordldr.f32. |
274 | Процедура получения следующего кластера в FAT (get_next_cluster): |
||
275 | 1. Вычисляет номер сектора в FAT, в котором находится запрошенный элемент. |
||
276 | (В секторе 0x200 байт, каждый вход занимает 4 байта.) |
||
277 | 2. Проверяет, есть ли сектор в кэше. Если есть, пропускает шаги 3 и 4. |
||
278 | 3. Если нет, то в кэш нужно вставить новый элемент. Если кэш ещё не заполнен, |
||
279 | выделяет очередной элемент в конце кэша. Если заполнен, удаляет |
||
280 | самый старый элемент (тот, к которому дольше всего не было обращений); |
||
281 | для того, чтобы отслеживать порядок элементов по времени последнего |
||
282 | обращения, все (выделенные) элементы кэша связаны в двусвязный список, |
||
283 | в котором первым элементом является самый старый, а ссылки вперёд |
||
284 | указывают на следующий по времени последнего обращения. |
||
285 | 4. Читает соответствующий сектор FAT с диска. |
||
286 | 5. Корректирует список: текущий обрабатываемый элемент удаляется с той позиции, |
||
287 | где он находится, и добавляется в конец. (В случае со свежедобавленными |
||
288 | в кэш элементами удаления не делается, поскольку их в списке ещё нет.) |
||
289 | 6. Считывает нужный вход в FAT, сбрасывая старшие 4 бита. |
||
290 | 7. Сравнивает прочитанное значение с пределом: если оно строго меньше |
||
291 | 0x0FFFFFF7, то оно задаёт номер следующего кластера в цепочке; |
||
292 | в противном случае цепочка закончилась. |
||
1065 | Lrz | 293 | |
3539 | clevermous | 294 | Процедура загрузки файла (load_file): |
295 | 1. Текущая рассматриваемая папка - корневая. В цикле выполняет шаги 2-4. |
||
296 | 2. Конвертирует имя текущего рассматриваемого компонента имени (компоненты |
||
297 | разделяются символом '/') в FAT-формат 8+3. Если это невозможно |
||
298 | (больше 8 символов в имени, больше 3 символов в расширении или |
||
299 | больше одной точки), возвращается с ошибкой. |
||
300 | 3. Ищет элемент с таким именем в текущей рассматриваемой папке. |
||
301 | а) Проверяет, есть ли такая папка в кэше папок. (Идентификация папок |
||
302 | осуществляется по номеру начального кластера.) Если такой папки ещё |
||
303 | нет, добавляет её в кэш; если тот переполняется, выкидывает папку, |
||
304 | к которой дольше всего не было обращений. (Для каждого элемента кэша |
||
305 | хранится метка от 0 до (размер кэша)-1, определяющая его номер при |
||
306 | сортировке по давности последнего обращения. При обращении к какому-то |
||
307 | элементу его метка становится нулевой, а те метки, которые меньше |
||
308 | старого значения, увеличиваются на единицу.) |
||
309 | б) Просматривает в поисках запрошенного имени все элементы из кэша, |
||
310 | используя процедуру из бутсектора. Если обнаруживает искомый элемент, |
||
311 | переходит к шагу 4. Если обнаруживает конец папки, возвращается из |
||
312 | процедуры с ошибкой. |
||
313 | в) В цикле считывает папку посекторно. При этом пропускает начальные |
||
314 | секторы, которые уже находятся в кэше и уже были просмотрены. Каждый |
||
315 | прочитанный сектор копирует в кэш, если там ещё остаётся место, |
||
316 | и просматривает в нём все элементы. Работает, пока не случится одно из |
||
317 | трёх событий: найден искомый элемент; кончились кластеры (судя по |
||
318 | цепочке кластеров в FAT); очередной элемент папки сигнализирует о конце |
||
319 | (первый байт нулевой). В двух последних случаях возвращается с ошибкой. |
||
320 | 4. Проверяет тип найденного элемента (файл/папка): последний элемент в |
||
321 | запрошенном имени должен быть файлом, все промежуточные - папками. |
||
322 | Если текущий компонент имени - промежуточный, продвигает текущую |
||
323 | рассматриваемую папку и возвращается к пункту 2. |
||
324 | 5. Проходит по цепочке кластеров в FAT и считывает все кластеры в указанный |
||
325 | при вызове буфер последовательными вызовами функции бутсектора; |
||
326 | при этом если несколько кластеров файла расположены на диске |
||
327 | последовательно, то их чтение объединяется в одну операцию. |
||
328 | Следит за тем, чтобы не превысить указанный при вызове процедуры |
||
329 | лимит числа секторов для чтения. |
||
1065 | Lrz | 330 | |
3539 | clevermous | 331 | Процедура продолжения загрузки файла (continue_load_file): встроена |
332 | внутрь шага 5 load_file; загружает в регистры нужные значения (ранее |
||
333 | сохранённые из load_file) и продолжает шаг 5. |