Rev 1962 | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1962 | 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 | ||
27 | Âñòðå÷àþòñÿ âèðóñ è FAT. |
27 | Встречаются вирус и FAT. |
28 | - Ïðèâåò, òû êòî? |
28 | - Привет, ты кто? |
29 | - ß? Âèðóñ. |
29 | - Я? Вирус. |
Line 30... | Line 30... | ||
30 | - A ÿ AFT, òî åñòü TAF, òî åñòü FTA, ÷åðò, ñîâñåì çàïóòàëñÿ... |
30 | - A я AFT, то есть TAF, то есть FTA, черт, совсем запутался... |
Line 31... | Line 31... | ||
31 | 31 | ||
Line 32... | Line 32... | ||
32 | Áóòñåêòîð äëÿ FAT12/FAT16-òîìà íà íîñèòåëå ñ ðàçìåðîì ñåêòîðà 0x200 = 512 áàéò. |
32 | Бутсектор для FAT12/FAT16-тома на носителе с размером сектора 0x200 = 512 байт. |
33 | 33 | ||
34 | ===================================================================== |
34 | ===================================================================== |
35 | 35 | ||
36 | Åñòü äâå âåðñèè â çàâèñèìîñòè îò òîãî, ïîääåðæèâàåò ëè íîñèòåëü LBA, |
36 | Есть две версии в зависимости от того, поддерживает ли носитель LBA, |
37 | âûáîð îñóùåñòâëÿåòñÿ óñòàíîâêîé êîíñòàíòû use_lba â ïåðâîé ñòðîêå èñõîäíèêà. |
37 | выбор осуществляется установкой константы use_lba в первой строке исходника. |
38 | Òðåáîâàíèÿ äëÿ ðàáîòû: |
38 | Требования для работы: |
Line 39... | Line 39... | ||
39 | 1) Ñàì áóòñåêòîð, ïåðâàÿ êîïèÿ FAT è âñå èñïîëüçóåìûå ôàéëû |
39 | 1) Сам бутсектор, первая копия FAT и все используемые файлы |
Line 40... | Line 40... | ||
40 | äîëæíû áûòü ÷èòàáåëüíû. |
40 | должны быть читабельны. |
41 | 2) Ìèíèìàëüíûé ïðîöåññîð - 80186. |
41 | 2) Минимальный процессор - 80186. |
42 | 3) Â ñèñòåìå äîëæíî áûòü êàê ìèíèìóì 592K ñâîáîäíîé áàçîâîé ïàìÿòè. |
42 | 3) В системе должно быть как минимум 592K свободной базовой памяти. |
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 | Ìàêñèìàëüíîå êîëè÷åñòâî êëàñòåðîâ íà FAT12-òîìå - 0xFF4 = 4084; êàæäûé êëàñòåð |
57 | Максимальное количество кластеров на FAT12-томе - 0xFF4 = 4084; каждый кластер |
58 | çàíèìàåò 12 áèò â òàáëèöå FAT, òàê ÷òî îáùèé ðàçìåð íå ïðåâîñõîäèò |
58 | занимает 12 бит в таблице FAT, так что общий размер не превосходит |
59 | 0x17EE = 6126 áàéò. Âñÿ òàáëèöà ïîìåùàåòñÿ â ïàìÿòè. |
59 | 0x17EE = 6126 байт. Вся таблица помещается в памяти. |
60 | Ìàêñèìàëüíîå êîëè÷åñòâî êëàñòåðîâ íà FAT16-òîìå - 0xFFF4 = 65524; êàæäûé |
60 | Максимальное количество кластеров на FAT16-томе - 0xFFF4 = 65524; каждый |
61 | êëàñòåð çàíèìàåò 16 áèò â òàáëèöå FAT, òàê ÷òî îáùèé ðàçìåð íå ïðåâîñõîäèò |
61 | кластер занимает 16 бит в таблице FAT, так что общий размер не превосходит |
62 | 0x1FFE8 = 131048 áàéò. Âñÿ òàáëèöà òàêæå ïîìåùàåòñÿ â ïàìÿòè, îäíàêî â |
62 | 0x1FFE8 = 131048 байт. Вся таблица также помещается в памяти, однако в |
63 | ýòîì ñëó÷àå íåñêîëüêî íåöåëåñîîáðàçíî ñ÷èòûâàòü âñþ òàáëèöó, ïîñêîëüêó |
63 | этом случае несколько нецелесообразно считывать всю таблицу, поскольку |
64 | íà ïðàêòèêå íóæíà òîëüêî íåáîëüøàÿ å¸ ÷àñòü. Ïîýòîìó ìåñòî â ïàìÿòè |
64 | на практике нужна только небольшая её часть. Поэтому место в памяти |
65 | ðåçåðâèðóåòñÿ, íî äàííûå ñ÷èòûâàþòñÿ òîëüêî â ìîìåíò, êîãäà ê íèì |
65 | резервируется, но данные считываются только в момент, когда к ним |
66 | äåéñòâèòåëüíî èä¸ò îáðàùåíèå. |
66 | действительно идёт обращение. |
67 | 67 | ||
68 | Ñõåìà èñïîëüçóåìîé ïàìÿòè: |
68 | Схема используемой памяти: |
69 | ...-7C00 ñòåê |
69 | ...-7C00 стек |
70 | 7C00-7E00 êîä áóòñåêòîðà |
70 | 7C00-7E00 код бутсектора |
71 | 7E00-8200 âñïîìîãàòåëüíûé ôàéë çàãðóç÷èêà (kordldr.f1x) |
71 | 7E00-8200 вспомогательный файл загрузчика (kordldr.f1x) |
72 | 8200-8300 ñïèñîê çàãðóæåííûõ ñåêòîðîâ òàáëèöû FAT16 |
72 | 8200-8300 список загруженных секторов таблицы FAT16 |
73 | (1 = ñîîòâåòñòâóþùèé ñåêòîð çàãðóæåí) |
73 | (1 = соответствующий сектор загружен) |
74 | 60000-80000 çàãðóæåííàÿ òàáëèöà FAT12 / ìåñòî äëÿ òàáëèöû FAT16 |
74 | 60000-80000 загруженная таблица FAT12 / место для таблицы FAT16 |
Line 75... | Line 75... | ||
75 | 80000-90000 òåêóùèé êëàñòåð òåêóùåé ðàññìàòðèâàåìîé ïàïêè |
75 | 80000-90000 текущий кластер текущей рассматриваемой папки |
Line 76... | Line 76... | ||
76 | 90000-92000 êýø äëÿ êîðíåâîé ïàïêè |
76 | 90000-92000 кэш для корневой папки |
77 | 92000-... êýø äëÿ íåêîðíåâûõ ïàïîê (êàæäîé ïàïêå îòâîäèòñÿ |
77 | 92000-... кэш для некорневых папок (каждой папке отводится |
78 | 2000h áàéò = 100h âõîäîâ, îäíîâðåìåííî â êýøå |
78 | 2000h байт = 100h входов, одновременно в кэше |
79 | ìîæåò íàõîäèòüñÿ íå áîëåå 7 ïàïîê; |
79 | может находиться не более 7 папок; |
80 | òî÷íûé ðàçìåð îïðåäåëÿåòñÿ ðàçìåðîì äîñòóïíîé |
80 | точный размер определяется размером доступной |
81 | ôèçè÷åñêîé ïàìÿòè - êàê ïðàâèëî, íåïîñðåäñòâåííî |
81 | физической памяти - как правило, непосредственно |
82 | ïåðåä A0000 ðàçìåùàåòñÿ EBDA, Extended BIOS Data Area) |
82 | перед A0000 размещается EBDA, Extended BIOS Data Area) |
83 | 83 | ||
84 | ===================================================================== |
84 | ===================================================================== |
85 | 85 | ||
86 | Îñíîâíîé ïðîöåññ çàãðóçêè. |
86 | Основной процесс загрузки. |
87 | Òî÷êà âõîäà (start): ïîëó÷àåò óïðàâëåíèå îò BIOS ïðè çàãðóçêå, ïðè ýòîì |
87 | Точка входа (start): получает управление от BIOS при загрузке, при этом |
88 | dl ñîäåðæèò èäåíòèôèêàòîð äèñêà, ñ êîòîðîãî èä¸ò çàãðóçêà |
88 | dl содержит идентификатор диска, с которого идёт загрузка |
89 | 1. Íàñòðàèâàåò ñòåê ss:sp = 0:7C00 (ñòåê ðàñïîëàãàåòñÿ íåïîñðåäñòâåííî ïåðåä |
89 | 1. Настраивает стек ss:sp = 0:7C00 (стек располагается непосредственно перед |
90 | êîäîì), ñåãìåíò äàííûõ ds = 0, è óñòàíàâëèâàåò ss:bp íà íà÷àëî |
90 | кодом), сегмент данных ds = 0, и устанавливает ss:bp на начало |
91 | áóòñåêòîðà (â äàëüíåéøåì äàííûå áóäóò àäðåñîâàòüñÿ ÷åðåç [bp+N] - |
91 | бутсектора (в дальнейшем данные будут адресоваться через [bp+N] - |
92 | ýòî îñâîáîæäàåò ds è ýêîíîìèò íà ðàçìåðå êîäà). |
92 | это освобождает ds и экономит на размере кода). |
93 | 2. LBA-âåðñèÿ: ïðîâåðÿåò, ïîääåðæèâàåò ëè íîñèòåëü LBA, âûçîâîì ôóíêöèè 41h |
93 | 2. LBA-версия: проверяет, поддерживает ли носитель LBA, вызовом функции 41h |
94 | ïðåðûâàíèÿ 13h. Åñëè íåò, ïåðåõîäèò íà êîä îáðàáîòêè îøèáîê ñ |
94 | прерывания 13h. Если нет, переходит на код обработки ошибок с |
95 | ñîîáùåíèåì îá îòñóòñòâèè LBA. |
95 | сообщением об отсутствии LBA. |
96 | CHS-âåðñèÿ: îïðåäåëÿåò ãåîìåòðèþ íîñèòåëÿ âûçîâîì ôóíêöèè 8 ïðåðûâàíèÿ 13h è |
96 | CHS-версия: определяет геометрию носителя вызовом функции 8 прерывания 13h и |
97 | çàïèñûâàåò ïîëó÷åííûå äàííûå ïîâåðõ BPB. Åñëè âûçîâ çàâåðøèëñÿ îøèáêîé, |
97 | записывает полученные данные поверх BPB. Если вызов завершился ошибкой, |
98 | ïðåäïîëàãàåò óæå ñóùåñòâóþùèå äàííûå êîððåêòíûìè. |
98 | предполагает уже существующие данные корректными. |
99 | 3. Âû÷èñëÿåò íåêîòîðûå ïàðàìåòðû FAT-òîìà: íà÷àëüíûé ñåêòîð êîðíåâîé ïàïêè |
99 | 3. Вычисляет некоторые параметры FAT-тома: начальный сектор корневой папки |
100 | è íà÷àëüíûé ñåêòîð äàííûõ. Êëàä¸ò èõ â ñòåê; âïîñëåäñòâèè îíè |
100 | и начальный сектор данных. Кладёт их в стек; впоследствии они |
101 | âñåãäà áóäóò ëåæàòü â ñòåêå è àäðåñîâàòüñÿ ÷åðåç bp. |
101 | всегда будут лежать в стеке и адресоваться через bp. |
102 | 4. Ñ÷èòûâàåò íà÷àëî êîðíåâîé ïàïêè ïî àäðåñó 9000:0000. ×èñëî ñ÷èòûâàåìûõ |
102 | 4. Считывает начало корневой папки по адресу 9000:0000. Число считываемых |
103 | ñåêòîðîâ - ìèíèìóì èç ðàçìåðà êîðíåâîé ïàïêè, óêàçàííîãî â BPB, è 16 |
103 | секторов - минимум из размера корневой папки, указанного в BPB, и 16 |
104 | (ðàçìåð êýøà äëÿ êîðíåâîé ïàïêè - 2000h áàéò = 16 ñåêòîðîâ). |
104 | (размер кэша для корневой папки - 2000h байт = 16 секторов). |
105 | 5. Èùåò â êîðíåâîé ïàïêå ýëåìåíò kordldr.f1x. Åñëè íå íàõîäèò, èëè åñëè |
105 | 5. Ищет в корневой папке элемент kordldr.f1x. Если не находит, или если |
106 | îí îêàçûâàåòñÿ ïàïêîé, èëè åñëè ôàéë èìååò íóëåâóþ äëèíó - |
106 | он оказывается папкой, или если файл имеет нулевую длину - |
107 | ïåðåõîäèò íà êîä îáðàáîòêè îøèáîê ñ ñîîáùåíèåì î |
107 | переходит на код обработки ошибок с сообщением о |
108 | íåíàéäåííîì çàãðóç÷èêå. |
108 | ненайденном загрузчике. |
109 | Çàìå÷àíèå: íà ýòîì ýòàïå çàãðóçêè èñêàòü ìîæíî òîëüêî â êîðíåâîé |
109 | Замечание: на этом этапе загрузки искать можно только в корневой |
110 | ïàïêå è òîëüêî èìåíà, çàäàííûå â ôîðìàòå ôàéëîâîé ñèñòåìå FAT |
110 | папке и только имена, заданные в формате файловой системе FAT |
111 | (8+3 - 8 áàéò íà èìÿ, 3 áàéòà íà ðàñøèðåíèå, âñå áóêâû äîëæíû |
111 | (8+3 - 8 байт на имя, 3 байта на расширение, все буквы должны |
112 | áûòü çàãëàâíûìè, ïðè íåîáõîäèìîñòè èìÿ è ðàñøèðåíèå äîïîëíÿþòñÿ |
112 | быть заглавными, при необходимости имя и расширение дополняются |
113 | ïðîáåëàìè, ðàçäåëÿþùåé òî÷êè íåò, çàâåðøàþùåãî íóëÿ íåò). |
113 | пробелами, разделяющей точки нет, завершающего нуля нет). |
114 | 6. Çàãðóæàåò ïåðâûé êëàñòåð ôàéëà kordldr.f1x ïî àäðåñó 0:7E00 è ïåðåäà¸ò |
114 | 6. Загружает первый кластер файла kordldr.f1x по адресу 0:7E00 и передаёт |
115 | åìó óïðàâëåíèå. Ïðè ýòîì â ðåãèñòðàõ dx:ax îêàçûâàåòñÿ àáñîëþòíûé |
115 | ему управление. При этом в регистрах dx:ax оказывается абсолютный |
Line 116... | Line 116... | ||
116 | íîìåð ïåðâîãî ñåêòîðà kordldr.f1x, à â cx - ÷èñëî ñ÷èòàííûõ ñåêòîðîâ |
116 | номер первого сектора kordldr.f1x, а в cx - число считанных секторов |
117 | (ðàâíîå ðàçìåðó êëàñòåðà). |
117 | (равное размеру кластера). |
118 | 118 | ||
119 | Âñïîìîãàòåëüíûå ïðîöåäóðû áóòñåêòîðà. |
119 | Вспомогательные процедуры бутсектора. |
120 | Êîä îáðàáîòêè îøèáîê (err): |
120 | Код обработки ошибок (err): |
121 | 1. Âûâîäèò ñòðîêó ñ ñîîáùåíèåì îá îøèáêå. |
121 | 1. Выводит строку с сообщением об ошибке. |
122 | 2. Âûâîäèò ñòðîêó "Press any key...". |
122 | 2. Выводит строку "Press any key...". |
123 | 3. Æä¸ò íàæàòèÿ any key. |
123 | 3. Ждёт нажатия any key. |
124 | 4. Âûçûâàåò int 18h, äàâàÿ øàíñ BIOSó ïîïûòàòüñÿ çàãðóçèòüñÿ îòêóäà-íèáóäü åù¸. |
124 | 4. Вызывает int 18h, давая шанс BIOSу попытаться загрузиться откуда-нибудь ещё. |
125 | 5. Äëÿ ïîäñòðàõîâêè çàöèêëèâàåòñÿ. |
125 | 5. Для подстраховки зацикливается. |
126 | 126 | ||
127 | Ïðîöåäóðà ÷òåíèÿ ñåêòîðîâ (read_sectors è read_sectors2): |
127 | Процедура чтения секторов (read_sectors и read_sectors2): |
128 | íà âõîäå äîëæíî áûòü óñòàíîâëåíî: |
128 | на входе должно быть установлено: |
129 | ss:bp = 0:7C00 |
129 | ss:bp = 0:7C00 |
130 | es:bx = óêàçàòåëü íà íà÷àëî áóôåðà, êóäà áóäóò ïðî÷èòàíû äàííûå |
130 | es:bx = указатель на начало буфера, куда будут прочитаны данные |
131 | dx:ax = ñòàðòîâûé ñåêòîð (îòíîñèòåëüíî íà÷àëà ëîãè÷åñêîãî äèñêà |
131 | dx:ax = стартовый сектор (относительно начала логического диска |
132 | äëÿ read_sectors, îòíîñèòåëüíî íà÷àëà äàííûõ äëÿ read_sectors2) |
132 | для read_sectors, относительно начала данных для read_sectors2) |
133 | cx = ÷èñëî ñåêòîðîâ (äîëæíî áûòü áîëüøå íóëÿ) |
133 | cx = число секторов (должно быть больше нуля) |
134 | íà âûõîäå: es:bx óêàçûâàåò íà êîíåö áóôåðà, â êîòîðûé áûëè ïðî÷èòàíû äàííûå |
134 | на выходе: es:bx указывает на конец буфера, в который были прочитаны данные |
135 | 0. Åñëè âûçûâàåòñÿ read_sectors2, îíà ïåðåâîäèò óêàçàííûé åé íîìåð ñåêòîðà |
135 | 0. Если вызывается read_sectors2, она переводит указанный ей номер сектора |
136 | â íîìåð îòíîñèòåëüíî íà÷àëà ëîãè÷åñêîãî äèñêà, ïðèáàâëÿÿ íîìåð ñåêòîðà |
136 | в номер относительно начала логического диска, прибавляя номер сектора |
137 | íà÷àëà äàííûõ, õðàíÿùèéñÿ â ñòåêå êàê [bp-8]. |
137 | начала данных, хранящийся в стеке как [bp-8]. |
138 | 1. Ïåðåâîäèò ñòàðòîâûé ñåêòîð (îòñ÷èòûâàåìûé îò íà÷àëà òîìà) â ñåêòîð íà |
138 | 1. Переводит стартовый сектор (отсчитываемый от начала тома) в сектор на |
139 | óñòðîéñòâå, ïðèáàâëÿÿ çíà÷åíèå ñîîòâåòñòâóþùåãî ïîëÿ èç BPB. |
139 | устройстве, прибавляя значение соответствующего поля из BPB. |
140 | 2.  öèêëå (øàãè 3-6) ÷èòàåò ñåêòîðû, ñëåäèò çà òåì, ÷òîáû íà êàæäîé èòåðàöèè |
140 | 2. В цикле (шаги 3-6) читает секторы, следит за тем, чтобы на каждой итерации |
141 | CHS-âåðñèÿ: âñå ÷èòàåìûå ñåêòîðû áûëè íà îäíîé äîðîæêå. |
141 | CHS-версия: все читаемые секторы были на одной дорожке. |
142 | LBA-âåðñèÿ: ÷èñëî ÷èòàåìûõ ñåêòîðîâ íå ïðåâîñõîäèëî 7Fh (òðåáîâàíèå |
142 | LBA-версия: число читаемых секторов не превосходило 7Fh (требование |
143 | ñïåöèôèêàöèè EDD BIOS). |
143 | спецификации EDD BIOS). |
144 | CHS-âåðñèÿ: |
144 | CHS-версия: |
145 | 3. Ïåðåâîäèò àáñîëþòíûé íîìåð ñåêòîðà â CHS-ñèñòåìó: ñåêòîð ðàññ÷èòûâàåòñÿ êàê |
145 | 3. Переводит абсолютный номер сектора в CHS-систему: сектор рассчитывается как |
146 | åäèíèöà ïëþñ îñòàòîê îò äåëåíèÿ àáñîëþòíîãî íîìåðà íà ÷èñëî ñåêòîðîâ |
146 | единица плюс остаток от деления абсолютного номера на число секторов |
147 | íà äîðîæêå; äîðîæêà ðàññ÷èòûâàåòñÿ êàê îñòàòîê îò äåëåíèÿ ÷àñòíîãî, |
147 | на дорожке; дорожка рассчитывается как остаток от деления частного, |
148 | ïîëó÷åííîãî íà ïðåäûäóùåì øàãå, íà ÷èñëî äîðîæåê, à öèëèíäð - êàê |
148 | полученного на предыдущем шаге, на число дорожек, а цилиндр - как |
149 | ÷àñòíîå îò ýòîãî æå äåëåíèÿ. Åñëè ÷èñëî ñåêòîðîâ äëÿ ÷òåíèÿ áîëüøå, |
149 | частное от этого же деления. Если число секторов для чтения больше, |
150 | ÷åì ÷èñëî ñåêòîðîâ äî êîíöà äîðîæêè, óìåíüøàåò ÷èñëî ñåêòîðîâ äëÿ |
150 | чем число секторов до конца дорожки, уменьшает число секторов для |
151 | ÷òåíèÿ. |
151 | чтения. |
152 | 4. Ôîðìèðóåò äàííûå äëÿ âûçîâà int 13h (ah=2 - ÷òåíèå, al=÷èñëî ñåêòîðîâ, |
152 | 4. Формирует данные для вызова int 13h (ah=2 - чтение, al=число секторов, |
153 | dh=ãîëîâêà, (ìëàäøèå 6 áèò cl)=ñåêòîð, |
153 | dh=головка, (младшие 6 бит cl)=сектор, |
154 | (ñòàðøèå 2 áèòà cl è âåñü ch)=äîðîæêà, dl=äèñê, es:bx->áóôåð). |
154 | (старшие 2 бита cl и весь ch)=дорожка, dl=диск, es:bx->буфер). |
155 | 5. Âûçûâàåò BIOS. Åñëè BIOS ðàïîðòóåò îá îøèáêå, âûïîëíÿåò ñáðîñ äèñêà |
155 | 5. Вызывает BIOS. Если BIOS рапортует об ошибке, выполняет сброс диска |
156 | è ïîâòîðÿåò ïîïûòêó ÷òåíèÿ, âñåãî äåëàåòñÿ íå áîëåå òð¸õ ïîïûòîê |
156 | и повторяет попытку чтения, всего делается не более трёх попыток |
157 | (íåñêîëüêî ïîïûòîê íóæíî â ñëó÷àå äèñêåòû äëÿ ãàðàíòèè òîãî, ÷òî |
157 | (несколько попыток нужно в случае дискеты для гарантии того, что |
158 | ìîòîð ðàñêðóòèëñÿ). Åñëè âñå òðè ðàçà ïðîèñõîäèò îøèáêà ÷òåíèÿ, |
158 | мотор раскрутился). Если все три раза происходит ошибка чтения, |
159 | ïåðåõîäèò íà êîä îáðàáîòêè îøèáîê ñ ñîîáùåíèåì "Read error". |
159 | переходит на код обработки ошибок с сообщением "Read error". |
160 | 6.  ñîîòâåòñòâèè ñ ÷èñëîì ïðî÷èòàííûõ íà òåêóùåé èòåðàöèè ñåêòîðîâ |
160 | 6. В соответствии с числом прочитанных на текущей итерации секторов |
161 | êîððåêòèðóåò òåêóùèé ñåêòîð, ÷èñëî îñòàâøèõñÿ ñåêòîðîâ è óêàçàòåëü íà |
161 | корректирует текущий сектор, число оставшихся секторов и указатель на |
162 | áóôåð (â ïàðå es:bx êîððåêòèðóåòñÿ es). Åñëè âñ¸ ïðî÷èòàíî, çàêàí÷èâàåò |
162 | буфер (в паре es:bx корректируется es). Если всё прочитано, заканчивает |
163 | ðàáîòó, èíà÷å âîçâðàùàåòñÿ íà øàã 3. |
163 | работу, иначе возвращается на шаг 3. |
164 | LBA-âåðñèÿ: |
164 | LBA-версия: |
165 | 3. Åñëè ÷èñëî ñåêòîðîâ äëÿ ÷òåíèÿ áîëüøå 7Fh, óìåíüøàåò åãî (äëÿ òåêóùåé |
165 | 3. Если число секторов для чтения больше 7Fh, уменьшает его (для текущей |
166 | èòåðàöèè) äî 7Fh. |
166 | итерации) до 7Fh. |
Line 167... | Line 167... | ||
167 | 4. Ôîðìèðóåò â ñòåêå ïàêåò äëÿ int 13h (êëàä¸ò âñå íóæíûå äàííûå êîìàíäàìè |
167 | 4. Формирует в стеке пакет для int 13h (кладёт все нужные данные командами |
168 | push, ïðè÷¸ì â îáðàòíîì ïîðÿäêå: ñòåê - ñòðóêòóðà LIFO, è äàííûå â |
168 | push, причём в обратном порядке: стек - структура LIFO, и данные в |
169 | ñòåêå õðàíÿòñÿ â îáðàòíîì ïîðÿäêå ïî îòíîøåíèþ ê òîìó, êàê èõ òóäà |
169 | стеке хранятся в обратном порядке по отношению к тому, как их туда |
170 | êëàëè). |
170 | клали). |
171 | 5. Âûçûâàåò BIOS. Åñëè BIOS ðàïîðòóåò îá îøèáêå, ïåðåõîäèò íà êîä îáðàáîòêè |
171 | 5. Вызывает BIOS. Если BIOS рапортует об ошибке, переходит на код обработки |
172 | îøèáîê ñ ñîîáùåíèåì "Read error". Î÷èùàåò ñòåê îò ïàêåòà, |
172 | ошибок с сообщением "Read error". Очищает стек от пакета, |
173 | ñôîðìèðîâàííîãî íà ïðåäûäóùåì øàãå. |
173 | сформированного на предыдущем шаге. |
174 | 6.  ñîîòâåòñòâèè ñ ÷èñëîì ïðî÷èòàííûõ íà òåêóùåé èòåðàöèè ñåêòîðîâ |
174 | 6. В соответствии с числом прочитанных на текущей итерации секторов |
175 | êîððåêòèðóåò òåêóùèé ñåêòîð, ÷èñëî îñòàâøèõñÿ ñåêòîðîâ è óêàçàòåëü íà |
175 | корректирует текущий сектор, число оставшихся секторов и указатель на |
176 | áóôåð (â ïàðå es:bx êîððåêòèðóåòñÿ es). Åñëè âñ¸ ïðî÷èòàíî, çàêàí÷èâàåò |
176 | буфер (в паре es:bx корректируется es). Если всё прочитано, заканчивает |
177 | ðàáîòó, èíà÷å âîçâðàùàåòñÿ íà øàã 3. |
177 | работу, иначе возвращается на шаг 3. |
178 | 178 | ||
179 | Ïðîöåäóðà ïîèñêà ýëåìåíòà ïî èìåíè â óæå ïðî÷èòàííûõ äàííûõ ïàïêè |
179 | Процедура поиска элемента по имени в уже прочитанных данных папки |
180 | (scan_for_filename): |
180 | (scan_for_filename): |
181 | íà âõîäå äîëæíî áûòü óñòàíîâëåíî: |
181 | на входе должно быть установлено: |
Line 182... | Line 182... | ||
182 | ds:si = óêàçàòåëü íà èìÿ ôàéëà â ôîðìàòå FAT (11 áàéò, 8 íà èìÿ, |
182 | ds:si = указатель на имя файла в формате FAT (11 байт, 8 на имя, |
183 | 3 íà ðàñøèðåíèå, âñå áóêâû çàãëàâíûå, åñëè èìÿ/ðàñøèðåíèå |
183 | 3 на расширение, все буквы заглавные, если имя/расширение |
184 | êîðî÷å, îíî äîïîëíÿåòñÿ äî ìàêñèìóìà ïðîáåëàìè) |
184 | короче, оно дополняется до максимума пробелами) |
185 | es = ñåãìåíò äàííûõ ïàïêè |
185 | es = сегмент данных папки |
186 | cx = ÷èñëî ýëåìåíòîâ â ïðî÷èòàííûõ äàííûõ |
186 | cx = число элементов в прочитанных данных |
187 | íà âûõîäå: ZF îïðåäåëÿåò, íóæíî ëè ïðîäîëæàòü ðàçáîð äàííûõ ïàïêè |
187 | на выходе: ZF определяет, нужно ли продолжать разбор данных папки |
188 | (ZF=1, åñëè ëèáî íàéäåí çàïðîøåííûé ýëåìåíò, ëèáî äîñòèãíóò |
188 | (ZF=1, если либо найден запрошенный элемент, либо достигнут |
189 | êîíåö ïàïêè); CF îïðåäåëÿåò, óäàëîñü ëè íàéòè ýëåìåíò ñ èñêîìûì èìåíåì |
189 | конец папки); CF определяет, удалось ли найти элемент с искомым именем |
190 | (CF=1, åñëè íå óäàëîñü); åñëè óäàëîñü, òî es:di óêàçûâàåò íà íåãî. |
190 | (CF=1, если не удалось); если удалось, то es:di указывает на него. |
191 | scan_for_filename ñ÷èòàåò, ÷òî äàííûå ïàïêè ðàçìåùàþòñÿ íà÷èíàÿ ñ es:0. |
191 | scan_for_filename считает, что данные папки размещаются начиная с es:0. |
192 | Ïåðâîé êîìàíäîé ïðîöåäóðà îáíóëÿåò di. Çàòåì ïðîñòî â öèêëå ïî ýëåìåíòàì ïàïêè |
192 | Первой командой процедура обнуляет di. Затем просто в цикле по элементам папки |
193 | ïðîâåðÿåò èìåíà. |
193 | проверяет имена. |
194 | 194 | ||
195 | Ïðîöåäóðà ïîèñêà ýëåìåíòà â êîðíåâîé ïàïêå (lookup_in_root_dir): |
195 | Процедура поиска элемента в корневой папке (lookup_in_root_dir): |
196 | íà âõîäå äîëæíî áûòü óñòàíîâëåíî: |
196 | на входе должно быть установлено: |
197 | ss:bp = 0:7C00 |
197 | ss:bp = 0:7C00 |
198 | ds:si = óêàçàòåëü íà èìÿ ôàéëà â ôîðìàòå FAT (ñì. âûøå) |
198 | ds:si = указатель на имя файла в формате FAT (см. выше) |
199 | íà âûõîäå: ôëàã CF îïðåäåëÿåò, óäàëîñü ëè íàéòè ôàéë; åñëè óäàëîñü, òî |
199 | на выходе: флаг CF определяет, удалось ли найти файл; если удалось, то |
200 | CF ñáðîøåí è es:di óêàçûâàåò íà ýëåìåíò ïàïêè |
200 | CF сброшен и es:di указывает на элемент папки |
201 | Íà÷èíàåò ñ ïðîñìîòðà êýøèðîâàííîé (íà÷àëüíîé) ÷àñòè êîðíåâîé ïàïêè.  öèêëå |
201 | Начинает с просмотра кэшированной (начальной) части корневой папки. В цикле |
Line 202... | Line 202... | ||
202 | ñêàíèðóåò ýëåìåíòû; åñëè ïî ðåçóëüòàòàì ñêàíèðîâàíèÿ îáíàðóæèâàåò, |
202 | сканирует элементы; если по результатам сканирования обнаруживает, |
Line 203... | Line 203... | ||
203 | ÷òî íóæíî ÷èòàòü ïàïêó äàëüøå, òî ñ÷èòûâàåò íå áîëåå 0x10000 = 64K |
203 | что нужно читать папку дальше, то считывает не более 0x10000 = 64K |
204 | áàéò (îãðàíè÷åíèå ââåäåíî ïî äâóì ïðè÷èíàì: âî-ïåðâûõ, ÷òîáû çàâåäîìî |
204 | байт (ограничение введено по двум причинам: во-первых, чтобы заведомо |
205 | íå âûëåçòè çà ïðåäåëû èñïîëüçóåìîé ïàìÿòè, âî-âòîðûõ, ñêàíèðîâàíèå |
205 | не вылезти за пределы используемой памяти, во-вторых, сканирование |
206 | ïðåäïîëàãàåò, ÷òî âñå îáðàáàòûâàåìûå ýëåìåíòû ðàñïîëàãàþòñÿ â îäíîì |
206 | предполагает, что все обрабатываемые элементы располагаются в одном |
207 | ñåãìåíòå) è ïðîäîëæàåò öèêë. |
207 | сегменте) и продолжает цикл. |
208 | Ñêàíèðîâàíèå ïðåêðàùàåòñÿ â òð¸õ ñëó÷àÿõ: îáíàðóæåí èñêîìûé ýëåìåíò; |
208 | Сканирование прекращается в трёх случаях: обнаружен искомый элемент; |
209 | êîí÷èëèñü ýëåìåíòû â ïàïêå (ñóäÿ ïî ÷èñëó ýëåìåíòîâ, óêàçàííîìó â BPB); |
209 | кончились элементы в папке (судя по числу элементов, указанному в BPB); |
210 | î÷åðåäíîé ýëåìåíò ïàïêè ñèãíàëèçèðóåò î êîíöå (ïåðâûé áàéò íóëåâîé). |
210 | очередной элемент папки сигнализирует о конце (первый байт нулевой). |
211 | 211 | ||
212 | Ïðîöåäóðà âûâîäà íà ýêðàí ASCIIZ-ñòðîêè (out_string): |
212 | Процедура вывода на экран ASCIIZ-строки (out_string): |
213 | íà âõîäå: ds:si -> ñòðîêà |
213 | на входе: ds:si -> строка |
214 | Â öèêëå, ïîêà íå äîñòèãíóò çàâåðøàþùèé íîëü, âûçûâàåò ôóíêöèþ int 10h/ah=0Eh. |
214 | В цикле, пока не достигнут завершающий ноль, вызывает функцию int 10h/ah=0Eh. |
215 | 215 | ||
216 | ===================================================================== |
216 | ===================================================================== |
217 | 217 | ||
218 | Ðàáîòà âñïîìîãàòåëüíîãî çàãðóç÷èêà kordldr.f1x: |
218 | Работа вспомогательного загрузчика kordldr.f1x: |
219 | 1. Îïðåäåëÿåò, áûë ëè îí çàãðóæåí CHS- èëè LBA-âåðñèåé áóòñåêòîðà. |
219 | 1. Определяет, был ли он загружен CHS- или LBA-версией бутсектора. |
220 | Â çàâèñèìîñòè îò ýòîãî óñòàíàâëèâàåò ñìåùåíèÿ èñïîëüçóåìûõ ïðîöåäóð |
220 | В зависимости от этого устанавливает смещения используемых процедур |
221 | áóòñåêòîðà. Êðèòåðèé ïðîâåðêè: scan_for_filename äîëæíà íà÷èíàòüñÿ |
221 | бутсектора. Критерий проверки: scan_for_filename должна начинаться |
222 | ñ èíñòðóêöèè 'xor di,di' ñ êîäîì 31 FF (âîîáùå-òî ýòà èíñòðóêöèÿ ìîæåò |
222 | с инструкции 'xor di,di' с кодом 31 FF (вообще-то эта инструкция может |
223 | ñ ðàâíûì óñïåõîì àññåìáëèðîâàòüñÿ è êàê 33 FF, íî fasm ãåíåðèðóåò |
223 | с равным успехом ассемблироваться и как 33 FF, но fasm генерирует |
224 | èìåííî òàêóþ ôîðìó). |
224 | именно такую форму). |
225 | 2. Óçíà¸ò ðàçìåð ñâîáîäíîé áàçîâîé ïàìÿòè (ò.å. ñâîáîäíîãî íåïðåðûâíîãî êóñêà |
225 | 2. Узнаёт размер свободной базовой памяти (т.е. свободного непрерывного куска |
226 | àäðåñîâ ïàìÿòè, íà÷èíàþùåãîñÿ ñ 0) âûçîâîì int 12h.  ñîîòâåòñòâèè ñ |
226 | адресов памяти, начинающегося с 0) вызовом int 12h. В соответствии с |
227 | íèì âû÷èñëÿåò ÷èñëî ýëåìåíòîâ â êýøå ïàïîê. Õîòÿ áû äëÿ îäíîãî ýëåìåíòà |
227 | ним вычисляет число элементов в кэше папок. Хотя бы для одного элемента |
228 | ìåñòî äîëæíî áûòü, îòñþäà îãðàíè÷åíèå â 592 Kb (94000h áàéò). |
228 | место должно быть, отсюда ограничение в 592 Kb (94000h байт). |
229 | Çàìå÷àíèå: ýòîò ðàçìåð íå ìîæåò ïðåâîñõîäèòü 0A0000h áàéò è |
229 | Замечание: этот размер не может превосходить 0A0000h байт и |
230 | íà ïðàêòèêå îêàçûâàåòñÿ íåìíîãî (íà 1-2 êèëîáàéòà) ìåíüøèì èç-çà |
230 | на практике оказывается немного (на 1-2 килобайта) меньшим из-за |
231 | íàëè÷èÿ äîïîëíèòåëüíîé îáëàñòè äàííûõ BIOS "ââåðõó" áàçîâîé ïàìÿòè. |
231 | наличия дополнительной области данных BIOS "вверху" базовой памяти. |
232 | 3. Îïðåäåëÿåò òèï ôàéëîâîé ñèñòåìû: FAT12 èëè FAT16. Ñîãëàñíî îôèöèàëüíîé |
232 | 3. Определяет тип файловой системы: FAT12 или FAT16. Согласно официальной |
233 | ñïåöèôèêàöèè îò Microsoft (âåðñèÿ 1.03 ñïåöèôèêàöèè äàòèðîâàíà, |
233 | спецификации от Microsoft (версия 1.03 спецификации датирована, |
234 | ê ñëîâó, 06 äåêàáðÿ 2000 ãîäà), ðàçðÿäíîñòü FAT îïðåäåëÿåòñÿ |
234 | к слову, 06 декабря 2000 года), разрядность FAT определяется |
235 | èñêëþ÷èòåëüíî ÷èñëîì êëàñòåðîâ: ìàêñèìàëüíîå ÷èñëî êëàñòåðîâ íà |
235 | исключительно числом кластеров: максимальное число кластеров на |
236 | FAT12-òîìå ðàâíî 4094 = 0xFF4. Ñîãëàñíî çäðàâîìó ñìûñëó, íà FAT12 |
236 | FAT12-томе равно 4094 = 0xFF4. Согласно здравому смыслу, на FAT12 |
237 | ìîæåò áûòü 0xFF5 êëàñòåðîâ, íî íå áîëüøå: êëàñòåðû íóìåðóþòñÿ ñ 2, |
237 | может быть 0xFF5 кластеров, но не больше: кластеры нумеруются с 2, |
238 | à ÷èñëî 0xFF7 íå ìîæåò áûòü êîððåêòíûì íîìåðîì êëàñòåðà. |
238 | а число 0xFF7 не может быть корректным номером кластера. |
239 | Win95/98/Me ñëåäóåò çäðàâîìó ñìûñëó: ðàçãðàíè÷åíèå FAT12/16 äåëàåòñÿ |
239 | Win95/98/Me следует здравому смыслу: разграничение FAT12/16 делается |
240 | ïî ìàêñèìóìó 0xFF5. Äðàéâåð FAT â WinNT/2k/XP/Vista âîîáùå ïîñòóïàåò |
240 | по максимуму 0xFF5. Драйвер FAT в WinNT/2k/XP/Vista вообще поступает |
241 | ÿâíî íåâåðíî, ñ÷èòàÿ, ÷òî 0xFF6 (èëè ìåíüøå) êëàñòåðîâ îçíà÷àåò |
241 | явно неверно, считая, что 0xFF6 (или меньше) кластеров означает |
242 | FAT12-òîì, â ðåçóëüòàòå ïîëó÷àåòñÿ, ÷òî ïîñëåäíèé êëàñòåð |
242 | FAT12-том, в результате получается, что последний кластер |
243 | (â ñëó÷àå 0xFF6) íåàäðåñóåì. Îñíîâíîé çàãðóç÷èê osloader.exe |
243 | (в случае 0xFF6) неадресуем. Основной загрузчик osloader.exe |
244 | [âñòðîåí â ntldr] äëÿ NT/2k/XP äåëàåò òàê æå. Ïåðâè÷íûé çàãðóç÷èê |
244 | [встроен в ntldr] для NT/2k/XP делает так же. Первичный загрузчик |
245 | [áóòñåêòîð FAT12/16 çàãðóæàåò ïåðâûé ñåêòîð ntldr, è ðàçáîð FAT-òàáëèöû |
245 | [бутсектор FAT12/16 загружает первый сектор ntldr, и разбор FAT-таблицы |
246 | ëåæèò íà í¸ì] â NT/2k ïîäâåðæåí òîé æå îøèáêå.  XP å¸ òàêè èñïðàâèëè |
246 | лежит на нём] в NT/2k подвержен той же ошибке. В XP её таки исправили |
247 | â ñîîòâåòñòâèè ñî ñïåöèôèêàöèåé. Linux ïðè îïðåäåëåíèè FAT12/FAT16 |
247 | в соответствии со спецификацией. Linux при определении FAT12/FAT16 |
248 | ÷åñòíî ñëåäóåò ñïåöèôèêàöèè. |
248 | честно следует спецификации. |
249 | Çäåñü êîä îñíîâàí âñ¸ æå íà ñïåöèôèêàöèè. 9x ìåðòâà, à â ëèíåéêå NT |
249 | Здесь код основан всё же на спецификации. 9x мертва, а в линейке NT |
250 | Microsoft åñëè è áóäåò èñïðàâëÿòü îøèáêè, òî ñîãëàñíî ñîáñòâåííîìó |
250 | Microsoft если и будет исправлять ошибки, то согласно собственному |
251 | îïèñàíèþ. |
251 | описанию. |
252 | 4. Äëÿ FAT12: çàãðóæàåò â ïàìÿòü ïåðâóþ êîïèþ òàáëèöû FAT ïî àäðåñó 6000:0000. |
252 | 4. Для FAT12: загружает в память первую копию таблицы FAT по адресу 6000:0000. |
253 | Åñëè ðàçìåð, óêàçàííûé â BPB, ïðåâîñõîäèò 12 ñåêòîðîâ, |
253 | Если размер, указанный в BPB, превосходит 12 секторов, |
254 | ýòî îçíà÷àåò, ÷òî çàÿâëåííûé ðàçìåð ñëèøêîì áîëüøîé (ýòî íå ñ÷èòàåòñÿ |
254 | это означает, что заявленный размер слишком большой (это не считается |
255 | îøèáêîé ôàéëîâîé ñèñòåìû), è ÷èòàþòñÿ òîëüêî 12 ñåêòîðîâ (òàáëèöà FAT12 |
255 | ошибкой файловой системы), и читаются только 12 секторов (таблица FAT12 |
256 | çàâåäîìî âëåçàåò â òàêîé îáú¸ì äàííûõ). |
256 | заведомо влезает в такой объём данных). |
257 | Äëÿ FAT16: èíèöèàëèçèðóåò âíóòðåííèå äàííûå, óêàçûâàÿ, ÷òî íèêàêîé ñåêòîð |
257 | Для FAT16: инициализирует внутренние данные, указывая, что никакой сектор |
258 | FAT íå çàãðóæåí (îíè áóäóò ïîäãðóæàòüñÿ ïîçäíåå, êîãäà ïîíàäîáÿòñÿ |
258 | FAT не загружен (они будут подгружаться позднее, когда понадобятся |
259 | è òîëüêî òå, êîòîðûå ïîíàäîáÿòñÿ). |
259 | и только те, которые понадобятся). |
260 | 5. Åñëè êëàñòåð ðàâåí ñåêòîðó, òî áóòñåêòîð çàãðóçèë òîëüêî ÷àñòü ôàéëà |
260 | 5. Если кластер равен сектору, то бутсектор загрузил только часть файла |
261 | kordldr.f1x, è çàãðóç÷èê ïîäãðóæàåò âòîðóþ ñâîþ ÷àñòü, èñïîëüçóÿ |
261 | kordldr.f1x, и загрузчик подгружает вторую свою часть, используя |
262 | çíà÷åíèÿ ðåãèñòðîâ íà âõîäå â kordldr.f1x. |
262 | значения регистров на входе в kordldr.f1x. |
263 | 6. Çàãðóæàåò âòîðè÷íûé çàãðóç÷èê kord/loader ïî àäðåñó 1000:0000. Åñëè ôàéë íå |
263 | 6. Загружает вторичный загрузчик kord/loader по адресу 1000:0000. Если файл не |
264 | íàéäåí, èëè îêàçàëñÿ ïàïêîé, èëè îêàçàëñÿ ñëèøêîì áîëüøèì, òî ïåðåõîäèò |
264 | найден, или оказался папкой, или оказался слишком большим, то переходит |
265 | íà êîä îáðàáîòêè îøèáîê èç áóòñåêòîðà ñ ñîîáùåíèåì |
265 | на код обработки ошибок из бутсектора с сообщением |
266 | "Fatal error: cannot load the secondary loader". |
266 | "Fatal error: cannot load the secondary loader". |
267 | Çàìå÷àíèå: íà ýòîì ýòàïå èìÿ ôàéëà óæå ìîæíî óêàçûâàòü âìåñòå ñ ïóò¸ì |
267 | Замечание: на этом этапе имя файла уже можно указывать вместе с путём |
268 | è â ôîðìàòå ASCIIZ, õîòÿ ïîääåðæêè äëèííûõ èì¸í è íåàíãëèéñêèõ ñèìâîëîâ |
268 | и в формате ASCIIZ, хотя поддержки длинных имён и неанглийских символов |
269 | ïî-ïðåæíåìó íåò. |
269 | по-прежнему нет. |
270 | 7. Èçìåíÿåò êîä îáðàáîòêè îøèáîê áóòñåêòîðà íà ïåðåõîä íà ìåòêó hooked_err. |
270 | 7. Изменяет код обработки ошибок бутсектора на переход на метку hooked_err. |
271 | Ýòî íóæíî, ÷òîáû ïîñëåäóþùèå îáðàùåíèÿ ê êîäó áóòñåêòîðà â ñëó÷àå |
271 | Это нужно, чтобы последующие обращения к коду бутсектора в случае |
272 | îøèáîê ÷òåíèÿ íå âûâîäèë ñîîòâåòñòâóþùåå ñîîáùåíèå ñ ïîñëåäóþùåé |
272 | ошибок чтения не выводил соответствующее сообщение с последующей |
273 | ïåðåçàãðóçêîé, à ðàïîðòîâàë îá îøèáêå ÷òåíèÿ, êîòîðóþ ìîã áû |
273 | перезагрузкой, а рапортовал об ошибке чтения, которую мог бы |
274 | êàê-íèáóäü îáðàáîòàòü âòîðè÷íûé çàãðóç÷èê. |
274 | как-нибудь обработать вторичный загрузчик. |
275 | 8. Åñëè çàãðóçî÷íûé äèñê èìååò èäåíòèôèêàòîð ìåíüøå 0x80, |
275 | 8. Если загрузочный диск имеет идентификатор меньше 0x80, |
276 | òî óñòàíàâëèâàåò al='f' ("floppy"), ah=èäåíòèôèêàòîð äèñêà, |
276 | то устанавливает al='f' ("floppy"), ah=идентификатор диска, |
277 | èíà÷å al='h' ("hard"), ah=èäåíòèôèêàòîð äèñêà-0x80 (íîìåð äèñêà). |
277 | иначе al='h' ("hard"), ah=идентификатор диска-0x80 (номер диска). |
278 | Óñòàíàâëèâàåò bx='12', åñëè òèï ôàéëîâîé ñèñòåìû - FAT12, è |
278 | Устанавливает bx='12', если тип файловой системы - FAT12, и |
279 | bx='16' â ñëó÷àå FAT16. Óñòàíàâëèâàåò si=ñìåùåíèå ôóíêöèè îáðàòíîãî |
279 | bx='16' в случае FAT16. Устанавливает si=смещение функции обратного |
280 | âûçîâà. Ïîñêîëüêó â ýòîò ìîìåíò ds=0, òî ds:si îáðàçóþò ïîëíûé àäðåñ. |
280 | вызова. Поскольку в этот момент ds=0, то ds:si образуют полный адрес. |
281 | 9. Ïåðåäà¸ò óïðàâëåíèå ïî àäðåñó 1000:0000. |
281 | 9. Передаёт управление по адресу 1000:0000. |
282 | 282 | ||
283 | Ôóíêöèÿ îáðàòíîãî âûçîâà äëÿ âòîðè÷íîãî çàãðóç÷èêà: |
283 | Функция обратного вызова для вторичного загрузчика: |
284 | ïðåäîñòàâëÿåò âîçìîæíîñòü ÷òåíèÿ ôàéëà. |
284 | предоставляет возможность чтения файла. |
285 | Âõîä è âûõîä îïèñàíû â ñïåöèôèêàöèè íà çàãðóç÷èê. |
285 | Вход и выход описаны в спецификации на загрузчик. |
286 | 1. Ñîõðàíÿåò ñòåê âûçûâàþùåãî êîäà è óñòàíàâëèâàåò ñâîé ñòåê: |
286 | 1. Сохраняет стек вызывающего кода и устанавливает свой стек: |
287 | ss:sp = 0:(7C00-8), bp=7C00: ïàðà ss:bp ïðè ðàáîòå ñ îñòàëüíûì |
287 | ss:sp = 0:(7C00-8), bp=7C00: пара ss:bp при работе с остальным |
288 | êîäîì äîëæíà óêàçûâàòü íà 0:7C00, à -8 áåð¸òñÿ îò òîãî, ÷òî |
288 | кодом должна указывать на 0:7C00, а -8 берётся от того, что |
289 | èíèöèàëèçèðóþùèé êîä áóòñåêòîðà óæå ïîìåñòèë â ñòåê 2 äâîéíûõ ñëîâà, |
289 | инициализирующий код бутсектора уже поместил в стек 2 двойных слова, |
290 | è îíè äîëæíû ñîõðàíÿòüñÿ â íåèçìåííîñòè. |
290 | и они должны сохраняться в неизменности. |
291 | 2. Ðàçáèðàåò ïåðåäàííûå ïàðàìåòðû, âûÿñíÿåò, êàêîå äåéñòâèå çàïðîøåíî, |
291 | 2. Разбирает переданные параметры, выясняет, какое действие запрошено, |
292 | è âûçûâàåò íóæíóþ âñïîìîãàòåëüíóþ ïðîöåäóðó. |
292 | и вызывает нужную вспомогательную процедуру. |
293 | 3. Âîññòàíàâëèâàåò ñòåê âûçûâàþùåãî êîäà è âîçâðàùàåò óïðàâëåíèå. |
293 | 3. Восстанавливает стек вызывающего кода и возвращает управление. |
294 | 294 | ||
295 | Âñïîìîãàòåëüíûå ïðîöåäóðû kordldr.f1x. |
295 | Вспомогательные процедуры kordldr.f1x. |
296 | Ïðîöåäóðà ïîëó÷åíèÿ ñëåäóþùåãî êëàñòåðà â FAT (get_next_cluster): |
296 | Процедура получения следующего кластера в FAT (get_next_cluster): |
297 | 1. Âñïîìèíàåò ðàçðÿäíîñòü FAT, âû÷èñëåííóþ ðàíåå. |
297 | 1. Вспоминает разрядность FAT, вычисленную ранее. |
298 | Äëÿ FAT12: |
298 | Для FAT12: |
299 | 2. Óñòàíàâëèâàåò ds = 0x6000 - ñåãìåíò, êóäà ðàíåå áûëà ñ÷èòàíà |
299 | 2. Устанавливает ds = 0x6000 - сегмент, куда ранее была считана |
300 | âñÿ òàáëèöà FAT. |
300 | вся таблица FAT. |
301 | 3. Ïîäñ÷èòûâàåò si = (êëàñòåð) + (êëàñòåð)/2 - ñìåùåíèå â ýòîì ñåãìåíòå |
301 | 3. Подсчитывает si = (кластер) + (кластер)/2 - смещение в этом сегменте |
302 | ñëîâà, çàäàþùåãî ñëåäóþùèé êëàñòåð. Çàãðóæàåò ñëîâî ïî ýòîìó àäðåñó. |
302 | слова, задающего следующий кластер. Загружает слово по этому адресу. |
303 | 4. Åñëè êëàñòåð èìååò íå÷¸òíûé íîìåð, òî ñîîòâåòñòâóþùèé åìó ýëåìåíò |
303 | 4. Если кластер имеет нечётный номер, то соответствующий ему элемент |
304 | ðàñïîëàãàåòñÿ â ñòàðøèõ 12 áèòàõ ñëîâà, è ñëîâî íóæíî ñäâèíóòü âïðàâî |
304 | располагается в старших 12 битах слова, и слово нужно сдвинуть вправо |
305 | íà 4 áèòà; â ïðîòèâíîì ñëó÷àå - â ìëàäøèõ 12 áèòàõ, è äåëàòü íè÷åãî íå |
305 | на 4 бита; в противном случае - в младших 12 битах, и делать ничего не |
306 | íàäî. |
306 | надо. |
307 | 5. Âûäåëÿåò èç ïîëó÷èâøåãîñÿ ñëîâà 12 áèò. Ñðàâíèâàåò èõ ñ ïðåäåëîì 0xFF7: |
307 | 5. Выделяет из получившегося слова 12 бит. Сравнивает их с пределом 0xFF7: |
308 | íîìåðà íîðìàëüíûõ êëàñòåðîâ ìåíüøå, è ôëàã CF óñòàíàâëèâàåòñÿ; |
308 | номера нормальных кластеров меньше, и флаг CF устанавливается; |
309 | ñïåöèàëüíûå çíà÷åíèÿ EOF è BadClus ñáðàñûâàþò ôëàã CF. |
309 | специальные значения EOF и BadClus сбрасывают флаг CF. |
310 | Äëÿ FAT16: |
310 | Для FAT16: |
311 | 2. Âû÷èñëÿåò àäðåñ ïàìÿòè, ïðåäíàçíà÷åííîé äëÿ ñîîòâåòñòâóþùåãî ñåêòîðà äàííûõ |
311 | 2. Вычисляет адрес памяти, предназначенной для соответствующего сектора данных |
312 | â òàáëèöå FAT. |
312 | в таблице FAT. |
313 | 3. Åñëè ñåêòîð åù¸ íå çàãðóæåí, òî çàãðóæàåò åãî. |
313 | 3. Если сектор ещё не загружен, то загружает его. |
314 | 4. Âû÷èñëÿåò ñìåùåíèå äàííûõ äëÿ êîíêðåòíîãî êëàñòåðà îòíîñèòåëüíî íà÷àëà |
314 | 4. Вычисляет смещение данных для конкретного кластера относительно начала |
315 | ñåêòîðà. |
315 | сектора. |
316 | 5. Çàãðóæàåò ñëîâî â ax èç àäðåñà, âû÷èñëåííîìó íà øàãàõ 1 è 3. |
316 | 5. Загружает слово в ax из адреса, вычисленному на шагах 1 и 3. |
317 | 6. Ñðàâíèâàåò åãî ñ ïðåäåëîì 0xFFF7: íîìåðà íîðìàëüíûõ êëàñòåðîâ ìåíüøå, è ôëàã |
317 | 6. Сравнивает его с пределом 0xFFF7: номера нормальных кластеров меньше, и флаг |
318 | CF óñòàíàâëèâàåòñÿ; ñïåöèàëüíûå çíà÷åíèÿ EOF è BadClus ñáðàñûâàþò CF. |
318 | CF устанавливается; специальные значения EOF и BadClus сбрасывают CF. |
319 | 319 | ||
320 | Ïðîöåäóðà çàãðóçêè ôàéëà (load_file): |
320 | Процедура загрузки файла (load_file): |
321 | 1. Òåêóùàÿ ðàññìàòðèâàåìàÿ ïàïêà - êîðíåâàÿ. Â öèêëå âûïîëíÿåò øàãè 2-4. |
321 | 1. Текущая рассматриваемая папка - корневая. В цикле выполняет шаги 2-4. |
322 | 2. Êîíâåðòèðóåò èìÿ òåêóùåãî ðàññìàòðèâàåìîãî êîìïîíåíòà èìåíè (êîìïîíåíòû |
322 | 2. Конвертирует имя текущего рассматриваемого компонента имени (компоненты |
323 | ðàçäåëÿþòñÿ ñèìâîëîì '/') â FAT-ôîðìàò 8+3. Åñëè ýòî íåâîçìîæíî |
323 | разделяются символом '/') в FAT-формат 8+3. Если это невозможно |
324 | (áîëüøå 8 ñèìâîëîâ â èìåíè, áîëüøå 3 ñèìâîëîâ â ðàñøèðåíèè èëè |
324 | (больше 8 символов в имени, больше 3 символов в расширении или |
325 | áîëüøå îäíîé òî÷êè), âîçâðàùàåòñÿ ñ îøèáêîé. |
325 | больше одной точки), возвращается с ошибкой. |
326 | 3. Èùåò ýëåìåíò ñ òàêèì èìåíåì â òåêóùåé ðàññìàòðèâàåìîé ïàïêå. Äëÿ êîðíåâîé |
326 | 3. Ищет элемент с таким именем в текущей рассматриваемой папке. Для корневой |
327 | ïàïêè èñïîëüçóåòñÿ ïðîöåäóðà èç áóòñåêòîðà. Äëÿ îñòàëüíûõ ïàïîê: |
327 | папки используется процедура из бутсектора. Для остальных папок: |
328 | a) Ïðîâåðÿåò, åñòü ëè òàêàÿ ïàïêà â êýøå íåêîðíåâûõ ïàïîê. |
328 | a) Проверяет, есть ли такая папка в кэше некорневых папок. |
329 | (Èäåíòèôèêàöèÿ ïàïîê îñóùåñòâëÿåòñÿ ïî íîìåðó íà÷àëüíîãî êëàñòåðà.) |
329 | (Идентификация папок осуществляется по номеру начального кластера.) |
330 | Åñëè òàêîé ïàïêè åù¸ íåò, äîáàâëÿåò å¸ â êýø; åñëè òîò ïåðåïîëíÿåòñÿ, |
330 | Если такой папки ещё нет, добавляет её в кэш; если тот переполняется, |
331 | âûêèäûâàåò ïàïêó, ê êîòîðîé äîëüøå âñåãî íå áûëî îáðàùåíèé. (Äëÿ |
331 | выкидывает папку, к которой дольше всего не было обращений. (Для |
332 | êàæäîãî ýëåìåíòà êýøà õðàíèòñÿ ìåòêà îò 0 äî (ðàçìåð êýøà)-1, |
332 | каждого элемента кэша хранится метка от 0 до (размер кэша)-1, |
333 | îïðåäåëÿþùàÿ åãî íîìåð ïðè ñîðòèðîâêå ïî äàâíîñòè ïîñëåäíåãî îáðàùåíèÿ. |
333 | определяющая его номер при сортировке по давности последнего обращения. |
334 | Ïðè îáðàùåíèè ê êàêîìó-òî ýëåìåíòó åãî ìåòêà ñòàíîâèòñÿ íóëåâîé, |
334 | При обращении к какому-то элементу его метка становится нулевой, |
335 | à òå ìåòêè, êîòîðûå ìåíüøå ñòàðîãî çíà÷åíèÿ, óâåëè÷èâàþòñÿ íà åäèíèöó.) |
335 | а те метки, которые меньше старого значения, увеличиваются на единицу.) |
336 | á) Ïðîñìàòðèâàåò â ïîèñêàõ çàïðîøåííîãî èìåíè âñå ýëåìåíòû èç êýøà, |
336 | б) Просматривает в поисках запрошенного имени все элементы из кэша, |
337 | èñïîëüçóÿ ïðîöåäóðó èç áóòñåêòîðà. Åñëè îáíàðóæèâàåò èñêîìûé ýëåìåíò, |
337 | используя процедуру из бутсектора. Если обнаруживает искомый элемент, |
338 | ïåðåõîäèò ê øàãó 4. Åñëè îáíàðóæèâàåò êîíåö ïàïêè, âîçâðàùàåòñÿ èç |
338 | переходит к шагу 4. Если обнаруживает конец папки, возвращается из |
339 | ïðîöåäóðû ñ îøèáêîé. |
339 | процедуры с ошибкой. |
340 | â)  öèêëå ñ÷èòûâàåò ïàïêó ïîñåêòîðíî. Ïðè ýòîì ïðîïóñêàåò íà÷àëüíûå |
340 | в) В цикле считывает папку посекторно. При этом пропускает начальные |
341 | ñåêòîðû, êîòîðûå óæå íàõîäÿòñÿ â êýøå è óæå áûëè ïðîñìîòðåíû. Êàæäûé |
341 | секторы, которые уже находятся в кэше и уже были просмотрены. Каждый |
342 | ïðî÷èòàííûé ñåêòîð êîïèðóåò â êýø, åñëè òàì åù¸ îñòà¸òñÿ ìåñòî, |
342 | прочитанный сектор копирует в кэш, если там ещё остаётся место, |
343 | è ïðîñìàòðèâàåò â í¸ì âñå ýëåìåíòû. Ðàáîòàåò, ïîêà íå ñëó÷èòñÿ îäíî èç |
343 | и просматривает в нём все элементы. Работает, пока не случится одно из |
344 | òð¸õ ñîáûòèé: íàéäåí èñêîìûé ýëåìåíò; êîí÷èëèñü êëàñòåðû (ñóäÿ ïî |
344 | трёх событий: найден искомый элемент; кончились кластеры (судя по |
345 | öåïî÷êå êëàñòåðîâ â FAT); î÷åðåäíîé ýëåìåíò ïàïêè ñèãíàëèçèðóåò î êîíöå |
345 | цепочке кластеров в FAT); очередной элемент папки сигнализирует о конце |