FAT BPB и обращение с прямым порядком байтов

Мой процессор имеет обратный порядок следования байтов, который, как мне сказали в документации, соответствует порядку байтов спецификации FAT. Почему же тогда я получаю действительный адрес для BS_jmpBoot, байты 0-3 первого сектора, но не получаю действительного числа для BPB_BytesPerSec, байты 11-12 первого сектора.

116         int fd = open (diskpath, O_RDONLY, S_IROTH);
117 
118         read (fd, BS_jmpBoot, 3);
119         printf("BS_jmpBoot = 0x%02x%02x%02x\n", BS_jmpBoot[0], S_jmpBoot[1], S_jmpBoot[2]);
120 
121         read (fd, OEMName, 8);
122         OEMName[8] = '\0';
123         printf("OEMName = %s\n", OEMName);
124 
125         read (fd, BPB_BytesPerSec, 2);
126         printf("BPB_BytesPerSec = 0x%02x%02x\n",BPB_BytesPerSec[0], BPB_BytesPerSec[1]);

Урожайность

BS_jmpBoot = 0xeb5890                  //valid address, while 0x9058eb would not be
OEMName = MSDOS5.0
BPB_BytesPerSec = 0x0002               //Should be 0x0200

Я хотел бы выяснить, почему BS_jmpBoot и OEMName печатаются правильно, а BPB_BytesPerSec - нет. Если бы кто-нибудь мог просветить меня, я был бы очень признателен.

Спасибо

РЕДАКТИРОВАТЬ: Спасибо за помощь всем, это были мои типы, из-за которых все пошло наперекосяк. Я заставил его работать, записав байты в беззнаковое короткое замыкание, как предложил (своего рода) uesp, но мне все же хотелось бы знать, почему это не сработало:

            unsigned char BPB_BytesPerSec[2];
...
125         read (fd, BPB_BytesPerSec, 2);
126         printf("BPB_BytesPerSec = 0x%04x\n", *BPB_BytesPerSec);

получено BPB_BytesPerSec = 0x0000

Я хотел бы использовать массивы символов для выделения пространства, потому что я хочу быть уверенным в пространстве, в которое я пишу, на любой машине; или я не должен?

Спасибо еще раз!


person Kdawg    schedule 26.11.2014    source источник
comment
read (fd, BS_jmpBoot, 3); --››read (fd, BS_jmpBoot, 4); Кстати, ЧТО такое BS_jmpBoot ?   -  person wildplasser    schedule 27.11.2014
comment
@wildplasser - на древних гибких дисках загрузочный сектор мог содержать исполняемый код - для DOS это был бы 16-битный машинный код 8086. Это было запущено путем буквального прыжка в начало загрузочного сектора, когда он был в ОЗУ. Однако в начале загрузочного сектора есть зарезервированные поля, описывающие формат диска — примерно до 64 байтов из 512 в зависимости от версии DOS — поэтому первые три байта были зарезервированы для инструкции перехода к реальному исполняемому коду.   -  person Steve314    schedule 27.11.2014
comment
Я знаю, что (был там, делал это) я имел в виду отсутствие определения для BS_jmpBoot Но на самом деле (ИМХО правильный метод - прочитать полный 512-байтовый сектор за один проход, а затем выбрать правильные куски.   -  person wildplasser    schedule 27.11.2014
comment
@wildplasser - я предполагаю, что это уже для файлов изображений на гибких дисках, поэтому один из вариантов - использовать файлы с отображением в память, если вы не возражаете против кода для конкретной платформы. Лично у меня при чтении двоичных файлов есть библиотека, которая кэширует несколько блоков в фоновом режиме и предоставляет кучу методов peek_<type> — в основном для того, чтобы чтение файла, порядок следования байтов и подобные проблемы не загромождали синтаксический анализ.   -  person Steve314    schedule 27.11.2014


Ответы (2)


Вы BPB_BytesPerSec читаете неправильно. Структура Bpb (из здесь):

BYTE  BS_jmpBoot[3];
BYTE  BS_OEMName[8];
WORD  BPB_BytesPerSec;
...

Первые два поля являются байтами, поэтому их порядок байтов не имеет значения (я думаю). BPB_BytesPerSec - это СЛОВО (при условии, что 2 байта), поэтому вы должны определить/прочитать его следующим образом:

WORD BPB_BytesPerSec;            //Assuming WORD is defined on your system
read (fd, &BPB_BytesPerSec, 2);
printf("BPB_BytesPerSec = 0x%04x\n", BPB_BytesPerSec); 

Поскольку, когда вы читаете байты напрямую, вы получаете 00 02, что соответствует 0x0200 с прямым порядком байтов, вы должны правильно читать BPB_BytesPerSec вот так.

person uesp    schedule 26.11.2014

Прежде всего, эта строка:

printf("BPB_BytesPerSec = 0x%02x%02x\n",BPB_BytesPerSec[0], BPB_BytesPerSec[1]);

печатает значение в формате с обратным порядком байтов. Если он напечатает здесь 0x0002, фактическое значение будет 0x0200 с прямым порядком байтов.

Что касается значения BS_jmpBoot, согласно этому сайту:

Первые три байта EB 3C и 90 дизассемблируются в JMP SHORT 3C NOP. (Значение 3C может быть другим.) Причина этого заключается в переходе через информацию о формате диска (BPB и EBPB). Поскольку первый сектор диска загружается в оперативную память по адресу 0x0000:0x7c00 и выполняется, без этого перехода процессор попытается выполнить данные, не являющиеся кодом.

Другими словами, первые 3 байта — это коды операций, которые представляют собой три отдельных байта, а не одно значение с прямым порядком байтов.

person JS1    schedule 26.11.2014
comment
Байты для BS_jmpBoot правильные - для DOS либо E9 XX XX для 16-битного перехода, либо EB XX 90 для короткого перехода, за которым следует NOP, в любом случае переход к загрузочному коду. Однако, как говорит uesp, это поле представляет собой последовательность байтов (содержащую 16-битный машинный код x86) - порядок следования байтов не применяется. Прикрепление 0x перед выводом не означает, что последовательность байтов является чем-то другим, кроме последовательности байтов. Проблема с байтами на сектор заключается в том, что он не преобразует байты компонента обратно в одно значение - вот когда вы беспокоитесь о порядке байтов. - person Steve314; 27.11.2014
comment
Я прекрасно понимаю, в чем проблема. Я просто пытаюсь объяснить это самым простым способом. Наверное, я не очень хорошо объяснил. - person JS1; 27.11.2014
comment
Я не пытаюсь возражать, а лишь предлагаю возможные корректировки. - person Steve314; 27.11.2014