Reputation: 2062
Hey currently i have to do some exercises for a class but I am stuck. I am a bloody beginner in C and have to write a vm.
I am trying to read a .bin file to get information like format, version, amount of instructions ...
thats my code
FILE *inputFile;
char *charBuffer;
int *intBuffer;
long filelen;
char *inputPath = argv[i + 1];
inputFile = fopen(inputPath, "r");
fseek(inputFile, 0, SEEK_END);
filelen = ftell(inputFile);
rewind(inputFile);
charBuffer = (char *)malloc((filelen+1)*sizeof(char));
intBuffer = (int *)malloc((filelen+1)*sizeof(int));
fread(charBuffer, sizeof(char), 4, inputFile);
char *format = charBuffer;
printf("format: %s\n", format);
fread(intBuffer, sizeof(int), 1, inputFile);
int *version = intBuffer;
printf("version: %ls\n", version);
fread(intBuffer, sizeof(int), 1, inputFile);
int *instructionCount = intBuffer;
printf("instruction Count: %ls\n", instructionCount);
fread(intBuffer, sizeof(int), 1, inputFile);
int *variables = intBuffer;
printf("variable Count: %ls\n", variables);
and that is the output:
NJBF is correct but I was expected a 2 for version. Why is that such a weird cube with numbers in it? Why are Instructions and variables empty?
Unfortunately the class is only once per week and I cannot ask the instructor.
Thats what is in the test1.bin
opened with hexdump
00000000 4e 4a 42 46 02 00 00 00 0b 00 00 00 00 00 00 00 |NJBF............|
00000010 03 00 00 01 04 00 00 01 00 00 00 02 0a 00 00 01 |................|
00000020 06 00 00 01 00 00 00 03 00 00 00 04 00 00 00 08 |................|
00000030 0a 00 00 01 00 00 00 0a 00 00 00 00 |............|
0000003c
These are the rules:
4 bytes 'N', 'J', 'B', 'F' (identifies the format)
4 bytes version number (must match the VM's version number)
4 bytes number of instructions contained in the file
4 bytes number of variables in the static data area
n * 4 bytes instructions (the program to be executed)
Upvotes: 1
Views: 76
Reputation: 16910
I would probably start with something like this
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
typedef struct
{
char format[5];
uint32_t version;
uint32_t instruction_count;
uint32_t variable_count;
uint32_t *instructions;
} VmInfo;
uint32_t
u32_from_LE_bytes(const uint8_t *bytes)
{
return (((uint32_t)bytes[0])<< 0)|
(((uint32_t)bytes[1])<< 8)|
(((uint32_t)bytes[2])<<16)|
(((uint32_t)bytes[3])<<24);
}
bool // success
load_VmInfo(VmInfo *out_info,
const char *filename)
{
FILE *input=fopen(filename, "rb");
if(!input)
{
return false;
}
uint8_t raw_header[16];
if(fread(raw_header, sizeof(raw_header), 1, input)!=1)
{
fclose(input);
return false;
}
memcpy(out_info->format, raw_header, 4);
out_info->format[4]='\0';
out_info->version=u32_from_LE_bytes(raw_header+4);
out_info->instruction_count=u32_from_LE_bytes(raw_header+8);
out_info->variable_count=u32_from_LE_bytes(raw_header+12);
const size_t amount=out_info->instruction_count*sizeof(uint32_t);
out_info->instructions=(uint32_t *)malloc(amount);
if(!out_info->instructions)
{
abort();
}
if(fread(out_info->instructions, amount, 1, input)!=1)
{
fclose(input);
free(out_info->instructions);
return false;
}
for(uint32_t i=0; i<out_info->instruction_count; ++i)
{
const uint8_t *bytes=(const uint8_t *)out_info->instructions+i;
out_info->instructions[i]=u32_from_LE_bytes(bytes);
}
fclose(input);
return true;
}
int
main(void)
{
VmInfo info;
if(!load_VmInfo(&info, "test1.bin"))
{
fprintf(stderr,"bad VM file\n");
return 1;
}
printf("format: %s\n", info.format);
printf("version: %u\n", info.version);
printf("instruction_count: %u\n", info.instruction_count);
printf("variable_count: %u\n", info.variable_count);
for(uint32_t i=0; i<info.instruction_count; ++i)
{
printf(" %u\n", info.instructions[i]);
}
free(info.instructions);
return 0;
}
Oops, sorry I'm a bit late, I didn't see the accepted answer while I was writing.
Upvotes: 1
Reputation: 2039
It looks like you're trying to print integer data as a char with this line:
printf("version: %ls\n", version);
Because the data (an integer) can't be represented as an ASCII character, your terminal outputs the weird cube.
Try:
printf("version: %d\n", *version);
This should de-reference your integer pointer, and print it as a "raw" integer.
Upvotes: 1
Reputation: 781833
The version number is an int
, not a string. You need to use %d
format, and dereference the pointer.
printf("version: %d\n", *intBuffer);
You also need to add a null terminator to charBuffer
before using %s
to print.
fread(charBuffer, sizeof(char), 4, inputFile);
charBuffer[4] = 0;
printf("Format: %s\n", charBuffer);
Upvotes: 2