从C中的二进制文件中获取32位指令

时间:2014-05-28 19:09:32

标签: c file 32-bit

我需要从二进制文件中读取32位指令。 所以我现在拥有的是:

unsigned char buffer[4];
fread(buffer,sizeof(buffer),1,file);

将在数组中放入4个字节

我该如何处理将这4个字节连接在一起以便以后处理32位指令? 或者我应该以不同的方式开始而不是使用fread?

我现在的奇怪方法是创建一个大小为32的整数数组,并用缓冲区数组中的位填充

4 个答案:

答案 0 :(得分:1)

添加

unsigned int instruction;
memcpy(&instruction,buffer,4);

代码。这会将4个字节的缓冲区复制到一个32位变量中。因此,您将连接4个字节:)

答案 1 :(得分:1)

答案取决于32位整数如何存储在二进制文件中。 (我假设整数是无符号的,因为它确实是一个id,并使用uint32_t中的<stdint.h>类型。)

本机字节顺序数据在此计算机上以整数形式写出。只需使用fread读取整数:

uint32_t op;

fread(&op, sizeof(op), 1, file);

基本原理:fread将整数的原始表示读入内存。匹配fwrite执行相反的操作:它将原始表示写入thze文件。如果您不需要在平台之间交换文件,这是存储和读取数据的好方法。

小端字节顺序数据存储为四个字节,最低有效字节优先:

uint32_t op = 0u;

op |= getc(file);            // 0x000000AA
op |= getc(file) << 8;       // 0x0000BBaa
op |= getc(file) << 16;      // 0x00CCbbaa
op |= getc(file) << 24;      // 0xDDccbbaa

基本原理:getc读取一个字符并返回0到255之间的整数。(流用完且getc返回负值EOF的情况不在此处考虑简洁,即懒惰。)通过将您读取的每个字节移动8的倍数和/或它们与现有值来构建您的整数。评论概述了它的工作原理。正在阅读大写字母,小写字母已经存在。 Zeros尚未被分配。

大端字节顺序数据存储为四个字节,最后一个字节为最后一个字节:

uint32_t op = 0u;

op |= getc(file) << 24;      // 0xAA000000
op |= getc(file) << 16;      // 0xaaBB0000
op |= getc(file) << 8;       // 0xaabbCC00
op |= getc(file);            // 0xaabbccDD

基本原理:与上面几乎相同,只是你以另一种顺序移动字节。

你可以想象little-endian和big-endian将第一百二十二棵树(CXXIII)写成321或123.比特移位类似于在除以或乘以10的幂时移位十进制数字。 ,只是你把我的8位移位乘以2 ^ 8 = 256这里。

答案 2 :(得分:0)

如果您知道文件中的int与程序运行的机器具有相同的endian,那么您可以直接读入int。不需要char缓冲区。

unsigned int instruction;
fread(&instruction,sizeof(instruction),1,file);

如果您知道文件中int的endianness,而不知道程序运行的机器的endianness,那么您需要添加并将字节移位到一起。

unsigned char buffer[4];
unsigned int instruction;
fread(buffer,sizeof(buffer),1,file);

//big-endian
instruction = (buffer[0]<<24) + (buffer[1]<<16) + (buffer[2]<<8) + buffer[3];

//little-endian
instruction = (buffer[3]<<24) + (buffer[2]<<16) + (buffer[1]<<8) + buffer[0];

另一种想到这一点的方法是它是一个基数为256的位置数系统。就像你在基数10中组合数字一样。

257 
= 2*100 + 5*10 + 7
= 2*10^2 + 5*10^1 + 7*10^0

所以你也可以使用Horner的规则来组合它们。

//big-endian
instruction = ((((buffer[0]*256) + buffer[1]*256) + buffer[2]*256) + buffer[3]);

//little-endian
instruction = ((((buffer[3]*256) + buffer[2]*256) + buffer[1]*256) + buffer[0]);

答案 3 :(得分:0)

@luser droog

您的代码中有两个错误。

变量“指令”的大小不得为4个字节:例如,Turbo C假定sizeof(int)为2。显然,在这种情况下,您的程序将失败。但是,更重要的是,不是那么显而易见:如果sizeof(int)超过4个字节,您的程序也会失败!要理解这一点,请考虑以下示例:

int main()
{   const unsigned char a[4] = {0x21,0x43,0x65,0x87};
    const unsigned char* p = &a;
    unsigned long x = (((((p[3] << 8) + p[2]) << 8) + p[1]) << 8) + p[0];
    printf("%08lX\n", x);
    return 0;
}

该程序在amd64下打印“ FFFFFFFF87654321”,因为使用时未签名的char变量将变为SIGNED INT!因此,将变量“指令”的类型从“ int”更改为“ long”并不能解决问题。

唯一的方法是编写如下内容:

unsigned long instruction;

instruction = 0;
for (int i = 0, unsigned char* p = buffer + 3; i < 4; i++, p--) {
    instruction <<= 8;
    instruction += *p;
}