我正在尝试在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
[用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-bytes
)sizeof (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:请勿向外壳返回负值,而应返回1
或EXIT_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个值)
仔细检查,如果还有其他问题,请告诉我。