将二进制文件读入全局无符号整数

问题描述 投票:0回答:1

我正在尝试在C中启动VM,并且我正在尝试了解如何读取由汇编程序生成的二进制文件ive。根据分配指令,我们将全局内存分配为1k内存空间的无符号字节,然后使用加载功能将该二进制文件读取到内存中,然后使用获取功能将这些字节读取到它们的指令中。我遇到的问题是第1部分,如何将这个二进制文件读入这个无符号的int数组,然后以一种可以使用的方式对其进行解码?目前,我所打印的值根本不符合预期。

MAIN.c

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>

unsigned int memory[1028];

int loads(char *filename){
     FILE *file = fopen(filename, "r");
     ssize_t read;
     if(file == NULL){
         exit(-1);
     }

     while(fread(&memory, sizeof(unsigned int), 1, file) == 1){
         printf("%d\n", *memory);
     }
    fclose(file);
    exit(0);
}

int main(int argc, char** argv){
    if (argc <= 1){
        printf("No file found\n");
        return -1;
    }

    char *filename = argv[1];

    loads(filename);
}

inputfile.txt

t @ w @#(这是不可读的内容,但是当使用od -t x1 output.txt | head -5时,它打印为0000000 74 40 77 40 11 23 0000006)]

当前输出1081557108

所需输出74 40 77 40 11 23

c binaryfiles
1个回答
1
投票

[用fread读取时,fread读取字节。它不知道线的任何概念。字节'\n'0xa)与文件中的其他字节一样,都是字节。 fread的声明为:

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

ptr是足以容纳size * nmemb中的stream(大小*成员数)值的内存块的起始地址。其中size是元素或对象的大小(在您的情况下为sizeof (unsigned)nmemb是将要读取的数字(例如,在1028情况下为unsigned memory[1028];))请参阅man 3 fread

您的代码有问题的地方是您使用&memory作为指针。那是不对的。 (以及为什么要获得2个值)&memory的类型为unsigned (*)[1028](例如pointer-to-array-of unsigned[1028]sizeof(unsigned)是什么? (提示:4-bytessizeof (a_pointer)是什么? (提示:x86_64上的8-bytes)。因此,您可以在读取的其余部分调用Undefined Behavior的同时,将2个无符号值存储在指针的存储中。

fread的正确参数就是memory,它作为数组被转换为访问时的指针,但要遵循C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3)中列出的四个异常

在您的情况下,您将无符号数组memory声明为:

#define MAXU 1028   /* if you need a constant, #define one (or more) */

unsigned memory[MAXU];

(<< [note:除非绝对必要,否则要避免使用global变量。相反,请在所需范围内声明数组,例如在main()中,然后将指针传递给其中这是必需的)

[处理文件时,不要将文件名作为参数传递给函数,而应打开文件并确认它在调用方中处于打开状态(此处为main()),然后将打开的FILE*指针作为参数传递。除非可以打开该文件,否则无需进行函数调用并开始设置函数堆栈。因此,在main()中,您可以执行以下操作,将文件名作为第一个参数传递给程序,例如

int main(int argc, char **argv) { int n = 0; if (argc < 2) { /* validate at least 1 argument given for filename */ fprintf (stderr, "usage: %s filename\n", argv[0]); return 1; /* do NOT return negative values to the shell */ } /* use filename provided as 1st argument */ FILE *fp = fopen (argv[1], "r"); if (!fp) { /* validate file open for reading */ perror ("file open failed"); return 1; }

(<< [note:请勿向外壳返回负值,而应返回1EXIT_FAILURE(其值为1)以指示错误)

现在您要通过打开的文件流loads来调用fp函数,例如

if ((n = loads (fp)) == 0) { /* validate return of loads */ fputs ("error: loads() read zero bytes or error occurred.\n", stderr); return 1; }

您的loads()功能减少为:

int loads (FILE *fp)
{
    return fread (memory, sizeof *memory, MAXU, fp);
}

note: fread返回读取的成员数,仅等于size == 1时读取的字节数。因此,通过选择unsigned的大小,它将返回[ C0]值读取)。

完整的示例可能是:

unsigned

示例使用/输出

在我的文件#include <stdio.h> #include <stdlib.h> #define MAXU 1028 /* if you need a constant, #define one (or more) */ unsigned memory[MAXU]; int loads (FILE *fp) { return fread (memory, sizeof *memory, MAXU, fp); } int main(int argc, char **argv) { int n = 0; if (argc < 2) { /* validate at least 1 argument given for filename */ fprintf (stderr, "usage: %s filename\n", argv[0]); return 1; /* do NOT return negative values to the shell */ } /* use filename provided as 1st argument */ FILE *fp = fopen (argv[1], "r"); if (!fp) { /* validate file open for reading */ perror ("file open failed"); return 1; } if ((n = loads (fp)) == 0) { /* validate return of loads */ fputs ("error: loads() read zero bytes or error occurred.\n", stderr); return 1; } for (int i = 0; i < n; i++) { /* loop n times outputting values */ if (i && i % 10 == 0) /* output 10 columns for convenience */ putchar ('\n'); printf (" %4x", memory[i] & 0xffff); /* & 0xffff is for my file */ } putchar ('\n'); /* tidy up with newline */ } 中,我有100,000个整数值(在../dat/100000int.bin范围内为正和负,因此我用short屏蔽了每个值的高2个字节,以防止符号扩展

当存储的值小于零时,输​​出为无符号值,例如memory[i] & 0xffff

0xffff7d77(这是103行输出,每行10个值,最后一行8个值)

仔细检查,如果还有其他问题,请告诉我。
© www.soinside.com 2019 - 2024. All rights reserved.