Igor1024 Никакой, просто главное знать сколько точно байт. Сейчас пишу документ, где описываю свою файловую систему. В начале хотел до безобразия простую, но сейчас вот думаю как бы сделать простую, и в тоже время с каталогами. Так что я весь в работе. После этого документа, напишу на C++ программу, которая позволит открывать мой виртуальный образ дискеты как мою файловую систему (если конечно она будет в неё форматирована) и будет позволять просматривать, создавать, удалять и копировать файлы на дискету. ну и напишу программу, которая будет форматировать дискету в мою файловую систему.
Кстати, на дискете минимальное что можно извлечь - это сектор (512 байт). Получается, что если хоть один байт в секторе испорченный, то весь сектор не доступен (ошибочен). А как можно выяснить какие сектора с ошибками?
Вот скажите, пожалуйста, если у меня есть дискета 3.5' высокой плотности, которая вмещает 1474560 байт (1440 КБ), то из скольких частей она будет состоять (я имею в виду: головки, цилиндры и сектора)? Обязательно ли это будет для каждой подобной дискеты одинаковым количеством? 1474560 байт - это 2880 секторов. Но сами сектора располагаются на цилиндре. А в свою очередь цилиндры располагаются на головке. На сколько я знаю, головок может быть либо 1, либо 2. От чего это зависит и как это определять? Всё-таки я должен знать как мне каждую дискету полностью считывать. На каждой головке располагается какое-то количество цилиндров. Это число всегда постоянно, или же оно в два раза больше если всего одна головка? А вот уже на каждом цилиндре располагаются сектора. Сколько их? Надеюсь для дискет 3.5' высокой плотности постоянно одно и то же количество всех деталей.
Для всех 3.5' дискет высокой плотности характерно такое: - 2 головки; - на каждой головке по 80 цилиндров; - на каждом цилиндре по 18 секторов. ?
Цилиндр -- это группа дорожек, доступных для считывания-записи без механического перемещения блока головок. Так что ни головки на цилиндрах быть не могут, ни цилиндры на головках. Каждая дорожка состоит из одного или нескольких секторов, причём их число может быть переменным (и своим для каждой дорожки). Собственно, именно поэтому один и тот же привод способен считывать и записывать дискеты разных форматов. Никакого способа со 100% достоверностью узнать, сколько цилиндров на дискете используется и какое число секторов на каждой дорожке, не существует, не считая попыток считывания содержимого дискеты во всех мыслимых и немыслимых сочетаниях количества цилиндров, используемых головок (одна или две) и числа секторов на дорожке. Но этим никто, кроме специализированных программ, и не занимается; вместо этого используются несколько стандартных форматов дискет, а информация о том, какой именно формат применяется на данной дискете, хранится в её первом секторе (цилиндр 0, головка 0, сектор 1) в составе блока параметров BIOS (вроде так он называется, подробно уже не помню). Если дискета отформатирована нестандартным образом, то обычные ОС работать с ней не смогут как раз потому, что они не поддерживают любой изврат, какой только можно сотворить с дискетой.
добавлю, что никто не мешает сделать 160 дорожек, 20 секторов и по 1024 байта на сектор (и получить совсем неприличную емкость 6400К - другой вопрос, найдется ли дискета столь хорошего качества, и привод, в котором она будет стабильно читаться, иначе получишь 95% в бэдах). Или сделать по 1024 байта на сектор и 10 секторов на дорожку начиная с дорожки 45. Один из методов защиты дискеты от копирования. Когда-то во времена ДОС были популярны программки, форматирующие дискеты совсем нестандартно. Чтоб хоть немного, а побольше влезло. Нортоновские утилиты вроде в составе такую софтину имели. На самом деле, обычным format'ом тоже можно что-то сделать. Но в то время были удобнее утилиты - показывали процесс графически, позволяли порядок секторов поменять, оптимизировали размещение секторов по сторонам с учетом 2-х головок и угловой скорости вращения. Если дискета была размечена успешно, то как минимум с дос 6.22 она нормально работала, лично имел пачку дискет, отформатированных на 1.8Мб - читались без установки каких-либо драйверов, архивы на них таскал. Так что по хорошему, не только в емкости диска нельзя быть уверенным, но даже и в емкости сектора.
Подскажите, я совсем запутался с адресами! В реальном режиме загрузчик копируется по адресу 0x7C00:0x0000 и занимает 512 байт. Если выразить это в диапазоне, то получается от 0x7C00:0x0000 до 0x7C00:0x01FF. Правильно? А вот по какому диапазону адресов я должен обратиться в защищённом режиме, чтобы получить эти же 512 байт, которые загрузчик мне скопировал? От 0x0007C000 до 0x0007C1FF? Разумеется с учётом того, что я объявил сегмент на всё адресное пространство.
SII Спасибо! Забудем на время о C-коде. Есть два файла: boot.asm и preparing.asm. Вот содержимое boot.asm: Code (Text): use16 org 0x7C00 boot__code16: mov AX,CS mov DS,AX mov ES,AX mov FS,AX mov GS,AX mov SS,AX mov AX,boot_stack16_start mov SP,AX mov AH,0x02 mov AL,5 ; Количество читаемых секторов mov CL,2 ; Сектор mov CH,0 ; Цилиндр mov DH,0 ; Головка mov DL,0 ; Диск mov BX,boot__continuation int 0x13 jmp boot__continuation boot__data16: db 0,0,0,0,0,0,0,0 db 0,0,0,0,0,0,0,0 db 0,0,0,0,0,0,0,0 db 0,0,0,0,0,0,0,0 db 0,0,0,0,0,0,0,0 db 0,0,0,0,0,0,0,0 db 0,0,0,0,0,0,0,0 db 0,0,0,0,0,0,0,0 boot__stack16: db 0,0,0,0,0,0,0,0 db 0,0,0,0,0,0,0,0 db 0,0,0,0,0,0,0,0 db 0,0,0,0,0,0,0,0 db 0,0,0,0,0,0,0,0 db 0,0,0,0,0,0,0,0 db 0,0,0,0,0,0,0,0 boot_stack16_start: db 0,0,0,0,0,0,0,0 rb 510-($-$$) db 0x55,0xAA boot__continuation: include "preparing.asm" rb 1023-($-$$) db 0x00 А вот содержимое preparing.asm: Code (Text): preparing__code16: cli in AL,0x92 or AL,0x02 out 92h,AL lgdt [preparing__data16_gdtr] mov EAX,CR0 or EAX,00000000000000000000000000000001b mov CR0,EAX jmp 0000000000001000b:preparing__pmode preparing__data16: preparing__data16_gdtr: dw 8*4-1 dd preparing__data16_gdt preparing__data16_gdt: preparing__data16_gdt_null: dw 0000000000000000b ; Segment Limit(16) dw 0000000000000000b ; Base Address(16) db 00000000b ; Base Address(8) db 00000000b ; P(1), DPL(2), S(1), Type(4) db 00000000b ; G(1), D(1), NULL(1), AVL(1), Segment Limit(4) db 00000000b ; Base Address(8) preparing__data16_gdt_code: dw 1111111111111111b ; Segment Limit(16) dw 0000000000000000b ; Base Address(16) db 00000000b ; Base Address(8) db 10011000b ; P(1), DPL(2), S(1), Type(4) db 11001111b ; G(1), D(1), NULL(1), AVL(1), Segment Limit(4) db 00000000b ; Base Address(8) preparing__data16_gdt_data: dw 1111111111111111b ; Segment Limit(16) dw 0000000000000000b ; Base Address(16) db 00000000b ; Base Address(8) db 10010010b ; P(1), DPL(2), S(1), Type(4) db 11001111b ; G(1), D(1), NULL(1), AVL(1), Segment Limit(4) db 00000000b ; Base Address(8) preparing__data16_gdt_stack: dw 1111111111111111b ; Segment Limit(16) dw 0000000000000000b ; Base Address(16) db 00000000b ; Base Address(8) db 10010110b ; P(1), DPL(2), S(1), Type(4) db 11001111b ; G(1), D(1), NULL(1), AVL(1), Segment Limit(4) db 00000000b ; Base Address(8) preparing__pmode: use32 mov AX,0000000000010000b mov DS,AX mov ES,AX mov FS,AX mov GS,AX mov AX,0000000000011000b mov SS,AX mov ESP,0x0007C1FF mov ECX,80*25 mov EAX,0x000B8000 @@: mov [EAX],byte ' ' inc EAX mov [EAX],byte 00010000b inc EAX loop @b hlt Компилирую: Code (Text): fasm boot.asm BOS.img Запускаю в Bochs и всё работает как и планировалось. Но вот только стоит мне использовать стек: Code (Text): preparing__code16: cli in AL,0x92 or AL,0x02 out 92h,AL lgdt [preparing__data16_gdtr] mov EAX,CR0 or EAX,00000000000000000000000000000001b mov CR0,EAX jmp 0000000000001000b:preparing__pmode preparing__data16: preparing__data16_gdtr: dw 8*4-1 dd preparing__data16_gdt preparing__data16_gdt: preparing__data16_gdt_null: dw 0000000000000000b ; Segment Limit(16) dw 0000000000000000b ; Base Address(16) db 00000000b ; Base Address(8) db 00000000b ; P(1), DPL(2), S(1), Type(4) db 00000000b ; G(1), D(1), NULL(1), AVL(1), Segment Limit(4) db 00000000b ; Base Address(8) preparing__data16_gdt_code: dw 1111111111111111b ; Segment Limit(16) dw 0000000000000000b ; Base Address(16) db 00000000b ; Base Address(8) db 10011000b ; P(1), DPL(2), S(1), Type(4) db 11001111b ; G(1), D(1), NULL(1), AVL(1), Segment Limit(4) db 00000000b ; Base Address(8) preparing__data16_gdt_data: dw 1111111111111111b ; Segment Limit(16) dw 0000000000000000b ; Base Address(16) db 00000000b ; Base Address(8) db 10010010b ; P(1), DPL(2), S(1), Type(4) db 11001111b ; G(1), D(1), NULL(1), AVL(1), Segment Limit(4) db 00000000b ; Base Address(8) preparing__data16_gdt_stack: dw 1111111111111111b ; Segment Limit(16) dw 0000000000000000b ; Base Address(16) db 00000000b ; Base Address(8) db 10010110b ; P(1), DPL(2), S(1), Type(4) db 11001111b ; G(1), D(1), NULL(1), AVL(1), Segment Limit(4) db 00000000b ; Base Address(8) preparing__pmode: use32 mov AX,0000000000010000b mov DS,AX mov ES,AX mov FS,AX mov GS,AX mov AX,0000000000011000b mov SS,AX mov ESP,0x0007C1FF push AX mov ECX,80*25 mov EAX,0x000B8000 @@: mov [EAX],byte ' ' inc EAX mov [EAX],byte 00010000b inc EAX loop @b hlt То у меня виртуальный компьютер по кругу перезагружается, не успевая закрасить экран в синий цвет. То есть запинается на инструкции push AX. Что я делаю не так и как надо?
Всем доброй ночи! С чужой помощью удалось добиться работы кода. Во всём был виноват дескриптор сегмента данных, который я решил описать как стек (не нравилось ему что я бит EW установил в 1). Заработал и C++ код (компилирую через g++). Смог C++ кодом очищать экран и выводить символы. Но возникла проблема с вводом текста. Почему-то у меня не передаётся в функцию указатель на текст: Code (Text): #define VIDEO_RAM 0x000B8000 void Clear(const char _color); void DrawChar(const char _char,const unsigned int _x,const unsigned int _y,const char _color); void DrawText(const char* _text,const unsigned int _x,const unsigned int _y,const char _color); void kernel(void) { Clear(0b00010000); DrawText("Hello!\0",0,0,0b00011110); DrawChar('1',4,1,0b00001010); for(;;) { } } void Clear(const char _color) { unsigned int i=0; char* address=0; address=(char*)VIDEO_RAM; for(i=0;i<80*25*2;i+=2) { *(address+i)=' '; *(address+i+1)=_color; } } void DrawChar(const char _char,const unsigned int _x,const unsigned int _y,const char _color) { unsigned int i=0; char* address=0; i=160*_y+2*_x; address=(char*)VIDEO_RAM; *(address+i) = _char; *(address+i+1) = _color; } void DrawText(const char* _text,const unsigned int _x,const unsigned int _y,const char _color) { unsigned int i=0; unsigned int j=0; unsigned int length=0; char* address=0; i=160*_y+2*_x; address=(char*)VIDEO_RAM; while(_text[length]) length++; while(length) { *(address+i) = _text[j]; *(address+i+1) = _color; i+=2; j++; length--; } } В результате у меня выводится только символ 1 от функции DrawChar(). Почему функция DrawText() не получает указатель на текст и как это исправить?
Всем доброго дня! Я тут начал уже писать функции для очистки экрана, для очистки диапазона памяти и для вывода на экран текста и целых чисел. Не подскажите стать, где описано как вещественные числа (float, double и long double) переводить в текст? И ещё хочется понять как работают new, new[], delete и delete[]. Хотелось бы их использовать, но они к чему-то привязаны. Вообще, что мне нужно сделать, чтобы у меня программа могла с ними работать?
Они тянут три гигабайта кода с собой. Ну, не три, но всё равно полно. В конечном счёте эти вызовы могут обращаться к Вин32 АПИ (ну или другим АПИ в зависимости от ОС), поэтому их придётся переписывать самому.
Выделение и освобождение памяти нужного размера. Напишите программу на Си++ для Винды, дизассемблируйте да разберитесь, какой код компилятор генерирует для этих операторов и что конкретно делают соответствующие подпрограммы.
s3dworld New и Delete не простые функции нюансов там много. Они вызывает malloc и free Их внутреннее устройство немного расписано здесь http://dvoika.net/infor/teor/Glava 4/Index3.htm