Home > Mobile >  Union in another function reading the wrong memory location
Union in another function reading the wrong memory location

Time:06-06

#include <stdio.h>
#include <string.h>
enum ACTION {RD = 0 , WR = 1};
enum SIZE {B = 1, W = 2};

union memory{//Memory union since space is limited
    unsigned char byte[0x10000];
    unsigned short word[0x8000];
};
union word_byte{//Ability to access either a word or byte and save memory space
    unsigned short word;
    unsigned char byte[2];
};

void bus(unsigned short, unsigned short* , enum ACTION, enum SIZE);


void print(unsigned short, unsigned short*);

int main() {
    FILE* file;
    enum ACTION act;
    enum SIZE sz;;
    unsigned short addr, idata;
    char rdwr[256], wb[256];
    file = fopen("test.txt", "r");
    while (fscanf(file,"%hx %hx %s %s", &addr, &idata, rdwr, wb) != EOF)
    {
        printf("%x %x %s %s\n", addr, idata, rdwr, wb);//Read in address and byte
        if(*rdwr == 'R')//If it is reading
        {
            act = RD;
        }
        else// else writing
        {
            act = WR;
        }
        if(*wb == 'B')//If byte
        {
            sz = B;
        }
        else//Else word
        {
            sz = W;
        }

        if(act == RD && sz == W)//If read and word must execute an insturction since removed the execution but still prints byte locations
        {
            bus(addr, &idata, act, sz);
            print(addr, &idata);
        }else//Just send it to the bus to be written into union memory
        {
            bus(addr, &idata, act, sz);
        }
    }

    return 0;
}
/*
BUS function description
MAR is the address and *mbr is the data being either read or written with enums for selection
The bus function is used to access memory for this problem and allows for the reading or writing
of a byte or word
*/
void bus(unsigned short mar, unsigned short *mbr, enum ACTION rw, enum SIZE bw){
    union memory mem;
    if(rw == 0)
    {
        if(bw == 1)
        {
            *mbr = mem.byte[mar];
            printf("READ BYTE:%hx\n", *mbr);
        
        }
        else
        {
            mar = mar>>1;
            *mbr = (mem.word[mar] << 8) | (mem.word[mar 1]);
            printf("READ WORD: %hx\n", *mbr);
        }
    }
    else
    {
        if(bw == 1)
        {
            printf("MAR %hx, MBR %hx\n", mar, *mbr);
            mem.byte[mar] = *mbr & 0xFF;
            printf("Byte Write: %hx\n", mem.byte[mar]);
        }
        else
        {
            mar = mar >> 1;
            printf("MAR %hx, MBR %hx\n", mar, *mbr);
            mem.word[mar] = *mbr & 0xFF;
            printf("%hx Word Write: %hx\n",mar,  mem.word[mar]);
        }
    }
}
/*
PRINT function below description
Function for later on to manipulate memory and access it 
I do not understand where the extra 0x10 addition is coming into play?
*/
void print(unsigned short mar, unsigned short *mbr)
{
    union memory mem;
    int j = 0, k = 0;

        for(j = 0; j<=0xFF; j  )//For printing low address to check where the byte actually is.
            {
                
                *mbr = mem.byte[j];
                if(*mbr == 0)
                {
                    printf("");
                }else
                {
                    printf("j: %hx *MBR: %hx\n",j, *mbr);
                }
                
            }
}
    

Input file test.txt

007F AB W B
0080 CD W B
3005 94 W W 
3006 01 W W
3005 0 R W
007F 0 R B

Output in cmd

7f ab W B
MAR 7f, MBR ab
Byte Write: ab
80 cd W B
MAR 80, MBR cd
Byte Write: cd
3005 94 W W
MAR 1802, MBR 94
1802 Word Write: 94
3006 1 W W
MAR 1803, MBR 1
1803 Word Write: 1
3005 0 R W
READ WORD: 9401
j: 8 *MBR: 2
j: 8f *MBR: ab
j: 90 *MBR: cd
7f 0 R B
READ BYTE:ab

I posted this last night, but realize I can compact it to find my error. The program is for a class that my task is to read an address and data in along with two commands. The first command dictate whether the data should be read or written (R or W), while the second command dictates if the data is a word or byte (W or B). This all gets passed to the bus function which should write to memory. If there happens to be a R and W (read word) the program should execute an instruction. I haven't gotten that far due to a specific error in my unions so for now I just print the memory locations of the bytes. As seen by my input I specify the byte AB should be at the memory location 007F or 7F since the compiler doesn't print the 00. Later on when calling my print function I print out all memory locations rangining from 00 to FF in a attempt to now find where the byte AB is in memory. To my suprise it is at 8F which is 0x10 more then what I specified it to be written as. Yet when I do a read word in the bus function as shown in the last line of the input it reads the byte at 7f? Does the memory increase happen due to another call of the union memory in the function print? If more info is needed I would be happy to help.

Please ignore k:8 *MBR: 2 that is a random memory location not zeroed in my system!

Thanks!

CodePudding user response:

The line

union memory mem;

in the function bus and print will allocate a local array with the size of 64 KiB.

Since it is a non-static local array, the lifetime of this array is only as long as the function in which it is declared. Therefore, the functions bus and print are not using the same array.

The simplest fix to this problem would be to remove both declarations and to declare the array as a global variable instead, like this:

union memory{//Memory union since space is limited
    unsigned char byte[0x10000];
    unsigned short word[0x8000];
} mem;

That way, all functions would be using the same array when they use the identifier mem.

Alternatively, you could declare the array as a local array in main and pass a pointer to the array as an additional parameter whenever you call the functions bus and print. This is generally considered better programming style than using global variables.

Further issues:

You should check the return value of fopen and print an error message and terminate the program if it fails, for example like this:

file = fopen("test.txt", "r");
if ( file == NULL )
{
    fprintf( stderr, "Error opening file!\n" );
    exit( EXIT_FAILURE );
}

Note that you will have to #include <stdlib.h> in order to use the function exit.

The line

while (fscanf(file,"%hx %hx %s %s", &addr, &idata, rdwr, wb) != EOF)

should probably be changed to

while ( fscanf(file,"%hx %hx %s %s", &addr, &idata, rdwr, wb) == 4 )

because you probably want to stop if not all arguments could be matched.

  • Related