Rev 1065 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1065 | Rev 3539 | ||
---|---|---|---|
Line 22... | Line 22... | ||
22 | ; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
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 |
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. |
24 | ; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
25 | ;***************************************************************************** |
25 | ;***************************************************************************** |
Line 26... | Line 26... | ||
26 | 26 | ||
Line 27... | Line 27... | ||
27 | ×èòàé ìåæäó ñòðîê - òàì íèêîãäà íå áûâàåò îïå÷àòîê. |
27 | Читай между строк - там никогда не бывает опечаток. |
Line 28... | Line 28... | ||
28 | 28 | ||
Line 29... | Line 29... | ||
29 | Áóòñåêòîð äëÿ FAT32-òîìà íà íîñèòåëå ñ ðàçìåðîì ñåêòîðà 0x200 = 512 áàéò. |
29 | Бутсектор для FAT32-тома на носителе с размером сектора 0x200 = 512 байт. |
30 | 30 | ||
31 | ===================================================================== |
31 | ===================================================================== |
32 | 32 | ||
33 | Åñòü äâå âåðñèè â çàâèñèìîñòè îò òîãî, ïîääåðæèâàåò ëè íîñèòåëü LBA, |
33 | Есть две версии в зависимости от того, поддерживает ли носитель LBA, |
34 | âûáîð îñóùåñòâëÿåòñÿ óñòàíîâêîé êîíñòàíòû use_lba â ïåðâîé ñòðîêå èñõîäíèêà. |
34 | выбор осуществляется установкой константы use_lba в первой строке исходника. |
35 | Òðåáîâàíèÿ äëÿ ðàáîòû: |
35 | Требования для работы: |
36 | 1) Ñàì áóòñåêòîð, ïåðâàÿ êîïèÿ FAT è âñå èñïîëüçóåìûå ôàéëû |
36 | 1) Сам бутсектор, первая копия FAT и все используемые файлы |
37 | äîëæíû áûòü ÷èòàáåëüíû. (Åñëè äåëî ïðîèñõîäèò íà íîñèòåëå ñ ðàçáèåíèåì íà |
37 | должны быть читабельны. (Если дело происходит на носителе с разбиением на |
38 | ðàçäåëû è çàãðóçî÷íûé êîä â MBR äîñòàòî÷íî óìíûé, òî ÷èòàáåëüíîñòè ðåçåðâíîé |
38 | разделы и загрузочный код в MBR достаточно умный, то читабельности резервной |
Line 39... | Line 39... | ||
39 | êîïèè áóòñåêòîðà (ñåêòîð íîìåð 6 íà òîìå) äîñòàòî÷íî âìåñòî ÷èòàáåëüíîñòè |
39 | копии бутсектора (сектор номер 6 на томе) достаточно вместо читабельности |
Line 40... | Line 40... | ||
40 | ñàìîãî áóòñåêòîðà). |
40 | самого бутсектора). |
41 | 2) Ìèíèìàëüíûé ïðîöåññîð - 80386. |
41 | 2) Минимальный процессор - 80386. |
42 | 3) Â ñèñòåìå äîëæíî áûòü êàê ìèíèìóì 584K ñâîáîäíîé áàçîâîé ïàìÿòè. |
42 | 3) В системе должно быть как минимум 584K свободной базовой памяти. |
43 | 43 | ||
44 | ===================================================================== |
44 | ===================================================================== |
45 | 45 | ||
46 | Äîêóìåíòàöèÿ â òåìó (ññûëêè ïðîâåðÿëèñü íà âàëèäíîñòü 15.05.2008): |
46 | Документация в тему (ссылки проверялись на валидность 15.05.2008): |
47 | îôèöèàëüíàÿ ñïåöèôèêàöèÿ FAT: http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx |
47 | официальная спецификация FAT: http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx |
Line 48... | Line 48... | ||
48 | â ôîðìàòå PDF: http://staff.washington.edu/dittrich/misc/fatgen103.pdf |
48 | в формате PDF: http://staff.washington.edu/dittrich/misc/fatgen103.pdf |
Line 49... | Line 49... | ||
49 | ðóññêèé ïåðåâîä: http://wasm.ru/docs/11/fatgen103-rus.zip |
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 |
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 |
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 |
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 |
53 | официальная спецификация Boot BIOS: http://www.phoenix.com/NR/rdonlyres/56E38DE2-3E6F-4743-835F-B4A53726ABED/0/specsbbs101.pdf |
54 | 54 | ||
55 | ===================================================================== |
55 | ===================================================================== |
56 | 56 | ||
57 | Ñõåìà èñïîëüçóåìîé ïàìÿòè: |
57 | Схема используемой памяти: |
58 | ...-7C00 ñòåê |
58 | ...-7C00 стек |
59 | 7C00-7E00 êîä áóòñåêòîðà |
59 | 7C00-7E00 код бутсектора |
60 | 7E00-8200 âñïîìîãàòåëüíûé ôàéë çàãðóç÷èêà (kordldr.f32) |
60 | 7E00-8200 вспомогательный файл загрузчика (kordldr.f32) |
61 | 8400-8C00 èíôîðìàöèÿ î êýøå äëÿ òàáëèöû FAT: 100h âõîäîâ ïî 8 |
61 | 8400-8C00 информация о кэше для таблицы FAT: 100h входов по 8 |
62 | áàéò: 4 áàéòà (äâå ññûëêè - âïåð¸ä è íàçàä) äëÿ |
62 | байт: 4 байта (две ссылки - вперёд и назад) для |
63 | îðãàíèçàöèè L2-ñïèñêà âñåõ ïðî÷èòàííûõ ñåêòîðîâ â |
63 | организации L2-списка всех прочитанных секторов в |
64 | ïîðÿäêå âîçðàñòàíèÿ ïîñëåäíåãî âðåìåíè èñïîëüçîâàíèÿ |
64 | порядке возрастания последнего времени использования |
65 | + 4 áàéòà äëÿ íîìåðà ñåêòîðà; ïðè ïåðåïîëíåíèè êýøà |
65 | + 4 байта для номера сектора; при переполнении кэша |
66 | âûêèäûâàåòñÿ ýëåìåíò èç ãîëîâû ñïèñêà, òî åñòü òîò, |
66 | выкидывается элемент из головы списка, то есть тот, |
67 | ê êîòîðîìó äîëüøå âñåõ íå áûëî îáðàùåíèé |
67 | к которому дольше всех не было обращений |
Line 68... | Line 68... | ||
68 | 60000-80000 êýø äëÿ òàáëèöû FAT (100h ñåêòîðîâ) |
68 | 60000-80000 кэш для таблицы FAT (100h секторов) |
Line 69... | Line 69... | ||
69 | 80000-90000 òåêóùèé êëàñòåð òåêóùåé ðàññìàòðèâàåìîé ïàïêè |
69 | 80000-90000 текущий кластер текущей рассматриваемой папки |
70 | 90000-... êýø äëÿ ñîäåðæèìîãî ïàïîê (êàæäîé ïàïêå îòâîäèòñÿ |
70 | 90000-... кэш для содержимого папок (каждой папке отводится |
71 | 2000h áàéò = 100h âõîäîâ, îäíîâðåìåííî â êýøå |
71 | 2000h байт = 100h входов, одновременно в кэше |
72 | ìîæåò íàõîäèòüñÿ íå áîëåå 8 ïàïîê; |
72 | может находиться не более 8 папок; |
73 | òî÷íûé ðàçìåð îïðåäåëÿåòñÿ ðàçìåðîì äîñòóïíîé |
73 | точный размер определяется размером доступной |
74 | ôèçè÷åñêîé ïàìÿòè - êàê ïðàâèëî, íåïîñðåäñòâåííî |
74 | физической памяти - как правило, непосредственно |
75 | ïåðåä A0000 ðàçìåùàåòñÿ EBDA, Extended BIOS Data Area) |
75 | перед A0000 размещается EBDA, Extended BIOS Data Area) |
76 | 76 | ||
77 | ===================================================================== |
77 | ===================================================================== |
78 | 78 | ||
79 | Îñíîâíîé ïðîöåññ çàãðóçêè. |
79 | Основной процесс загрузки. |
80 | Òî÷êà âõîäà (start): ïîëó÷àåò óïðàâëåíèå îò BIOS ïðè çàãðóçêå, ïðè ýòîì |
80 | Точка входа (start): получает управление от BIOS при загрузке, при этом |
81 | dl ñîäåðæèò èäåíòèôèêàòîð äèñêà, ñ êîòîðîãî èä¸ò çàãðóçêà |
81 | dl содержит идентификатор диска, с которого идёт загрузка |
82 | 1. Íàñòðàèâàåò ñòåê ss:sp = 0:7C00 (ñòåê ðàñïîëàãàåòñÿ íåïîñðåäñòâåííî ïåðåä |
82 | 1. Настраивает стек ss:sp = 0:7C00 (стек располагается непосредственно перед |
83 | êîäîì), ñåãìåíò äàííûõ ds = 0, è óñòàíàâëèâàåò ss:bp íà íà÷àëî |
83 | кодом), сегмент данных ds = 0, и устанавливает ss:bp на начало |
84 | áóòñåêòîðà (â äàëüíåéøåì äàííûå áóäóò àäðåñîâàòüñÿ ÷åðåç [bp+N] - |
84 | бутсектора (в дальнейшем данные будут адресоваться через [bp+N] - |
85 | ýòî îñâîáîæäàåò ds è ýêîíîìèò íà ðàçìåðå êîäà). Ñîõðàíÿåò â ñòåêå |
85 | это освобождает ds и экономит на размере кода). Сохраняет в стеке |
86 | èäåíòèôèêàòîð çàãðóçî÷íîãî äèñêà äëÿ ïîñëåäóþùåãî îáðàùåíèÿ |
86 | идентификатор загрузочного диска для последующего обращения |
87 | ÷åðåç byte [bp-2]. |
87 | через byte [bp-2]. |
88 | 2. LBA-âåðñèÿ: ïðîâåðÿåò, ïîääåðæèâàåò ëè íîñèòåëü LBA, âûçîâîì ôóíêöèè 41h |
88 | 2. LBA-версия: проверяет, поддерживает ли носитель LBA, вызовом функции 41h |
89 | ïðåðûâàíèÿ 13h. Åñëè íåò, ïåðåõîäèò íà êîä îáðàáîòêè îøèáîê ñ |
89 | прерывания 13h. Если нет, переходит на код обработки ошибок с |
90 | ñîîáùåíèåì îá îòñóòñòâèè LBA. |
90 | сообщением об отсутствии LBA. |
91 | CHS-âåðñèÿ: îïðåäåëÿåò ãåîìåòðèþ íîñèòåëÿ âûçîâîì ôóíêöèè 8 ïðåðûâàíèÿ 13h è |
91 | CHS-версия: определяет геометрию носителя вызовом функции 8 прерывания 13h и |
92 | çàïèñûâàåò ïîëó÷åííûå äàííûå ïîâåðõ BPB. Åñëè âûçîâ çàâåðøèëñÿ îøèáêîé, |
92 | записывает полученные данные поверх BPB. Если вызов завершился ошибкой, |
93 | ïðåäïîëàãàåò óæå ñóùåñòâóþùèå äàííûå êîððåêòíûìè. |
93 | предполагает уже существующие данные корректными. |
94 | 3. Âû÷èñëÿåò íà÷àëî äàííûõ FAT-òîìà, ñîõðàíÿåò åãî â ñòåê äëÿ ïîñëåäóþùåãî |
94 | 3. Вычисляет начало данных FAT-тома, сохраняет его в стек для последующего |
95 | îáðàùåíèÿ ÷åðåç dword [bp-10].  ïðîöåññå âû÷èñëåíèÿ óçíà¸ò íà÷àëî |
95 | обращения через dword [bp-10]. В процессе вычисления узнаёт начало |
96 | ïåðâîé FAT, ñîõðàíÿåò è åãî â ñòåê äëÿ ïîñëåäóþùåãî îáðàùåíèÿ ÷åðåç |
96 | первой FAT, сохраняет и его в стек для последующего обращения через |
97 | dword [bp-6]. |
97 | dword [bp-6]. |
98 | 4. (Çàêàí÷èâàÿ òåìó ïàðàìåòðîâ â ñòåêå) Ïîìåùàåò â ñòåê dword-çíà÷åíèå -1 |
98 | 4. (Заканчивая тему параметров в стеке) Помещает в стек dword-значение -1 |
99 | äëÿ ïîñëåäóþùåãî îáðàùåíèÿ ÷åðåç dword [bp-14] - èíèöèàëèçàöèÿ |
99 | для последующего обращения через dword [bp-14] - инициализация |
100 | ïåðåìåííîé, ñîäåðæàùåé òåêóùèé ñåêòîð, íàõîäÿùèéñÿ â êýøå FAT |
100 | переменной, содержащей текущий сектор, находящийся в кэше FAT |
101 | (-1 íå ÿâëÿåòñÿ âàëèäíûì çíà÷åíèåì äëÿ íîìåðà ñåêòîðà FAT). |
101 | (-1 не является валидным значением для номера сектора FAT). |
102 | 5. Èùåò â êîðíåâîé ïàïêå ýëåìåíò kordldr.f32. Åñëè íå íàõîäèò - ïåðåõîäèò íà |
102 | 5. Ищет в корневой папке элемент kordldr.f32. Если не находит - переходит на |
103 | êîä îáðàáîòêè îøèáîê ñ ñîîáùåíèåì î íåíàéäåííîì çàãðóç÷èêå. |
103 | код обработки ошибок с сообщением о ненайденном загрузчике. |
104 | Çàìå÷àíèå: íà ýòîì ýòàïå çàãðóçêè èñêàòü ìîæíî òîëüêî â êîðíåâîé |
104 | Замечание: на этом этапе загрузки искать можно только в корневой |
105 | ïàïêå è òîëüêî èìåíà, çàäàííûå â ôîðìàòå ôàéëîâîé ñèñòåìå FAT |
105 | папке и только имена, заданные в формате файловой системе FAT |
106 | (8+3 - 8 áàéò íà èìÿ, 3 áàéòà íà ðàñøèðåíèå, âñå áóêâû äîëæíû |
106 | (8+3 - 8 байт на имя, 3 байта на расширение, все буквы должны |
107 | áûòü çàãëàâíûìè, ïðè íåîáõîäèìîñòè èìÿ è ðàñøèðåíèå äîïîëíÿþòñÿ |
107 | быть заглавными, при необходимости имя и расширение дополняются |
108 | ïðîáåëàìè, ðàçäåëÿþùåé òî÷êè íåò, çàâåðøàþùåãî íóëÿ íåò). |
108 | пробелами, разделяющей точки нет, завершающего нуля нет). |
109 | 6. Çàãðóæàåò ïåðâûé êëàñòåð ôàéëà kordldr.f32 ïî àäðåñó 0:7E00 è ïåðåäà¸ò |
109 | 6. Загружает первый кластер файла kordldr.f32 по адресу 0:7E00 и передаёт |
110 | åìó óïðàâëåíèå. Ïðè ýòîì â ðåãèñòðå eax îêàçûâàåòñÿ àáñîëþòíûé |
110 | ему управление. При этом в регистре eax оказывается абсолютный |
Line 111... | Line 111... | ||
111 | íîìåð ïåðâîãî ñåêòîðà kordldr.f32, à â cx - ÷èñëî ñ÷èòàííûõ ñåêòîðîâ |
111 | номер первого сектора kordldr.f32, а в cx - число считанных секторов |
112 | (ðàâíîå ðàçìåðó êëàñòåðà). |
112 | (равное размеру кластера). |
113 | 113 | ||
114 | Âñïîìîãàòåëüíûå ïðîöåäóðû áóòñåêòîðà. |
114 | Вспомогательные процедуры бутсектора. |
115 | Êîä îáðàáîòêè îøèáîê (err): |
115 | Код обработки ошибок (err): |
116 | 1. Âûâîäèò ñòðîêó ñ ñîîáùåíèåì îá îøèáêå. |
116 | 1. Выводит строку с сообщением об ошибке. |
117 | 2. Âûâîäèò ñòðîêó "Press any key...". |
117 | 2. Выводит строку "Press any key...". |
118 | 3. Æä¸ò íàæàòèÿ any key. |
118 | 3. Ждёт нажатия any key. |
119 | 4. Âûçûâàåò int 18h, äàâàÿ øàíñ BIOSó ïîïûòàòüñÿ çàãðóçèòüñÿ îòêóäà-íèáóäü åù¸. |
119 | 4. Вызывает int 18h, давая шанс BIOSу попытаться загрузиться откуда-нибудь ещё. |
120 | 5. Äëÿ ïîäñòðàõîâêè çàöèêëèâàåòñÿ. |
120 | 5. Для подстраховки зацикливается. |
Line 121... | Line 121... | ||
121 | 121 | ||
122 | Ïðîöåäóðà ÷òåíèÿ êëàñòåðà (read_cluster): |
122 | Процедура чтения кластера (read_cluster): |
123 | íà âõîäå äîëæíî áûòü óñòàíîâëåíî: |
123 | на входе должно быть установлено: |
124 | ss:bp = 0:7C00 |
124 | ss:bp = 0:7C00 |
125 | es:bx = óêàçàòåëü íà íà÷àëî áóôåðà, êóäà áóäóò ïðî÷èòàíû äàííûå |
125 | es:bx = указатель на начало буфера, куда будут прочитаны данные |
126 | eax = íîìåð êëàñòåðà |
126 | eax = номер кластера |
127 | íà âûõîäå: ecx = ÷èñëî ïðî÷èòàííûõ ñåêòîðîâ (ðàçìåð êëàñòåðà), |
127 | на выходе: ecx = число прочитанных секторов (размер кластера), |
128 | es:bx óêàçûâàåò íà êîíåö áóôåðà, â êîòîðûé áûëè ïðî÷èòàíû äàííûå, |
128 | es:bx указывает на конец буфера, в который были прочитаны данные, |
129 | eax è ñòàðøèå ñëîâà äðóãèõ 32-áèòíûõ ðåãèñòðîâ ðàçðóøàþòñÿ |
129 | eax и старшие слова других 32-битных регистров разрушаются |
130 | Çàãðóæàåò â ecx ðàçìåð êëàñòåðà, ïåðåêîäèðóåò íîìåð êëàñòåðà â íîìåð ñåêòîðà |
130 | Загружает в ecx размер кластера, перекодирует номер кластера в номер сектора |
131 | è ïåðåõîäèò ê ñëåäóþùåé ïðîöåäóðå. |
131 | и переходит к следующей процедуре. |
132 | 132 | ||
133 | Ïðîöåäóðà ÷òåíèÿ ñåêòîðîâ (read_sectors32 è read_sectors2): |
133 | Процедура чтения секторов (read_sectors32 и read_sectors2): |
134 | íà âõîäå äîëæíî áûòü óñòàíîâëåíî: |
134 | на входе должно быть установлено: |
135 | ss:bp = 0:7C00 |
135 | ss:bp = 0:7C00 |
136 | es:bx = óêàçàòåëü íà íà÷àëî áóôåðà, êóäà áóäóò ïðî÷èòàíû äàííûå |
136 | es:bx = указатель на начало буфера, куда будут прочитаны данные |
137 | eax = ñòàðòîâûé ñåêòîð (îòíîñèòåëüíî íà÷àëà ëîãè÷åñêîãî äèñêà |
137 | eax = стартовый сектор (относительно начала логического диска |
138 | äëÿ read_sectors32, îòíîñèòåëüíî íà÷àëà äàííûõ |
138 | для read_sectors32, относительно начала данных |
139 | äëÿ read_sectors2) |
139 | для read_sectors2) |
140 | cx = ÷èñëî ñåêòîðîâ (äîëæíî áûòü áîëüøå íóëÿ) |
140 | cx = число секторов (должно быть больше нуля) |
141 | íà âûõîäå: es:bx óêàçûâàåò íà êîíåö áóôåðà, â êîòîðûé áûëè ïðî÷èòàíû äàííûå |
141 | на выходе: es:bx указывает на конец буфера, в который были прочитаны данные |
142 | ñòàðøèå ñëîâà 32-áèòíûõ ðåãèñòðîâ ìîãóò ðàçðóøèòüñÿ |
142 | старшие слова 32-битных регистров могут разрушиться |
143 | 0. Åñëè âûçûâàåòñÿ read_sectors2, îíà ïåðåâîäèò óêàçàííûé åé íîìåð ñåêòîðà |
143 | 0. Если вызывается read_sectors2, она переводит указанный ей номер сектора |
144 | â íîìåð îòíîñèòåëüíî íà÷àëà ëîãè÷åñêîãî äèñêà, ïðèáàâëÿÿ íîìåð ñåêòîðà |
144 | в номер относительно начала логического диска, прибавляя номер сектора |
145 | íà÷àëà äàííûõ, õðàíÿùèéñÿ â ñòåêå êàê [bp-10]. |
145 | начала данных, хранящийся в стеке как [bp-10]. |
146 | 1. Ïåðåâîäèò ñòàðòîâûé ñåêòîð (îòñ÷èòûâàåìûé îò íà÷àëà òîìà) â ñåêòîð íà |
146 | 1. Переводит стартовый сектор (отсчитываемый от начала тома) в сектор на |
147 | óñòðîéñòâå, ïðèáàâëÿÿ çíà÷åíèå ñîîòâåòñòâóþùåãî ïîëÿ èç BPB. |
147 | устройстве, прибавляя значение соответствующего поля из BPB. |
148 | 2.  öèêëå (øàãè 3-6) ÷èòàåò ñåêòîðû, ñëåäèò çà òåì, ÷òîáû íà êàæäîé èòåðàöèè |
148 | 2. В цикле (шаги 3-6) читает секторы, следит за тем, чтобы на каждой итерации |
149 | CHS-âåðñèÿ: âñå ÷èòàåìûå ñåêòîðû áûëè íà îäíîé äîðîæêå. |
149 | CHS-версия: все читаемые секторы были на одной дорожке. |
150 | LBA-âåðñèÿ: ÷èñëî ÷èòàåìûõ ñåêòîðîâ íå ïðåâîñõîäèëî 7Fh (òðåáîâàíèå |
150 | LBA-версия: число читаемых секторов не превосходило 7Fh (требование |
151 | ñïåöèôèêàöèè EDD BIOS). |
151 | спецификации EDD BIOS). |
152 | CHS-âåðñèÿ: |
152 | CHS-версия: |
153 | 3. Ïåðåâîäèò àáñîëþòíûé íîìåð ñåêòîðà â CHS-ñèñòåìó: ñåêòîð ðàññ÷èòûâàåòñÿ êàê |
153 | 3. Переводит абсолютный номер сектора в CHS-систему: сектор рассчитывается как |
154 | åäèíèöà ïëþñ îñòàòîê îò äåëåíèÿ àáñîëþòíîãî íîìåðà íà ÷èñëî ñåêòîðîâ |
154 | единица плюс остаток от деления абсолютного номера на число секторов |
155 | íà äîðîæêå; äîðîæêà ðàññ÷èòûâàåòñÿ êàê îñòàòîê îò äåëåíèÿ ÷àñòíîãî, |
155 | на дорожке; дорожка рассчитывается как остаток от деления частного, |
156 | ïîëó÷åííîãî íà ïðåäûäóùåì øàãå, íà ÷èñëî äîðîæåê, à öèëèíäð - êàê |
156 | полученного на предыдущем шаге, на число дорожек, а цилиндр - как |
157 | ÷àñòíîå îò ýòîãî æå äåëåíèÿ. Åñëè ÷èñëî ñåêòîðîâ äëÿ ÷òåíèÿ áîëüøå, |
157 | частное от этого же деления. Если число секторов для чтения больше, |
158 | ÷åì ÷èñëî ñåêòîðîâ äî êîíöà äîðîæêè, óìåíüøàåò ÷èñëî ñåêòîðîâ äëÿ |
158 | чем число секторов до конца дорожки, уменьшает число секторов для |
159 | ÷òåíèÿ. |
159 | чтения. |
160 | 4. Ôîðìèðóåò äàííûå äëÿ âûçîâà int 13h (ah=2 - ÷òåíèå, al=÷èñëî ñåêòîðîâ, |
160 | 4. Формирует данные для вызова int 13h (ah=2 - чтение, al=число секторов, |
161 | dh=ãîëîâêà, (ìëàäøèå 6 áèò cl)=ñåêòîð, |
161 | dh=головка, (младшие 6 бит cl)=сектор, |
162 | (ñòàðøèå 2 áèòà cl è âåñü ch)=äîðîæêà, dl=äèñê, es:bx->áóôåð). |
162 | (старшие 2 бита cl и весь ch)=дорожка, dl=диск, es:bx->буфер). |
163 | 5. Âûçûâàåò BIOS. Åñëè BIOS ðàïîðòóåò îá îøèáêå, âûïîëíÿåò ñáðîñ äèñêà |
163 | 5. Вызывает BIOS. Если BIOS рапортует об ошибке, выполняет сброс диска |
164 | è ïîâòîðÿåò ïîïûòêó ÷òåíèÿ, âñåãî äåëàåòñÿ íå áîëåå òð¸õ ïîïûòîê |
164 | и повторяет попытку чтения, всего делается не более трёх попыток |
165 | (íåñêîëüêî ïîïûòîê íóæíî â ñëó÷àå äèñêåòû äëÿ ãàðàíòèè òîãî, ÷òî |
165 | (несколько попыток нужно в случае дискеты для гарантии того, что |
166 | ìîòîð ðàñêðóòèëñÿ). Åñëè âñå òðè ðàçà ïðîèñõîäèò îøèáêà ÷òåíèÿ, |
166 | мотор раскрутился). Если все три раза происходит ошибка чтения, |
167 | ïåðåõîäèò íà êîä îáðàáîòêè îøèáîê ñ ñîîáùåíèåì "Read error". |
167 | переходит на код обработки ошибок с сообщением "Read error". |
168 | 6.  ñîîòâåòñòâèè ñ ÷èñëîì ïðî÷èòàííûõ íà òåêóùåé èòåðàöèè ñåêòîðîâ |
168 | 6. В соответствии с числом прочитанных на текущей итерации секторов |
169 | êîððåêòèðóåò òåêóùèé ñåêòîð, ÷èñëî îñòàâøèõñÿ ñåêòîðîâ è óêàçàòåëü íà |
169 | корректирует текущий сектор, число оставшихся секторов и указатель на |
170 | áóôåð (â ïàðå es:bx êîððåêòèðóåòñÿ es). Åñëè âñ¸ ïðî÷èòàíî, çàêàí÷èâàåò |
170 | буфер (в паре es:bx корректируется es). Если всё прочитано, заканчивает |
171 | ðàáîòó, èíà÷å âîçâðàùàåòñÿ íà øàã 3. |
171 | работу, иначе возвращается на шаг 3. |
172 | LBA-âåðñèÿ: |
172 | LBA-версия: |
173 | 3. Åñëè ÷èñëî ñåêòîðîâ äëÿ ÷òåíèÿ áîëüøå 7Fh, óìåíüøàåò åãî (äëÿ òåêóùåé |
173 | 3. Если число секторов для чтения больше 7Fh, уменьшает его (для текущей |
Line 174... | Line 174... | ||
174 | èòåðàöèè) äî 7Fh. |
174 | итерации) до 7Fh. |
175 | 4. Ôîðìèðóåò â ñòåêå ïàêåò äëÿ int 13h (êëàä¸ò âñå íóæíûå äàííûå êîìàíäàìè |
175 | 4. Формирует в стеке пакет для int 13h (кладёт все нужные данные командами |
176 | push, ïðè÷¸ì â îáðàòíîì ïîðÿäêå: ñòåê - ñòðóêòóðà LIFO, è äàííûå â |
176 | push, причём в обратном порядке: стек - структура LIFO, и данные в |
177 | ñòåêå õðàíÿòñÿ â îáðàòíîì ïîðÿäêå ïî îòíîøåíèþ ê òîìó, êàê èõ òóäà |
177 | стеке хранятся в обратном порядке по отношению к тому, как их туда |
178 | êëàëè). |
178 | клали). |
179 | 5. Âûçûâàåò BIOS. Åñëè BIOS ðàïîðòóåò îá îøèáêå, ïåðåõîäèò íà êîä îáðàáîòêè |
179 | 5. Вызывает BIOS. Если BIOS рапортует об ошибке, переходит на код обработки |
180 | îøèáîê ñ ñîîáùåíèåì "Read error". Î÷èùàåò ñòåê îò ïàêåòà, |
180 | ошибок с сообщением "Read error". Очищает стек от пакета, |
181 | ñôîðìèðîâàííîãî íà ïðåäûäóùåì øàãå. |
181 | сформированного на предыдущем шаге. |
182 | 6.  ñîîòâåòñòâèè ñ ÷èñëîì ïðî÷èòàííûõ íà òåêóùåé èòåðàöèè ñåêòîðîâ |
182 | 6. В соответствии с числом прочитанных на текущей итерации секторов |
183 | êîððåêòèðóåò òåêóùèé ñåêòîð, ÷èñëî îñòàâøèõñÿ ñåêòîðîâ è óêàçàòåëü íà |
183 | корректирует текущий сектор, число оставшихся секторов и указатель на |
184 | áóôåð (â ïàðå es:bx êîððåêòèðóåòñÿ es). Åñëè âñ¸ ïðî÷èòàíî, çàêàí÷èâàåò |
184 | буфер (в паре es:bx корректируется es). Если всё прочитано, заканчивает |
185 | ðàáîòó, èíà÷å âîçâðàùàåòñÿ íà øàã 3. |
185 | работу, иначе возвращается на шаг 3. |
186 | 186 | ||
187 | Ïðîöåäóðà ïîèñêà ýëåìåíòà â ïàïêå (lookup_in_dir): |
187 | Процедура поиска элемента в папке (lookup_in_dir): |
188 | íà âõîäå äîëæíî áûòü óñòàíîâëåíî: |
188 | на входе должно быть установлено: |
189 | ss:bp = 0:7C00 |
189 | ss:bp = 0:7C00 |
190 | ds:si = óêàçàòåëü íà èìÿ ôàéëà â ôîðìàòå FAT (ñì. âûøå) |
190 | ds:si = указатель на имя файла в формате FAT (см. выше) |
191 | eax = íà÷àëüíûé êëàñòåð ïàïêè |
191 | eax = начальный кластер папки |
192 | bx = 0 |
192 | bx = 0 |
193 | íà âûõîäå: ôëàã CF îïðåäåëÿåò, óäàëîñü ëè íàéòè ôàéë; åñëè óäàëîñü, òî |
193 | на выходе: флаг CF определяет, удалось ли найти файл; если удалось, то |
194 | CF ñáðîøåí è es:di óêàçûâàåò íà ýëåìåíò ïàïêè |
194 | CF сброшен и es:di указывает на элемент папки |
195 |  öèêëå ñ÷èòûâàåò êëàñòåðû ïàïêè è èùåò çàïðîøåííûé ýëåìåíò â ïðî÷èòàííûõ |
195 | В цикле считывает кластеры папки и ищет запрошенный элемент в прочитанных |
Line 196... | Line 196... | ||
196 | äàííûõ. Äëÿ ÷òåíèÿ êëàñòåðà èñïîëüçóåò óæå îïèñàííóþ ïðîöåäóðó read_clusters, |
196 | данных. Для чтения кластера использует уже описанную процедуру read_clusters, |
Line 197... | Line 197... | ||
197 | äëÿ ïðîäâèæåíèÿ ïî öåïî÷êå êëàñòåðîâ - îïèñàííóþ äàëåå ïðîöåäóðó |
197 | для продвижения по цепочке кластеров - описанную далее процедуру |
198 | get_next_clusters. Äàííûå ÷èòàþòñÿ â îáëàñòü ïàìÿòè, íà÷èíàþùóþñÿ ñ àäðåñà |
198 | get_next_clusters. Данные читаются в область памяти, начинающуюся с адреса |
199 | 8000:0000, ïðè ýòîì ïåðâûå 2000h áàéò èç äàííûõ ïàïêè (ìîæåò áûòü, ìåíüøå, |
199 | 8000:0000, при этом первые 2000h байт из данных папки (может быть, меньше, |
200 | åñëè ÷òåíèå ïðåðâ¸òñÿ ðàíüøå) íå ïåðåêðûâàþòñÿ ïîñëåäóþùèìè ÷òåíèÿìè |
200 | если чтение прервётся раньше) не перекрываются последующими чтениями |
201 | (ýòî áóäåò èñïîëüçîâàíî ïîçäíåå, â ñèñòåìå êýøèðîâàíèÿ èç kordldr.f32). |
201 | (это будет использовано позднее, в системе кэширования из kordldr.f32). |
202 | Âûõîä îñóùåñòâëÿåòñÿ â ëþáîì èç ñëåäóþùèõ ñëó÷àåâ: íàéäåí çàïðîøåííûé ýëåìåíò; |
202 | Выход осуществляется в любом из следующих случаев: найден запрошенный элемент; |
203 | êîí÷èëèñü ýëåìåíòû â ïàïêå (ïåðâûé áàéò î÷åðåäíîãî ýëåìåíòà íóëåâîé); |
203 | кончились элементы в папке (первый байт очередного элемента нулевой); |
204 | êîí÷èëèñü äàííûå ïàïêè â ñîîòâåòñòâèè ñ öåïî÷êîé êëàñòåðîâ èç FAT. |
204 | кончились данные папки в соответствии с цепочкой кластеров из FAT. |
205 | 205 | ||
206 | Ïðîöåäóðà âûâîäà íà ýêðàí ASCIIZ-ñòðîêè (out_string): |
206 | Процедура вывода на экран ASCIIZ-строки (out_string): |
207 | íà âõîäå: ds:si -> ñòðîêà |
207 | на входе: ds:si -> строка |
208 | Â öèêëå, ïîêà íå äîñòèãíóò çàâåðøàþùèé íîëü, âûçûâàåò ôóíêöèþ int 10h/ah=0Eh. |
208 | В цикле, пока не достигнут завершающий ноль, вызывает функцию int 10h/ah=0Eh. |
209 | 209 | ||
210 | ===================================================================== |
210 | ===================================================================== |
211 | 211 | ||
212 | Ðàáîòà âñïîìîãàòåëüíîãî çàãðóç÷èêà kordldr.f32: |
212 | Работа вспомогательного загрузчика kordldr.f32: |
213 | 1. Îïðåäåëÿåò, áûë ëè îí çàãðóæåí CHS- èëè LBA-âåðñèåé áóòñåêòîðà. |
213 | 1. Определяет, был ли он загружен CHS- или LBA-версией бутсектора. |
214 | Â çàâèñèìîñòè îò ýòîãî óñòàíàâëèâàåò ñìåùåíèÿ èñïîëüçóåìûõ ïðîöåäóð |
214 | В зависимости от этого устанавливает смещения используемых процедур |
215 | áóòñåêòîðà. Êðèòåðèé ïðîâåðêè: â CHS-âåðñèè ïî àäðåñó err íàõîäèòñÿ |
215 | бутсектора. Критерий проверки: в CHS-версии по адресу err находится |
216 | áàéò 0xE8 (ìàøèííàÿ êîìàíäà call), â LBA-âåðñèè ïî òîìó æå àäðåñó |
216 | байт 0xE8 (машинная команда call), в LBA-версии по тому же адресу |
217 | íàõîäèòñÿ áàéò 0x14, à àäðåñ ïðîöåäóðû err äðóãîé. |
217 | находится байт 0x14, а адрес процедуры err другой. |
218 | 2. Óçíà¸ò ðàçìåð ñâîáîäíîé áàçîâîé ïàìÿòè (ò.å. ñâîáîäíîãî íåïðåðûâíîãî êóñêà |
218 | 2. Узнаёт размер свободной базовой памяти (т.е. свободного непрерывного куска |
219 | àäðåñîâ ïàìÿòè, íà÷èíàþùåãîñÿ ñ 0) âûçîâîì int 12h.  ñîîòâåòñòâèè ñ |
219 | адресов памяти, начинающегося с 0) вызовом int 12h. В соответствии с |
220 | íèì âû÷èñëÿåò ÷èñëî ýëåìåíòîâ â êýøå ïàïîê. Õîòÿ áû äëÿ îäíîãî ýëåìåíòà |
220 | ним вычисляет число элементов в кэше папок. Хотя бы для одного элемента |
221 | ìåñòî äîëæíî áûòü, îòñþäà îãðàíè÷åíèå â 592 Kb (94000h áàéò). |
221 | место должно быть, отсюда ограничение в 592 Kb (94000h байт). |
222 | Çàìå÷àíèå: ýòîò ðàçìåð íå ìîæåò ïðåâîñõîäèòü 0A0000h áàéò è |
222 | Замечание: этот размер не может превосходить 0A0000h байт и |
223 | íà ïðàêòèêå îêàçûâàåòñÿ íåìíîãî (íà 1-2 êèëîáàéòà) ìåíüøèì èç-çà |
223 | на практике оказывается немного (на 1-2 килобайта) меньшим из-за |
224 | íàëè÷èÿ äîïîëíèòåëüíîé îáëàñòè äàííûõ BIOS "ââåðõó" áàçîâîé ïàìÿòè. |
224 | наличия дополнительной области данных BIOS "вверху" базовой памяти. |
225 | 3. Èíèöèàëèçèðóåò êýøèðîâàíèå ïàïîê. Áóòñåêòîð óæå çàãðóçèë êàêóþ-òî ÷àñòü |
225 | 3. Инициализирует кэширование папок. Бутсектор уже загрузил какую-то часть |
226 | äàííûõ êîðíåâîé ïàïêè; êîïèðóåò çàãðóæåííûå äàííûå â êýø è çàïîìèíàåò, |
226 | данных корневой папки; копирует загруженные данные в кэш и запоминает, |
227 | ÷òî â êýøå åñòü êîðíåâàÿ ïàïêà. |
227 | что в кэше есть корневая папка. |
228 | 4. Èíèöèàëèçèðóåò êýøèðîâàíèå FAT. Áóòñåêòîð èìååò äåëî ñ FAT â òîì è òîëüêî |
228 | 4. Инициализирует кэширование FAT. Бутсектор имеет дело с FAT в том и только |
229 | òîì ñëó÷àå, êîãäà åìó ïðèõîäèòñÿ çàãðóæàòü äàííûå êîðíåâîé ïàïêè, |
229 | том случае, когда ему приходится загружать данные корневой папки, |
230 | íå ïîìåñòèâøèåñÿ â îäèí êëàñòåð.  ýòîì ñëó÷àå â ïàìÿòè ïðèñóòñòâóåò |
230 | не поместившиеся в один кластер. В этом случае в памяти присутствует |
231 | îäèí ñåêòîð FAT (åñëè áûëî íåñêîëüêî îáðàùåíèé - ïîñëåäíèé èç |
231 | один сектор FAT (если было несколько обращений - последний из |
232 | èñïîëüçîâàííûõ). |
232 | использованных). |
233 | 5. Åñëè êëàñòåð ðàâåí ñåêòîðó, òî áóòñåêòîð çàãðóçèë òîëüêî ÷àñòü ôàéëà |
233 | 5. Если кластер равен сектору, то бутсектор загрузил только часть файла |
234 | kordldr.f32, è çàãðóç÷èê ïîäãðóæàåò âòîðóþ ñâîþ ÷àñòü, èñïîëüçóÿ |
234 | kordldr.f32, и загрузчик подгружает вторую свою часть, используя |
235 | çíà÷åíèÿ ðåãèñòðîâ íà âõîäå â kordldr.f32. |
235 | значения регистров на входе в kordldr.f32. |
236 | 6. Çàãðóæàåò âòîðè÷íûé çàãðóç÷èê kord/loader ïî àäðåñó 1000:0000. Åñëè ôàéë íå |
236 | 6. Загружает вторичный загрузчик kord/loader по адресу 1000:0000. Если файл не |
237 | íàéäåí, èëè îêàçàëñÿ ïàïêîé, èëè îêàçàëñÿ ñëèøêîì áîëüøèì, òî ïåðåõîäèò |
237 | найден, или оказался папкой, или оказался слишком большим, то переходит |
238 | íà êîä îáðàáîòêè îøèáîê èç áóòñåêòîðà ñ ñîîáùåíèåì |
238 | на код обработки ошибок из бутсектора с сообщением |
239 | "Fatal error: cannot load the secondary loader". |
239 | "Fatal error: cannot load the secondary loader". |
240 | Çàìå÷àíèå: íà ýòîì ýòàïå èìÿ ôàéëà óæå ìîæíî óêàçûâàòü âìåñòå ñ ïóò¸ì |
240 | Замечание: на этом этапе имя файла уже можно указывать вместе с путём |
241 | è â ôîðìàòå ASCIIZ, õîòÿ ïîääåðæêè äëèííûõ èì¸í è íåàíãëèéñêèõ ñèìâîëîâ |
241 | и в формате ASCIIZ, хотя поддержки длинных имён и неанглийских символов |
242 | ïî-ïðåæíåìó íåò. |
242 | по-прежнему нет. |
243 | 7. Èçìåíÿåò êîä îáðàáîòêè îøèáîê áóòñåêòîðà íà ïåðåõîä íà ìåòêó hooked_err. |
243 | 7. Изменяет код обработки ошибок бутсектора на переход на метку hooked_err. |
244 | Ýòî íóæíî, ÷òîáû ïîñëåäóþùèå îáðàùåíèÿ ê êîäó áóòñåêòîðà â ñëó÷àå |
244 | Это нужно, чтобы последующие обращения к коду бутсектора в случае |
245 | îøèáîê ÷òåíèÿ íå âûâîäèë ñîîòâåòñòâóþùåå ñîîáùåíèå ñ ïîñëåäóþùåé |
245 | ошибок чтения не выводил соответствующее сообщение с последующей |
246 | ïåðåçàãðóçêîé, à ðàïîðòîâàë îá îøèáêå ÷òåíèÿ, êîòîðóþ ìîãëî áû |
246 | перезагрузкой, а рапортовал об ошибке чтения, которую могло бы |
247 | êàê-íèáóäü îáðàáîòàòü ÿäðî. |
247 | как-нибудь обработать ядро. |
248 | 8. Åñëè çàãðóçî÷íûé äèñê èìååò èäåíòèôèêàòîð ìåíüøå 0x80, |
248 | 8. Если загрузочный диск имеет идентификатор меньше 0x80, |
249 | òî óñòàíàâëèâàåò al='f' ("floppy"), ah=èäåíòèôèêàòîð äèñêà, |
249 | то устанавливает al='f' ("floppy"), ah=идентификатор диска, |
250 | èíà÷å al='h' ("hard"), ah=èäåíòèôèêàòîð äèñêà-0x80 (íîìåð äèñêà). |
250 | иначе al='h' ("hard"), ah=идентификатор диска-0x80 (номер диска). |
251 | (Ãîâîðèòå, äèñêåòîê ñ FAT32 íå áûâàåò?  ÷¸ì-òî Âû ïðàâû... íî |
251 | (Говорите, дискеток с FAT32 не бывает? В чём-то Вы правы... но |
252 | óâåðåíû ëè Âû, ÷òî íåò çàãðóçî÷íûõ óñòðîéñòâ, ïîäîáíûõ äèñêåòàì, |
252 | уверены ли Вы, что нет загрузочных устройств, подобных дискетам, |
253 | íî áîëüøåãî ðàçìåðà, è äëÿ êîòîðûõ BIOS-èäåíòèôèêàòîð ìåíüøå 0x80?) |
253 | но большего размера, и для которых BIOS-идентификатор меньше 0x80?) |
254 | Óñòàíàâëèâàåò bx='32' (òèï ôàéëîâîé ñèñòåìû - FAT32). |
254 | Устанавливает bx='32' (тип файловой системы - FAT32). |
255 | Óñòàíàâëèâàåò si=ñìåùåíèå ôóíêöèè îáðàòíîãî âûçîâà. Ïîñêîëüêó â ýòîò |
255 | Устанавливает si=смещение функции обратного вызова. Поскольку в этот |
256 | ìîìåíò ds=0, òî ds:si îáðàçóþò ïîëíûé àäðåñ. |
256 | момент ds=0, то ds:si образуют полный адрес. |
257 | 9. Ïåðåäà¸ò óïðàâëåíèå ïî àäðåñó 1000:0000. |
257 | 9. Передаёт управление по адресу 1000:0000. |
258 | 258 | ||
259 | Ôóíêöèÿ îáðàòíîãî âûçîâà äëÿ âòîðè÷íîãî çàãðóç÷èêà: |
259 | Функция обратного вызова для вторичного загрузчика: |
260 | ïðåäîñòàâëÿåò âîçìîæíîñòü ÷òåíèÿ ôàéëà. |
260 | предоставляет возможность чтения файла. |
261 | Âõîä è âûõîä îïèñàíû â ñïåöèôèêàöèè íà çàãðóç÷èê. |
261 | Вход и выход описаны в спецификации на загрузчик. |
262 | 1. Ñîõðàíÿåò ñòåê âûçûâàþùåãî êîäà è óñòàíàâëèâàåò ñâîé ñòåê: |
262 | 1. Сохраняет стек вызывающего кода и устанавливает свой стек: |
263 | ss:sp = 0:(7C00-10), bp=7C00: ïàðà ss:bp ïðè ðàáîòå ñ îñòàëüíûì |
263 | ss:sp = 0:(7C00-10), bp=7C00: пара ss:bp при работе с остальным |
264 | êîäîì äîëæíà óêàçûâàòü íà 0:7C00, à -10 áåð¸òñÿ îò òîãî, ÷òî |
264 | кодом должна указывать на 0:7C00, а -10 берётся от того, что |
265 | èíèöèàëèçèðóþùèé êîä áóòñåêòîðà óæå ïîìåñòèë â ñòåê 10 áàéò ïàðàìåòðîâ, |
265 | инициализирующий код бутсектора уже поместил в стек 10 байт параметров, |
266 | è îíè äîëæíû ñîõðàíÿòüñÿ â íåèçìåííîñòè. (Çíà÷åíèå [ebp-14], |
266 | и они должны сохраняться в неизменности. (Значение [ebp-14], |
267 | "òåêóùèé ñåêòîð, íàõîäÿùèéñÿ â êýøå FAT", íå èñïîëüçóåòñÿ ïîñëå |
267 | "текущий сектор, находящийся в кэше FAT", не используется после |
268 | èíèöèàëèçàöèè êýøèðîâàíèÿ â kordldr.f32.) |
268 | инициализации кэширования в kordldr.f32.) |
269 | 2. Ðàçáèðàåò ïåðåäàííûå ïàðàìåòðû è âûçûâàåò íóæíóþ èç âñïîìîãàòåëüíûõ |
269 | 2. Разбирает переданные параметры и вызывает нужную из вспомогательных |
270 | ïðîöåäóð (çàãðóçêè ôàéëà ëèáî ïðîäîëæåíèÿ çàãðóçêè ôàéëà). |
270 | процедур (загрузки файла либо продолжения загрузки файла). |
271 | 3. Âîññòàíàâëèâàåò ñòåê âûçûâàþùåãî êîäà è âîçâðàùàåò óïðàâëåíèå. |
271 | 3. Восстанавливает стек вызывающего кода и возвращает управление. |
272 | 272 | ||
273 | Âñïîìîãàòåëüíûå ïðîöåäóðû kordldr.f32. |
273 | Вспомогательные процедуры kordldr.f32. |
274 | Ïðîöåäóðà ïîëó÷åíèÿ ñëåäóþùåãî êëàñòåðà â FAT (get_next_cluster): |
274 | Процедура получения следующего кластера в FAT (get_next_cluster): |
275 | 1. Âû÷èñëÿåò íîìåð ñåêòîðà â FAT, â êîòîðîì íàõîäèòñÿ çàïðîøåííûé ýëåìåíò. |
275 | 1. Вычисляет номер сектора в FAT, в котором находится запрошенный элемент. |
276 | (Â ñåêòîðå 0x200 áàéò, êàæäûé âõîä çàíèìàåò 4 áàéòà.) |
276 | (В секторе 0x200 байт, каждый вход занимает 4 байта.) |
277 | 2. Ïðîâåðÿåò, åñòü ëè ñåêòîð â êýøå. Åñëè åñòü, ïðîïóñêàåò øàãè 3 è 4. |
277 | 2. Проверяет, есть ли сектор в кэше. Если есть, пропускает шаги 3 и 4. |
278 | 3. Åñëè íåò, òî â êýø íóæíî âñòàâèòü íîâûé ýëåìåíò. Åñëè êýø åù¸ íå çàïîëíåí, |
278 | 3. Если нет, то в кэш нужно вставить новый элемент. Если кэш ещё не заполнен, |
279 | âûäåëÿåò î÷åðåäíîé ýëåìåíò â êîíöå êýøà. Åñëè çàïîëíåí, óäàëÿåò |
279 | выделяет очередной элемент в конце кэша. Если заполнен, удаляет |
280 | ñàìûé ñòàðûé ýëåìåíò (òîò, ê êîòîðîìó äîëüøå âñåãî íå áûëî îáðàùåíèé); |
280 | самый старый элемент (тот, к которому дольше всего не было обращений); |
281 | äëÿ òîãî, ÷òîáû îòñëåæèâàòü ïîðÿäîê ýëåìåíòîâ ïî âðåìåíè ïîñëåäíåãî |
281 | для того, чтобы отслеживать порядок элементов по времени последнего |
282 | îáðàùåíèÿ, âñå (âûäåëåííûå) ýëåìåíòû êýøà ñâÿçàíû â äâóñâÿçíûé ñïèñîê, |
282 | обращения, все (выделенные) элементы кэша связаны в двусвязный список, |
283 | â êîòîðîì ïåðâûì ýëåìåíòîì ÿâëÿåòñÿ ñàìûé ñòàðûé, à ññûëêè âïåð¸ä |
283 | в котором первым элементом является самый старый, а ссылки вперёд |
284 | óêàçûâàþò íà ñëåäóþùèé ïî âðåìåíè ïîñëåäíåãî îáðàùåíèÿ. |
284 | указывают на следующий по времени последнего обращения. |
285 | 4. ×èòàåò ñîîòâåòñòâóþùèé ñåêòîð FAT ñ äèñêà. |
285 | 4. Читает соответствующий сектор FAT с диска. |
286 | 5. Êîððåêòèðóåò ñïèñîê: òåêóùèé îáðàáàòûâàåìûé ýëåìåíò óäàëÿåòñÿ ñ òîé ïîçèöèè, |
286 | 5. Корректирует список: текущий обрабатываемый элемент удаляется с той позиции, |
287 | ãäå îí íàõîäèòñÿ, è äîáàâëÿåòñÿ â êîíåö. ( ñëó÷àå ñî ñâåæåäîáàâëåííûìè |
287 | где он находится, и добавляется в конец. (В случае со свежедобавленными |
288 | â êýø ýëåìåíòàìè óäàëåíèÿ íå äåëàåòñÿ, ïîñêîëüêó èõ â ñïèñêå åù¸ íåò.) |
288 | в кэш элементами удаления не делается, поскольку их в списке ещё нет.) |
289 | 6. Ñ÷èòûâàåò íóæíûé âõîä â FAT, ñáðàñûâàÿ ñòàðøèå 4 áèòà. |
289 | 6. Считывает нужный вход в FAT, сбрасывая старшие 4 бита. |
290 | 7. Ñðàâíèâàåò ïðî÷èòàííîå çíà÷åíèå ñ ïðåäåëîì: åñëè îíî ñòðîãî ìåíüøå |
290 | 7. Сравнивает прочитанное значение с пределом: если оно строго меньше |
291 | 0x0FFFFFF7, òî îíî çàäà¸ò íîìåð ñëåäóþùåãî êëàñòåðà â öåïî÷êå; |
291 | 0x0FFFFFF7, то оно задаёт номер следующего кластера в цепочке; |
292 | â ïðîòèâíîì ñëó÷àå öåïî÷êà çàêîí÷èëàñü. |
292 | в противном случае цепочка закончилась. |
293 | 293 | ||
294 | Ïðîöåäóðà çàãðóçêè ôàéëà (load_file): |
294 | Процедура загрузки файла (load_file): |
295 | 1. Òåêóùàÿ ðàññìàòðèâàåìàÿ ïàïêà - êîðíåâàÿ. Â öèêëå âûïîëíÿåò øàãè 2-4. |
295 | 1. Текущая рассматриваемая папка - корневая. В цикле выполняет шаги 2-4. |
296 | 2. Êîíâåðòèðóåò èìÿ òåêóùåãî ðàññìàòðèâàåìîãî êîìïîíåíòà èìåíè (êîìïîíåíòû |
296 | 2. Конвертирует имя текущего рассматриваемого компонента имени (компоненты |
297 | ðàçäåëÿþòñÿ ñèìâîëîì '/') â FAT-ôîðìàò 8+3. Åñëè ýòî íåâîçìîæíî |
297 | разделяются символом '/') в FAT-формат 8+3. Если это невозможно |
298 | (áîëüøå 8 ñèìâîëîâ â èìåíè, áîëüøå 3 ñèìâîëîâ â ðàñøèðåíèè èëè |
298 | (больше 8 символов в имени, больше 3 символов в расширении или |
299 | áîëüøå îäíîé òî÷êè), âîçâðàùàåòñÿ ñ îøèáêîé. |
299 | больше одной точки), возвращается с ошибкой. |
300 | 3. Èùåò ýëåìåíò ñ òàêèì èìåíåì â òåêóùåé ðàññìàòðèâàåìîé ïàïêå. |
300 | 3. Ищет элемент с таким именем в текущей рассматриваемой папке. |
301 | à) Ïðîâåðÿåò, åñòü ëè òàêàÿ ïàïêà â êýøå ïàïîê. (Èäåíòèôèêàöèÿ ïàïîê |
301 | а) Проверяет, есть ли такая папка в кэше папок. (Идентификация папок |
302 | îñóùåñòâëÿåòñÿ ïî íîìåðó íà÷àëüíîãî êëàñòåðà.) Åñëè òàêîé ïàïêè åù¸ |
302 | осуществляется по номеру начального кластера.) Если такой папки ещё |
303 | íåò, äîáàâëÿåò å¸ â êýø; åñëè òîò ïåðåïîëíÿåòñÿ, âûêèäûâàåò ïàïêó, |
303 | нет, добавляет её в кэш; если тот переполняется, выкидывает папку, |
304 | ê êîòîðîé äîëüøå âñåãî íå áûëî îáðàùåíèé. (Äëÿ êàæäîãî ýëåìåíòà êýøà |
304 | к которой дольше всего не было обращений. (Для каждого элемента кэша |
305 | õðàíèòñÿ ìåòêà îò 0 äî (ðàçìåð êýøà)-1, îïðåäåëÿþùàÿ åãî íîìåð ïðè |
305 | хранится метка от 0 до (размер кэша)-1, определяющая его номер при |
306 | ñîðòèðîâêå ïî äàâíîñòè ïîñëåäíåãî îáðàùåíèÿ. Ïðè îáðàùåíèè ê êàêîìó-òî |
306 | сортировке по давности последнего обращения. При обращении к какому-то |
307 | ýëåìåíòó åãî ìåòêà ñòàíîâèòñÿ íóëåâîé, à òå ìåòêè, êîòîðûå ìåíüøå |
307 | элементу его метка становится нулевой, а те метки, которые меньше |
308 | ñòàðîãî çíà÷åíèÿ, óâåëè÷èâàþòñÿ íà åäèíèöó.) |
308 | старого значения, увеличиваются на единицу.) |
309 | á) Ïðîñìàòðèâàåò â ïîèñêàõ çàïðîøåííîãî èìåíè âñå ýëåìåíòû èç êýøà, |
309 | б) Просматривает в поисках запрошенного имени все элементы из кэша, |
310 | èñïîëüçóÿ ïðîöåäóðó èç áóòñåêòîðà. Åñëè îáíàðóæèâàåò èñêîìûé ýëåìåíò, |
310 | используя процедуру из бутсектора. Если обнаруживает искомый элемент, |
311 | ïåðåõîäèò ê øàãó 4. Åñëè îáíàðóæèâàåò êîíåö ïàïêè, âîçâðàùàåòñÿ èç |
311 | переходит к шагу 4. Если обнаруживает конец папки, возвращается из |
312 | ïðîöåäóðû ñ îøèáêîé. |
312 | процедуры с ошибкой. |
313 | â)  öèêëå ñ÷èòûâàåò ïàïêó ïîñåêòîðíî. Ïðè ýòîì ïðîïóñêàåò íà÷àëüíûå |
313 | в) В цикле считывает папку посекторно. При этом пропускает начальные |
314 | ñåêòîðû, êîòîðûå óæå íàõîäÿòñÿ â êýøå è óæå áûëè ïðîñìîòðåíû. Êàæäûé |
314 | секторы, которые уже находятся в кэше и уже были просмотрены. Каждый |
315 | ïðî÷èòàííûé ñåêòîð êîïèðóåò â êýø, åñëè òàì åù¸ îñòà¸òñÿ ìåñòî, |
315 | прочитанный сектор копирует в кэш, если там ещё остаётся место, |
316 | è ïðîñìàòðèâàåò â í¸ì âñå ýëåìåíòû. Ðàáîòàåò, ïîêà íå ñëó÷èòñÿ îäíî èç |
316 | и просматривает в нём все элементы. Работает, пока не случится одно из |
317 | òð¸õ ñîáûòèé: íàéäåí èñêîìûé ýëåìåíò; êîí÷èëèñü êëàñòåðû (ñóäÿ ïî |
317 | трёх событий: найден искомый элемент; кончились кластеры (судя по |
318 | öåïî÷êå êëàñòåðîâ â FAT); î÷åðåäíîé ýëåìåíò ïàïêè ñèãíàëèçèðóåò î êîíöå |
318 | цепочке кластеров в FAT); очередной элемент папки сигнализирует о конце |