I am trying to read and display the disk geometry of a floppy in C. I was able to manage the first few entries (as far as I know of they're correct at least) such as:
Bytes per Sector
Sectors per Cluster
Reserved Sectors for the Boot Record
Number of FATS
My problem is I'm stuck at trying to figure out bit shifting for the rest of the geometry, which is what I was told to do in order to properly read in the values. I don't believe it's a problem with my code, but here is what I'm doing (SECTORSIZE is a const 512)::
void getSector(char *sector, int secNum, FILE *fp)
{
fseek(fp, (secNum*SECTORSIZE), SEEK_SET);
fread(sector, sizeof(char), SECTORSIZE, fp);
}
FILE *fp;
char sector[512];
unsigned int fileSize;
int i;
int diroffset;
char name[8];
name[0] = 0;
fp = fopen("floppy", "r");
//sector 0 contains the disk geometry
getSector(sector, 0, fp);
printf("Bytes per Sector: %d\n", (((unsigned int)sector[0x0c]) << 8u) | (unsigned int)sector[11]);
printf("Sectors per Cluster: %d\n", ((unsigned int)sector[0x0d] ));
printf("Reserved Sectors for the Boot Record: %d\n", (((unsigned int)sector[0x0f]) << 8u) | (unsigned int)sector[0x0e]);
printf("Number of FATS: %d\n", ((unsigned int)sector[0x10]));
//printf("Max # of Root Directory Entries: %d\n", (((unsigned int)sector[0x12]) << 8u) | (unsigned int)sector[0x11]);
//printf("Number of Sectors: %d\n", (((unsigned int)sector[12])) | (unsigned int)sector[11]);
//printf("Sectors per FAT: %d\n", ((unsigned int)sector[13] << 8u));
//printf("Sectors per Track: %d\n", (((unsigned int)sector[12]) << 8u) | (unsigned int)sector[11]);
//printf("Number of Surfaces: %d\n", (((unsigned int)sector[12]) << 8u) | (unsigned int)sector[11]);
The commented out sections are the parts where I'm still working on them. I pretty much just copied the first line and just changed the string name to match. The next one after number of FATS is the max # of root directories which is where I'm running into trouble. I have a list of the hex representation for each geometry location but the bit shifting is what's throwing me off.
However I am also noticing that when I'm displaying filenames I'm displaying an extra name of random characters. Below is how I'm finding filenames:
diroffset = 0;
while(diroffset <= 512) {
getSector(sector, 19, fp);
// print name of the file
if((void *) sector[0] != NULL)
for(i = 0; i < 8; i++)
name[i] = sector[diroffset + i];
if(name[0] != 0) {
printf("Filename: ");
for(i = 0; i < 8; i++)
printf("%c", name[i]);
putchar('\n');
}
name[0] = 0;
diroffset += 32;
}
It was my understanding that every 32 you would have a new filename, which it works as far as I know except displaying these characters as the last file found:
Filename: É·╬╩
I would like some more clarification on bit shifting in general, such as when and where to bit shift. I was trying to follow examples provided to me but maybe I'm just over complicating something and I'm not seeing it.
PS: If you're curious why I have so many unsigned int it's because my IDE complains otherwise when using bit operators
Related
maybe one of you can help me. I don't know what to do anymore. I have the following test code:
#include <stdio.h>
int main() {
unsigned int block = 0;
unsigned int alp = 0;
char *input ="test";
unsigned int *pt = NULL;
pt = (unsigned int*)input;
alp |= ((*pt) >> 8);
printf("pointer value:\t %d \n", alp);
for(int a = 0; a < 3; a++) {
block |= (unsigned char)input[a];
if(a != 2) {
block <<= 8;
}
}
printf("block value:\t %d \n", block);
return 0;
}
I would expect both values to be exactly the same, since they look at exactly 3 bytes. Only the values have a difference. Does anyone have an idea why this is the case or can explain me why?
pointer value: 7631717
block value: 7628147
Compiled with "gcc test.c -Wall -o test" (gcc (Ubuntu 12.2.0-3ubuntu1) 12.2.0)
Many thanks
The value of block is
(input[0] << 16) | (input[1] << 8) | (input[2]);
If you're on a little-endian system(which most people are), then the value of alp is
(input[3] << 16) | (input[2] << 8) | (input[1]);
There's nothing fishy going on. the different results are expected on a little-endian system. Your CPU reads the first byte as the least significant one and the last byte as the most significant one, but your for loop reads the first byte as the most significant one and the last byte as the least significant one.
More info on endianness
I'm not sure wheather my PC is trying to fool me or if I'm just to tired to find the bug. For hours and almost days I'm trying to write a bitmap file in pure C. I don't have any problems with the format or the padding, but the content.
Here's a MWE.
int main() {
FILE *file;
int w = 256;
int h = 15;
int pad = (4 - ((3 * w) % 4)) % 4;
int filesize = 54 + (3 * w + pad) * h;
// Create file header
unsigned char bmpfileheader[14] = { 'B','M', 0,0,0,0, 0,0, 0,0, 54,0,0,0 };
bmpfileheader[2] = (unsigned char)(filesize);
bmpfileheader[3] = (unsigned char)(filesize >> 8);
bmpfileheader[4] = (unsigned char)(filesize >> 16);
bmpfileheader[5] = (unsigned char)(filesize >> 24);
// Create Info Header
unsigned char bmpinfoheader[40] = { 40,0,0,0, 0,0,0,0, 0,0,0,0, 1,0, 24,0 };
bmpinfoheader[4] = (unsigned char)(w);
bmpinfoheader[5] = (unsigned char)(w >> 8);
bmpinfoheader[6] = (unsigned char)(w >> 16);
bmpinfoheader[7] = (unsigned char)(w >> 24);
bmpinfoheader[8] = (unsigned char)(h);
bmpinfoheader[9] = (unsigned char)(h >> 8);
bmpinfoheader[10] = (unsigned char)(h >> 16);
bmpinfoheader[11] = (unsigned char)(h >> 24);
// Create content
// Allocate memory dynamically
unsigned char *bmpcontent = (unsigned char *)calloc(filesize - 54, sizeof(unsigned char));
int index;
// map data values onto blue-red scale
for (int j = 0; j < h; j++)
{
for (int i = 0; i < w; i++)
{
index = 3 * i + (3 * w + pad) * j;
// blue
*(bmpcontent + index) = 255-i;
}
}
// Write to file
file = fopen("test.bmp", "w");
fwrite(bmpfileheader, sizeof(bmpfileheader[0]), 14, file);
fwrite(bmpinfoheader, sizeof(bmpinfoheader[0]), 40, file);
fwrite(bmpcontent, sizeof(bmpcontent[0]), filesize - 54, file);
fclose(file);
// free memory
free(bmpcontent);
return 0;
}
As I'm filling the 'blue-byte' of each pixel with 255-i I'm expecting to get a smooth fade from dark blue to black in each line. But I'm getting this:
example1
As you can see there is a byte-shift in each line which causes a change of color in each new line plus a pixel-shift after every third line. The curious thing is, that it only happens, when I'm trying to write a 13 into the file. Using a hex editor I found out, that a second 13 is written before the next value finds its way into the file. When I'm reducing the width to 240 (now the content of the bitmap varies between 14 and 255) I'm getting the smooth picture without any shifts: example2
You may say that it is pure coincidence that this fault appears while writing a 13 and it may be so. But I also tried to write data into the file where the 13 appeared at non-deterministic positions, and exactly the same effect occured.
I'm at my wits end, please help me!!!
It's because a value of 13 corresponds with a newline in Windows. Windows newlines are \r\n, which corresponds to hex 0D0A. Since you're trying to write 0D, it's treated as a newline, so it's getting written to the file as 0D0A. This is so that if you put only \n in a string, it will correctly be written as \r\n to a file. Thus, to fix this, you should make sure you're writing to the file in binary mode, which prevents this "feature" from writing the extra byte to the file. See here for more info: Strange 0x0D being added to my binary file
To use binary mode, just replace "w" with "wb" in your fopen, and it will work fine. I've verified this just now, and the output is correct:
On other platforms, this problem won't happen in the first place, so this fix will only work on, and is only needed for, Windows platforms.
This may be somewhat of an odd question as well as my first one ever on this site and a pretty complicated thing to ask basically I have this decompresser for a very specific archived file, I barely understand this but from what i can grasp its some sort of "bit mask" it reads the first 2 bytes out of target file, and stores them as a sequence.
The first for loop is where I get confused
Say for arguments sake mask is 2 bytes 10 04, or 1040(decimal) thats what it usually is in these files
for (t = 0; t<16; t++) {
if (mask & (1 << (15 - t))) {
This seems to be looping through all 16 bits of those 2 bytes and running an AND operation on mask (1040) on every bit?
The if statement is what I don't understand completely? Whats triggering the if? If the bit is greater then 0?
Because if mask is 1040, then really what were looking at is
if(1040 & 32768) index 15
if(1040 & 16384) index 14
if(1040 & 8192) index 13
if(1040 & 4096) index 12
if(1040 & 2048) index 11
if(1040 & 1024) index 10
if(1040 & 512) and so on.....
if(1040 & 256)
I just really need to know whats triggering this if statement? i think i might be over thinking it, but is it simply trigger if the current bit is greater then 0?
The only other thing i can do is compile this source myself, insert printfs on key variables and go hand in hand with a hex editor and try and figure out whats actually going on here, if anyone could give me a hand would be awesome.
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
uint8_t dest[1024 * 1024 * 4]; // holds the actual data
int main(int argc, char *argv[]) {
FILE *fi, *fo;
char fname[255];
uint16_t mask, tmp, offset, length;
uint16_t seq;
uint32_t dptr, sptr;
uint16_t l, ct;
uint16_t t, s;
int test_len;
int t_length, t_off;
// Print Usage if filename is missing
if (argc<3) {
printf("sld_unpack - Decompressor for .sld files ()\nsld_unpack <filename.sld> <filename.t2>\n");
return(-1);
}
// Open .SLD-file
if (!(fi = fopen(argv[1], "rb"))) {
printf("Error opening %s\n", argv[1]);
return(-1);
}
dptr = 0;
fread((uint16_t*)&seq, 1, 2, fi); // read 1st 2 bytes in file
test_len = ftell(fi);
printf("[Main Header sequence: %d]\n 'offset' : %d \n", seq, test_len);
sptr = 0;
fread((uint16_t*)&seq, 1, 2, fi);
while (!feof(fi)) { // while not at the end of the file set mask equal to sequence (first 2 bytes of header)
mask = seq;
// loop through 16 bit mask
for (t = 0; t<16; t++) {
if (mask & (1 << (15 - t))) { // check all bit fields and run AND check to if value greater then 0?
test_len = ftell(fi);
fread((uint16_t*)&seq, 1, 2, fi); // read
sptr = sptr + 2; // set from 0 to 2
tmp = seq; // set tmp to sequence
offset = ((uint32_t)tmp & 0x07ff) * 2;
length = ((tmp >> 11) & 0x1f) * 2; // 32 - 1?
if (length>0) {
for (l = 0; l<length; l++) {
dest[dptr] = dest[dptr - offset];
dptr++;
}
}
else { // if length == 0
t_length = ftell(fi);
fread((uint16_t*)&seq, 1, 2, fi);
sptr = sptr + 2;
length = seq * 2;
for (s = 0; s<length; s++) {
dest[dptr] = dest[dptr - offset];
dptr++;
}
}
}
else { // if sequence AND returns 0 (or less)?
fread((uint16_t*)&seq, 1, 2, fi);
t_length = ftell(fi);
sptr = sptr + 2;
dest[dptr++] = seq & 0xff;
dest[dptr++] = (seq >> 8) & 0xff;
}
}
fread((uint16_t*)&seq, 1, 2, fi);
}
fclose(fi);
sprintf(fname, "%s\0", argv[2]);
if (!(fo = fopen(fname, "wb"))) { // if file
printf("Error creating %s\n", fname);
return(-1);
}
fwrite((uint8_t*)&dest, 1, dptr, fo);
fclose(fo);
printf("Done.\n");
return(0);
}
Be careful here.
for arguments sake mask is 2 bytes 10 04, or 1040(decimal)
That assumption may be nowhere close to true. You need to show how mask is defined, but generally a mask of bytes 10 (00001010) and 40 (00101000) is binary 101000101000 or decimal (2600) not quite 1040.
The general mask of 2600 decimal will match when bits 4,6,10 & 12 are set. Remember a bit mask is nothing more than a number whose binary representation when anded or ored with a second number produces some desired result. Nothing magic about a bit mask, its just a number with the right bits set for your intended purpose.
When you and two numbers together and test, your are testing whether there are common bits set in both numbers. Using the for loop and shift, you are doing a bitwise test for which common bits are set. Using the mask of 2600 with the loop counter will test true when bits 4,6,10 & 12 are set. In other words when the test clause equals 8, 32, 512 or 2048.
The following is a short example of what is happening in the loop and if statements.
#include <stdio.h>
/* BUILD_64 */
#if defined(__LP64__) || defined(_LP64)
# define BUILD_64 1
#endif
/* BITS_PER_LONG */
#ifdef BUILD_64
# define BITS_PER_LONG 64
#else
# define BITS_PER_LONG 32
#endif
/* CHAR_BIT */
#ifndef CHAR_BIT
# define CHAR_BIT 8
#endif
char *binpad (unsigned long n, size_t sz);
int main (void) {
unsigned short t, mask;
mask = (10 << 8) | 40;
printf ("\n mask : %s (%hu)\n\n",
binpad (mask, sizeof mask * CHAR_BIT), mask);
for (t = 0; t<16; t++)
if (mask & (1 << (15 - t)))
printf (" t %2hu : %s (%hu)\n", t,
binpad (mask & (1 << (15 - t)), sizeof mask * CHAR_BIT),
mask & (1 << (15 - t)));
return 0;
}
/** returns pointer to binary representation of 'n' zero padded to 'sz'.
* returns pointer to string contianing binary representation of
* unsigned 64-bit (or less ) value zero padded to 'sz' digits.
*/
char *binpad (unsigned long n, size_t sz)
{
static char s[BITS_PER_LONG + 1] = {0};
char *p = s + BITS_PER_LONG;
register size_t i;
for (i = 0; i < sz; i++)
*--p = (n>>i & 1) ? '1' : '0';
return p;
}
Output
$ ./bin/bitmask1040
mask : 0000101000101000 (2600)
t 4 : 0000100000000000 (2048)
t 6 : 0000001000000000 (512)
t 10 : 0000000000100000 (32)
t 12 : 0000000000001000 (8)
The if statement is what I don't understand completely? Whats triggering the if? If the bit is greater then 0? ... I just really need to know whats triggering this if statement? i think i might be over thinking it, but is it simply trigger if the current bit is greater then 0?
The C (and C++) if statement "triggers" when the conditional statement evaluates to true, which is any non-zero value; zero equates to false.
Straight C doesn't have a Boolean type, it just use the convention of zero (0) is false, and any other value is true.
if (mask & (1 << (15 - t))) {...}
is the same as
if ((mask & (1 << (15 - t))) != 0) {...}
The expression you gave is only true (non-zero) when there is a bit in the mask in the same position that the 1 was shifted by. i.e. is the 15th bit in the mask set, etc.
N.b.
mask & (1 << (15 - t))
can only ever be 0 or 1 er... will only have one bit set.
I have a buffer of bits with 8 bits of data followed by 1 parity bit. This pattern repeats itself. The buffer is currently stored as an array of octets.
Example (p are parity bits):
0001 0001 p000 0100 0p00 0001 00p01 1100 ...
should become
0001 0001 0000 1000 0000 0100 0111 00 ...
Basically, I need to strip of every ninth bit to just obtain the data bits. How can I achieve this?
This is related to another question asked here sometime back.
This is on a 32 bit machine so the solution to the related question may not be applicable. The maximum possible number of bits is 45 i.e. 5 data octets
This is what I have tried so far. I have created a "boolean" array and added the bits into the array based on the the bitset of the octet. I then look at every ninth index of the array and through it away. Then move the remaining array down one index. Then I've got only the data bits left. I was thinking there may be better ways of doing this.
Your idea of having an array of bits is good. Just implement the array of bits by a 32-bit number (buffer).
To remove a bit from the middle of the buffer:
void remove_bit(uint32_t* buffer, int* occupancy, int pos)
{
assert(*occupancy > 0);
uint32_t high_half = *buffer >> pos >> 1;
uint32_t low_half = *buffer << (32 - pos) >> (32 - pos);
*buffer = high_half | low_half;
--*occupancy;
}
To add a byte to the buffer:
void add_byte(uint32_t* buffer, int* occupancy, uint8_t byte)
{
assert(*occupancy <= 24);
*buffer = (*buffer << 8) | byte;
*occupancy += 8;
}
To remove a byte from the buffer:
uint8_t remove_byte(uint32_t* buffer, int* occupancy)
{
uint8_t result = *buffer >> (*occupancy - 8);
assert(*occupancy >= 8);
*occupancy -= 8;
return result;
}
You will have to arrange the calls so that the buffer never overflows. For example:
buffer = 0;
occupancy = 0;
add_byte(buffer, occupancy, *input++);
add_byte(buffer, occupancy, *input++);
remove_bit(buffer, occupancy, 7);
*output++ = remove_byte(buffer, occupancy);
add_byte(buffer, occupancy, *input++);
remove_bit(buffer, occupancy, 6);
*output++ = remove_byte(buffer, occupancy);
... (there are only 6 input bytes, so this should be easy)
In pseudo-code (since you're not providing any proof you've tried something), I would probably do it like this, for simplicity:
View the data (with parity bits included) as a stream of bits
While there are bits left to read:
Read the next 8 bits
Write to the output
Read one more bit, and discard it
This "lifts you up" from worrying about reading bytes, which no longer is a useful operation since your bytes are interleaved with bits you want to discard.
I have written helper functions to read unaligned bit buffers (this was for AVC streams, see original source here). The code itself is GPL, I'm pasting interesting (modified) bits here.
typedef struct bit_buffer_ {
uint8_t * start;
size_t size;
uint8_t * current;
uint8_t read_bits;
} bit_buffer;
/* reads one bit and returns its value as a 8-bit integer */
uint8_t get_bit(bit_buffer * bb) {
uint8_t ret;
ret = (*(bb->current) >> (7 - bb->read_bits)) & 0x1;
if (bb->read_bits == 7) {
bb->read_bits = 0;
bb->current++;
}
else {
bb->read_bits++;
}
return ret;
}
/* reads up to 32 bits and returns the value as a 32-bit integer */
uint32_t get_bits(bit_buffer * bb, size_t nbits) {
uint32_t i, ret;
ret = 0;
for (i = 0; i < nbits; i++) {
ret = (ret << 1) + get_bit(bb);
}
return ret;
}
You can use the structure like this:
uint_8 * buffer;
size_t buffer_size;
/* assumes buffer points to your data */
bit_buffer bb;
bb.start = buffer;
bb.size = buffer_size;
bb.current = buffer;
bb.read_bits = 0;
uint32_t value = get_bits(&bb, 8);
uint8_t parity = get_bit(&bb);
uint32_t value2 = get_bits(&bb, 8);
uint8_t parity2 = get_bit(&bb);
/* etc */
I must stress that this code is quite perfectible, proper bound checking must be implemented, but it works fine in my use-case.
I leave it as an exercise to you to implement a proper bit buffer reader using this for inspiration.
This also works
void RemoveParity(unsigned char buffer[], int size)
{
int offset = 0;
int j = 0;
for(int i = 1; i + j < size; i++)
{
if (offset == 0)
{
printf("%u\n", buffer[i + j - 1]);
}
else
{
unsigned char left = buffer[i + j - 1] << offset;
unsigned char right = buffer[i + j] >> (8 - offset);
printf("%u\n", (unsigned char)(left | right));
}
offset++;
if (offset == 8)
{
offset = 0;
j++; // advance buffer (8 parity bit consumed)
}
}
}
I have a protocol that requires a length field up to 32-bits, and it must be
generated at runtime to describe how many bytes are in a given packet.
The code below is kind of ugly but I am wondering if this can be refactored to
be slightly more efficient or easily understandable. The problem is that the
code will only generate enough bytes to describe the length of the packet, so
less than 255 bytes = 1 byte of length, less than 65535 = 2 bytes of length
etc...
{
extern char byte_stream[];
int bytes = offset_in_packet;
int n = length_of_packet;
/* Under 4 billion, so this can be represented in 32 bits. */
int t;
/* 32-bit number used for temporary storage. */
/* These are the bytes we will break up n into. */
unsigned char first, second, third, fourth;
t = n & 0xFF000000;
/* We have used AND to "mask out" the first byte of the number. */
/* The only bits which can be on in t are the first 8 bits. */
first = t >> 24;
if (t) {
printf("byte 1: 0x%02x\n",first );
byte_stream[bytes] = first; bytes++;
write_zeros = 1;
}
/* Now we shift t so that it is between 0 and 255. This is the first, highest byte of n. */
t = n & 0x00FF0000;
second = t >> 16;
if (t || write_zeros) {
printf("byte 2: 0x%02x\n", second );
byte_stream[bytes] = second; bytes++;
write_zeros = 1;
}
t = n & 0x0000FF00;
third = t >> 8;
if ( t || write_zeros) {
printf("byte 3: 0x%02x\n", third );
byte_stream[bytes] = third; bytes++;
write_zeros = 1;
}
t = n & 0x000000FF;
fourth = t;
if (t || write_zeros) {
printf("byte 4: 0x%02x\n", fourth);
byte_stream[bytes] = fourth; bytes++;
}
}
You should really use a fixed-width field for your length.
When the program on the receiving end has to read the length field of your packet, how does it know where the length stops?
If the length of a packet can potentially reach 4 GB, does a 1-3 byte overhead really matter?
Do you see how complex your code has already become?
Really you're only doing four calculations, so readability seems way more important here than efficiency. My approach to make something like this more readable is to
Extract common code to a function
Put similar calculations together to make the patterns more obvious
Get rid of the intermediate variable print_zeroes and be explicit about the cases in which you output bytes even if they're zero (i.e. the preceding byte was non-zero)
I've changed the random code block into a function and changed a few variables (underscores are giving me trouble in the markdown preview screen). I've also assumed that bytes is being passed in, and that whoever is passing it in will pass us a pointer so we can modify it.
Here's the code:
/* append byte b to stream, increment index */
/* really needs to check length of stream before appending */
void output( int i, unsigned char b, char stream[], int *index )
{
printf("byte %d: 0x%02x\n", i, b);
stream[(*index)++] = b;
}
void answer( char bytestream[], unsigned int *bytes, unsigned int n)
{
/* mask out four bytes from word n */
first = (n & 0xFF000000) >> 24;
second = (n & 0x00FF0000) >> 16;
third = (n & 0x0000FF00) >> 8;
fourth = (n & 0x000000FF) >> 0;
/* conditionally output each byte starting with the */
/* first non-zero byte */
if (first)
output( 1, first, bytestream, bytes);
if (first || second)
output( 2, second, bytestream, bytes);
if (first || second || third)
output( 3, third, bytestream, bytes);
if (first || second || third || fourth)
output( 4, fourth, bytestream, bytes);
}
Ever so slightly more efficient, and maybe easier to understand would be this modification to the last four if statements:
if (n>0x00FFFFFF)
output( 1, first, bytestream, bytes);
if (n>0x0000FFFF)
output( 2, second, bytestream, bytes);
if (n>0x000000FF)
output( 3, third, bytestream, bytes);
if (1)
output( 4, fourth, bytestream, bytes);
I agree, however, that compressing this field makes the receiving state machine overly complicated. But if you can't change the protocol, this code is much easier to read.
Try this loop:
{
extern char byte_stream[];
int bytes = offset_in_packet;
int n = length_of_packet; /* Under 4 billion, so this can be represented in 32 bits. */
int t; /* 32-bit number used for temporary storage. */
int i;
unsigned char curByte;
for (i = 0; i < 4; i++) {
t = n & (0xFF000000 >> (i * 16));
curByte = t >> (24 - (i * 8));
if (t || write_zeros) {
printf("byte %d: 0x%02x\n", i, curByte );
byte_stream[bytes] = curByte;
bytes++;
write_zeros = 1;
}
}
}
I'm not sure I understand your question. What exactly are you trying to count? If I understand correctly you're trying to find the Most Significant non-zero byte.
You're probably better off using a loop like this:
int i;
int write_zeros = 0;
for (i = 3; i >=0 ; --i) {
t = (n >> (8 * i)) & 0xff;
if (t || write_zeros) {
write_zeros = 1;
printf ("byte %d : 0x%02x\n", 4-i, t);
byte_stream[bytes++] = t;
}
}