C FAT-BPB与小端反转
我的CPU是little endian,文档告诉我它符合FAT规范的字节顺序。那么,为什么我得到的是第一个扇区的字节0-3的有效地址,而不是第一个扇区的字节11-12的有效地址C FAT-BPB与小端反转,c,disk,endianness,fat,C,Disk,Endianness,Fat,我的CPU是little endian,文档告诉我它符合FAT规范的字节顺序。那么,为什么我得到的是第一个扇区的字节0-3的有效地址,而不是第一个扇区的字节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_jmpBoo
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
我想弄清楚为什么Bp_jmpBoot和OEMName打印有效,而Bp_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
我想使用字符数组来分配空间,因为我想确定我在任何机器上写入的空间;还是我不应该
再次感谢 首先,这一行:
printf("BPB_BytesPerSec = 0x%02x%02x\n",BPB_BytesPerSec[0], BPB_BytesPerSec[1]);
正在以big-endian格式打印值。如果它在这里打印0x0002
,实际值将是0x0200
,以小尾端为单位
至于BS_jmpBoot
值,根据:
前三个字节eb3c和90反汇编为JMP SHORT 3C NOP。(3C值可能不同。)其原因是跳过磁盘格式信息(BPB和EBPB)。由于磁盘的第一个扇区加载到位置0x0000:0x7c00处的ram中并执行,如果没有此跳转,处理器将尝试执行非代码的数据
换句话说,前3个字节是操作码,它们是三个独立的字节,而不是一个小的endian值。您错误地读取了
BPB_bytespercc
。Bpb的结构是(来自):
前两个字段是字节,所以它们的尾数是不相关的(我认为)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);
因为当你直接读取字节时,你会得到
0002
,在little endian中是0x0200
,你应该像这样正确地读取BPB_bytespercc
。read(fd,BS_jmpBoot,3)代码>-->读取(fd,BS_jmpBoot,4)代码>顺便说一句,什么是BS_jmpBoot
?@wildplasser-在古老的软盘中,引导扇区可能包含可执行代码-用于DOS的代码为16位8086机器代码。一旦进入RAM,就直接跳到启动扇区的开始。然而,在引导扇区的开头有一些保留字段描述磁盘格式——根据DOS版本的不同,512个字节中最多有64个字节——因此前三个字节是为跳转指令保留的,用于真正的可执行代码我指的是没有对BS_jmpBoot
的定义,但事实上(正确的方法是在一次扫描中读取完整的512字节扇区,然后选择正确的片段。@wildplasser-我想现在这是针对软盘映像文件的,所以如果您不介意平台特定的代码,一个选项是使用内存映射文件。就我个人而言,在读取二进制文件时,我有一个库,它在e background并提供了一系列peek
方法-主要用于防止文件读取、endian和类似问题干扰解析。BS_jmpBoot的字节是正确的-对于DOS,“E9 XX XX XX”表示16位跳转或“EB XX 90”对于后跟NOP的短跳转,无论哪种方式跳转到启动代码。但是,正如uesp所说,该字段是一个字节序列(包含16位x86机器代码)-endianness不适用。在输出前粘贴一个0x
,并不意味着字节序列不是字节序列。每个扇区的字节的问题是,他没有将组件字节转换回单个值-这就是你担心endianness的原因。我完全理解p问题是。我只是想用最简单的方式来解释。我可能没有很好地解释。我不是想反驳,只是建议可能的调整。
WORD BPB_BytesPerSec; //Assuming WORD is defined on your system
read (fd, &BPB_BytesPerSec, 2);
printf("BPB_BytesPerSec = 0x%04x\n", BPB_BytesPerSec);