Thread: Help on brookshear machine

  1. #1
    Registered User
    Join Date
    Oct 2012
    Posts
    14

    Question Help on brookshear machine

    Hi, I am trying to code a brookshear machine and I am getting weird results with my code.

    My Code:
    Code:
    #include <stdio.h>
    
    
    void display_values(unsigned int pc, unsigned char mem[], unsigned char reg[]);
    
    
    FILE *f;
    
    
    int main() {
        unsigned int pc = 0, i = 0, temp = 0;
        unsigned char reg[16], mem[256], a, b, c, d, cd;
        
        for(i = 0; i < sizeof(reg); i++) {
            reg[i] = 0x00;
        }
        
        for(i = 0; i < sizeof(mem); i++) {
            mem[i] = 0x00;
        }
        
        f = fopen("a3.txt", "r");
        if(f == NULL) {
            printf("Error: File not found!\n");
            return 0;
        }
        
        while(fscanf(f, "%X", &temp) != EOF) {
            mem[i] = (temp & 0xff00) >> 8;
            mem[i+1] = temp & 0xff;
            i+=2;
        }
        fclose(f);
        
        while(mem[pc] != 0xC0) {
            a = (mem[i] & 0xf0) >> 4;
            b = mem[i] & 0xf;
            c = (mem[i+1] & 0xf0) >> 4;
            d = mem[i+1] & 0xf;
            cd = mem[i+1];
            
            display_values(pc, mem, reg);
            
            if(a == 0x1) {
                // Load the register R with the value at memory address XY.
                reg[b] = mem[cd];
            }
            if(a == 0x2) {
                // Load register R with the value XY.
                reg[b] = cd;
            }
            if(a == 0x3) {
                // Store the value in register R at memory address XY.
                mem[cd] = reg[b];
            }
            if(a == 0x4) {
                // Move the value in register R to register S.
                reg[d] = reg[c];
                reg[c] = 0x00;
            }
            if(a == 0x5) {
                // Add(+) values in registers R and S and put the answer in register T.
                reg[d] = reg[b] + reg[c];
            }
            if(a == 0x7) {
                // Bit-wise OR(|) the values in registers R and S and put the answer in register T.
                reg[d] = reg[b] | reg[c];
            }
            if(a == 0x8) {
                // Bit-wise AND(&) the values in registers R and S and put the answer in register T.
                reg[d] = reg[b] & reg[c];
            }
            if(a == 0x9) {
                // Bit-wise XOR(^) the values in registers R and S and put the answer in register T.
                reg[d] = reg[b] ^ reg[c];
            }
            if(a == 0xA) {
                // Rotate the contents of register R X times to the right.
                reg[b] >>= 1;
                reg[b] = reg[b] | ((reg[b] & 0x1) << 31);
            }
            if(a == 0xB) {
                // Jump to the instruction located at memory address XY if register R = register 0.
                if(mem[b] == reg[0]) {
                    pc = cd;
                }
            }
            
            pc = pc + 2;
            
            display_values(pc, mem, reg);
        }
        
        return 0;
    }
    
    
    void display_values(unsigned int pc, unsigned char mem[], unsigned char reg[]) {    
        unsigned int i = 0;
        
        printf("%02X", pc);
        printf(" %02X%02X ", mem[pc], mem[pc+1]);
        for(i = 0; i < sizeof(reg); i++) {
            printf(" %02X ", reg[i]);
        }
        printf("\n");
    }
    I am reading from a text file that contains:
    B404
    239A
    2412
    5345
    350C
    C000
    The right result is:
    00 B404 – [00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00]
    04 2412 - [00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00]
    06 5345 - [00 00 00 00 12 00 00 00 00 00 00 00 00 00 00 00]
    08 350C - [00 00 00 00 12 12 00 00 00 00 00 00 00 00 00 00]
    0A C000 - [00 00 00 00 12 12 00 00 00 00 00 00 00 00 00 00]
    But I am getting: (Note: it started from 00...)
    Help on brookshear machine-brookshearerror-jpg


    Need help.
    Last edited by Warzaw; 04-22-2013 at 01:24 AM.

  2. #2
    Registered User
    Join Date
    May 2012
    Posts
    1,066
    Code:
    void display_values(unsigned int pc, unsigned char mem[], unsigned char reg[]) {    
        unsigned int i = 0;
        
        printf("%02X", pc);
        printf(" %02X%02X ", mem[pc], mem[pc+1]);
        for(i = 0; i < sizeof(reg); i++) {
            printf(" %02X ", reg[i]);
        }
        printf("\n");
    }
    "reg" is a pointer, thus sizeof(reg) gives you the size of a pointer. You need to pass the actual length of the array to your function.

    Bye, Andreas

  3. #3
    Registered User
    Join Date
    Oct 2012
    Posts
    14
    ok, i got the 16 registers to show now. but they are still all zeroes and the counter still runs from 00 to 108.

  4. #4
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    When reusing variables you have to reset then to sane values.
    set i to 0 before reading from the file.

    also
    Code:
        while(mem[pc] != 0xC0) {
            a = (mem[i] & 0xf0) >> 4;
            b = mem[i] & 0xf;
            c = (mem[i+1] & 0xf0) >> 4;
            d = mem[i+1] & 0xf;
            cd = mem[i+1];
    i never changes in that loop

    Kurt
    Last edited by ZuK; 04-22-2013 at 04:16 AM.

  5. #5
    Registered User
    Join Date
    May 2012
    Posts
    1,066
    Show us the new version.

    In the old one you don't reset "i" before the second while loop and never update "i" inside it.

    Bye, Andreas

  6. #6
    Registered User
    Join Date
    Oct 2012
    Posts
    14
    ok, here is the new code. Changes:
    • changed unsigned char to unsigned int
    • initialised all values
    • removed sizeof()
    • changed "i" to "pc" in while(mem[pc] != 0xC0) { ... }



    Code:
    #include <stdio.h>
    
    
    void display_values(unsigned int pc, unsigned int mem[], unsigned int reg[]);
    
    
    FILE *f;
    unsigned int size_mem = 256, size_reg = 16;
    
    
    int main() {
        unsigned int pc = 0, i = 0, temp = 0;
        unsigned int  a = 0, b = 0, c = 0, d = 0, cd = 0;
        unsigned int reg[size_reg], mem[size_mem];
        
        for(i = 0; i < size_reg; i++) {
            reg[i] = 0x00;
        }
        
        for(i = 0; i < size_mem; i++) {
            mem[i] = 0x00;
        }
        
        f = fopen("a3.txt", "r");
        if(f == NULL) {
            printf("Error: File not found!\n");
            return 0;
        }
        
        while(fscanf(f, "%X", &temp) != EOF) {
            mem[i] = (temp & 0xff00) >> 0x8;
            mem[i+1] = temp & 0xff;
            i += 2;
        }
        fclose(f);
        
        while(mem[pc] != 0xC0) {
            a = (mem[pc] & 0xf0) >> 0x4;
            b = mem[pc] & 0xf;
            c = (mem[pc+1] & 0xf0) >> 0x4;
            d = mem[pc+1] & 0xf;
            cd = mem[pc+1];
            
            if(a == 0x1) {
                // Load the register R with the value at memory address XY.
                reg[b] = mem[cd];
            }
            if(a == 0x2) {
                // Load register R with the value XY.
                reg[b] = cd;
            }
            if(a == 0x3) {
                // Store the value in register R at memory address XY.
                mem[cd] = reg[b];
            }
            if(a == 0x4) {
                // Move the value in register R to register S.
                reg[d] = reg[c];
                reg[c] = 0x00;
            }
            if(a == 0x5) {
                // Add(+) values in registers R and S and put the answer in register T.
                reg[d] = reg[b] + reg[c];
            }
            if(a == 0x7) {
                // Bit-wise OR(|) the values in registers R and S and put the answer in register T.
                reg[d] = reg[b] | reg[c];
            }
            if(a == 0x8) {
                // Bit-wise AND(&) the values in registers R and S and put the answer in register T.
                reg[d] = reg[b] & reg[c];
            }
            if(a == 0x9) {
                // Bit-wise XOR(^) the values in registers R and S and put the answer in register T.
                reg[d] = reg[b] ^ reg[c];
            }
            if(a == 0xA) {
                // Rotate the contents of register R X times to the right.
                reg[b] >>= 1;
                reg[b] = reg[b] | ((reg[b] & 0x1) << 31);
            }
            if(a == 0xB) {
                // Jump to the instruction located at memory address XY if register R = register 0.
                if(mem[b] == reg[0]) {
                    pc = cd;
                }
            }
            
            display_values(pc, mem, reg);
            
            pc += 2;
        }
        
        return 0;
    }
    
    
    void display_values(unsigned int pc, unsigned int mem[], unsigned int reg[]) {    
        unsigned int i = 0;
        
        printf("%02X", pc);
        printf(" %02X%02X - [", mem[pc], mem[pc+1]);
        for(i = 0; i < size_reg; i++) {
            printf(" %02X ", reg[i]);
        }
        printf("]\n");
    }

    ...and here is the new result:
    Help on brookshear machine-brookshearerror-jpg
    Last edited by Warzaw; 04-22-2013 at 04:41 AM.

  7. #7
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    All of the bit fiddling techniques in main(), and the magic hex values, mean that your code is assuming a particular endianness on your target machine. If your target machine is a different endianness, the results will not be what you expect.

    Looping until fscanf() returns EOF is not a good idea, as fscanf() can return values other than EOF when certain errors occur (such as a character that cannot be interpreted as a hex digit, in your case). When starting that loop, the value of i will also be equal to size_mem.

    If you want to set arrays to zero, it is often better to either initialise them that way or to use memcpy().
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  8. #8
    Registered User
    Join Date
    Oct 2012
    Posts
    14
    do you mean something like...

    Code:
    unsigned int reg[size_reg] = {0}, mem[size_mem] = {0};
    ...when initialising arrays?
    Last edited by Warzaw; 04-22-2013 at 05:08 AM.

  9. #9
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    That's one way.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  10. #10
    Registered User
    Join Date
    Oct 2012
    Posts
    14
    tried it and i am getting an error message saying "variable-sized object `reg' may not be initialized" and "variable-sized object `mem' may not be initialized" if i initialise the arrays to zero using that method.

  11. #11
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Oh, okay. That's because size_reg is a variable (and your arrays are therefore VLAs). Try making the sizes visible to the compiler at compile time (e.g. #define size_mem 256 or [slightly more devious] an enum trick), rather than as values of variables.

    If the sizes really must be variables, then use something like memcpy() or memset().
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  12. #12
    Registered User
    Join Date
    May 2012
    Posts
    1,066
    Quote Originally Posted by ZuK View Post
    When reusing variables you have to reset then to sane values.
    set i to 0 before reading from the file.
    Code:
        while(fscanf(f, "%X", &temp) != EOF) {
            mem[i] = (temp & 0xff00) >> 0x8;
            mem[i+1] = temp & 0xff;
            i += 2;
        }
    What's the value of "i" before you read the file?

    Bye, Andreas

  13. #13
    Registered User
    Join Date
    Oct 2012
    Posts
    14
    well, there are no requirements to have the array size as a variable...thats just me wanting to explore more functions.

    anyway, I have changed the code again to this:

    Code:
    #include <stdio.h>
    
    
    #define size_mem 256
    #define size_reg 16
    
    
    void display_values(unsigned int pc, unsigned int mem[], unsigned int reg[]);
    
    
    FILE *f;
    
    
    
    
    int main() {
    	unsigned int pc = 0, i = 0, temp = 0;
    	unsigned int a = 0, b = 0, c = 0, d = 0, cd = 0;
    	unsigned int reg[size_reg] = {0}, mem[size_mem] = {0};
    	
    	f = fopen("a3.txt", "r");
    	if(f == NULL) {
    		printf("Error: File not found!\n");
    		return 0;
    	}
    	
    	while(fscanf(f, "%X", &temp) != EOF) {
    		mem[i] = (temp & 0xff00) >> 0x8;
    		mem[i+1] = temp & 0xff;
    		i += 2;
    	}
    	fclose(f);
    	
    	while(mem[pc] != 0xC0) {
    		a = (mem[pc] & 0xf0) >> 0x4;
    		b = mem[pc] & 0xf;
    		c = (mem[pc+1] & 0xf0) >> 0x4;
    		d = mem[pc+1] & 0xf;
    		cd = mem[pc+1];
    		
    		if(a == 0x1) {
    			// Load the register R with the value at memory address XY.
    			reg[b] = mem[cd];
    		}
    		if(a == 0x2) {
    			// Load register R with the value XY.
    			reg[b] = cd;
    		}
    		if(a == 0x3) {
    			// Store the value in register R at memory address XY.
    			mem[cd] = reg[b];
    		}
    		if(a == 0x4) {
    			// Move the value in register R to register S.
    			reg[d] = reg[c];
    			reg[c] = 0x00;
    		}
    		if(a == 0x5) {
    			// Add(+) values in registers R and S and put the answer in register T.
    			reg[d] = reg[b] + reg[c];
    		}
    		if(a == 0x7) {
    			// Bit-wise OR(|) the values in registers R and S and put the answer in register T.
    			reg[d] = reg[b] | reg[c];
    		}
    		if(a == 0x8) {
    			// Bit-wise AND(&) the values in registers R and S and put the answer in register T.
    			reg[d] = reg[b] & reg[c];
    		}
    		if(a == 0x9) {
    			// Bit-wise XOR(^) the values in registers R and S and put the answer in register T.
    			reg[d] = reg[b] ^ reg[c];
    		}
    		if(a == 0xA) {
    			// Rotate the contents of register R X times to the right.
    			temp = (reg[b] & 0x1);
    			reg[b] >>= 1;
    			reg[b] = reg[b] | ( temp << 31);
    		}
    		if(a == 0xB) {
    			// Jump to the instruction located at memory address XY if register R = register 0.
    			if(mem[b] == reg[0]) {
    				pc = cd;
    			}
    		}
    		
    		display_values(pc, mem, reg);
    		
    		pc += 2;
    	}
    	
    	return 0;
    }
    
    
    void display_values(unsigned int pc, unsigned int mem[], unsigned int reg[]) {	
    	unsigned int i = 0;
    	
    	printf("%02X", pc);
    	printf(" %02X%02X - [", mem[pc], mem[pc+1]);
    	for(i = 0; i < size_reg; i++) {
    		printf(" %02X ", reg[i]);
    	}
    	printf("]\n");
    }
    ...and the result is this:
    Help on brookshear machine-brookshearerror-jpg

    it looks more correct now. will have to try to solve it by hand to see if it actually is.

  14. #14
    Registered User
    Join Date
    Oct 2012
    Posts
    14
    Quote Originally Posted by AndiPersti View Post
    Code:
        while(fscanf(f, "%X", &temp) != EOF) {
            mem[i] = (temp & 0xff00) >> 0x8;
            mem[i+1] = temp & 0xff;
            i += 2;
        }
    What's the value of "i" before you read the file?

    Bye, Andreas
    I initialised i = 0.
    Last edited by Warzaw; 04-22-2013 at 05:36 AM.

  15. #15
    Registered User
    Join Date
    Oct 2012
    Posts
    14
    Quote Originally Posted by grumpy View Post
    Oh, okay. That's because size_reg is a variable (and your arrays are therefore VLAs). Try making the sizes visible to the compiler at compile time (e.g. #define size_mem 256 or [slightly more devious] an enum trick), rather than as values of variables.

    If the sizes really must be variables, then use something like memcpy() or memset().
    i used #define but im curious about the enum. do you use it on the array size or the array itself?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Simulating a "brookshear machine"
    By kiwisfan in forum C Programming
    Replies: 3
    Last Post: 04-30-2012, 04:55 AM
  2. Convert assembly>machine code, machine code>assembly
    By wenxinleong in forum C Programming
    Replies: 12
    Last Post: 06-23-2011, 10:42 PM
  3. Replies: 4
    Last Post: 01-18-2008, 07:05 PM
  4. Porting from 32 bit machine to 64 bit machine!
    By anoopks in forum C Programming
    Replies: 10
    Last Post: 02-25-2005, 08:02 PM
  5. IDEA: A Slot Machine (aka a fruit machine)
    By ygfperson in forum Contests Board
    Replies: 0
    Last Post: 08-12-2002, 11:13 PM