PROGRAM 2
// filename: operating_system.cpp author: anthony f. ortiz // this file contains the declaration and implementation of the operating_system // class. // headers. #include #include // addressing mode constants. #define REGISTER 0 #define IMMEDIATE 1 #define DIRECT 2 #define INDIRECT 3 #define DATA 4 #define INOUT 5 // operation code constants. #define AND 0 #define OR 1 #define EXOR 2 #define CLR 3 #define INC 4 #define ADD 5 #define SUB 6 #define MULT 7 #define DIV 8 #define LOAD 9 #define STOR 10 #define JMP_ABS 11 #define JMP_REL 12 #define IF_POSR_JMP 13 #define IF_NEGR_JMP 14 #define COMP 15 #define JMP_SUB 16 #define RET_SUB 17 #define ISZ 18 #define READ 19 #define PRINT 20 #define HALT 21 // process states. #define FINISHED 0 #define READY 1 #define RUNNING 2 // dedicated register. #define DEDICATED 7 // maximum registers #define max_registers 8 #define max_ram 200 #define max_buffer 100 #define max_pagetable 10 #define max_processes 4 #define page_size 10 // word. struct word { int mode; int opcode; int reg; int address; }; // pcb. struct program_context_block { int process_id; int state; int page_table [10]; int registers [8]; int pc; int begin_opcode; int end_opcode; int begin_data; int end_data; program_context_block * next; }; // operating system. class operating_system { private: // ram. word * m; // page table. int * page_table; // registers. int * registers; // ready queue. program_context_block * ready_queue_begin; program_context_block * ready_queue_end; // intruction register. word ir; // process id, process state, pc, total processes, and instruction // counter int process_id, state, pc, processes, instruction_counter; // begin_data, end_data, begin_opcode, end_opcode. int begin_data, end_data, begin_opcode, end_opcode; public: // constructor. operating_system (); // destructor. ~operating_system (); // fetch. void fetch (); // execute. void execute (); // display ir (addressing mode, opcode, register, address), pc, // and registers. void display (); // pause screen. void pause (); // insert into ready queue. void insert (program_context_block * pcb); // remove from ready queue. program_context_block * remove (); // is empty? int is_empty (); // initialize (begin). void begin_initialization (); // initialize (end). void end_initialization (); // return process count. int get_processes (); }; // constructor. operating_system :: operating_system () { // mode, address, page, frame, offset, logical, physical, page count, // frame count, data count, start data, file pointer, buffer, and // file names; int mode, address, page, frame, offset, logical, physical, page_count; int frame_count, data_count, start_data; FILE * fp; char buf [100]; char * file_name [10] = {"f1.1.txt", "f2.2.txt", "f3.3.txt", "f4.4.txt"}; // allocate memory for page table. page_table = new int [max_pagetable]; // allocate memory for registers. registers = new int [max_registers]; // allocate memory for ready queue and initialize ready queue. ready_queue_begin = new program_context_block; ready_queue_begin -> next = NULL; ready_queue_end = ready_queue_begin; // allocate memory for ram and initialize ram, 0-99 opcode, // 100-199 data. m = new word [max_ram]; for (address = 0; address < max_ram; address++) { m [address].mode = -1; m [address].opcode = -1; m [address].reg = -1; m [address].address = -1; } // initialize total processes, frame count, and data count. processes = 0; frame_count = 0; data_count = max_ram / 2; // initialize each pcb. while (processes < max_processes) { // open file. fp = fopen (file_name [processes], "r"); // drastic step. if (fp == NULL) { printf ("this file doesn't exist.\n\n"); exit (0); } // initialize pcb. program_context_block * pcb = new program_context_block; // initialize pcb id. pcb -> process_id = processes; // initialize pcb state. pcb -> state = READY; // initialize pcb page table. for (page = 0; page < max_pagetable; page++) { pcb -> page_table [page] = -1; } // initialize pcb registers. for (int i = 0; i < max_registers; i++) { pcb -> registers [i] = 0; } // initialize logical memory, page count, and start data. logical = 0; page_count = 0; start_data = data_count; // initialize rest of pcb. while (fgets (buf, max_buffer, fp) != NULL) { sscanf (buf, "%i", &mode); if (mode != DATA) { if (logical % max_pagetable == 0) { do { frame = rand () % 10; } while (m [frame * page_size].mode != -1 && frame_count > max_pagetable); pcb -> page_table [page_count] = frame; page_count++; frame_count++; } // drastic step. if (frame_count > max_pagetable) { printf ("there is no more space in opcode part of memory.\n\n"); exit (0); } // drasitc step. if (page_count > max_pagetable) { printf ("there is no more space in page table.\n\n"); exit (0); } offset = logical % max_pagetable; physical = frame * page_size + offset; sscanf (buf, "%i %i %i %i", &m [physical].mode, &m [physical].opcode, &m [physical].reg, &m [physical].address); logical++; } else { sscanf (buf, "%i %i %i %i", &m [data_count].mode, &m [data_count].opcode, &m [data_count].reg, &m [data_count].address); data_count++; // drastic step. if (data_count > max_ram) { printf ("there is no more space in data part of memory.\n\n"); exit (0); } } } // initialize pcb pc, pcb begin_opcode, pcb end_opcode, // pcb begin_data, and pcb end_data. pcb -> pc = 0; pcb -> begin_opcode = 0; if (logical == 0) { pcb -> end_opcode = 0; } else { pcb -> end_opcode = logical - 1; } pcb -> begin_data = start_data; if (data_count == max_ram / 2) { pcb -> end_data = start_data; } else { pcb -> end_data = data_count - 1; } // update processes count. processes++; // close file. fclose (fp); // add to ready queue. insert (pcb); } // initialize instruction counter. instruction_counter = 0; } // destructor. operating_system :: ~operating_system () { // deallocate memory. delete [] registers; delete [] page_table; delete [] m; } // fetch. void operating_system :: fetch () { // frame, offset, and physical. int frame, offset, physical; // round robin scheduling. if (instruction_counter % 4 == 0 || state == FINISHED) { begin_initialization (); } // translate logical (pc) address to physical address (frame + offset), // fetch instruction from memory, place in instruction register, and // update pc. frame = page_table [pc / max_pagetable]; offset = pc % page_size; physical = frame * page_size + offset; ir = m [physical]; pc++; } // execute. void operating_system :: execute () { // execute one of the commands. if (ir.mode < REGISTER || ir.mode > INOUT) { printf ("this is an invalid addressing mode.\n\n"); } else if (ir.opcode < AND || ir.opcode > HALT) { printf ("this is an invalide op-code.\n\n"); } else if (ir.reg < 0 || ir.reg > 7 && ir.opcode != ISZ) { printf ("this is an invalid register.\n\n"); } else if (ir.mode == REGISTER) { if (ir.address < 0 || ir.address > 7 && ir.opcode != ISZ) { printf ("this is an invalid register.\n\n"); } else if (ir.opcode == AND) { registers [ir.reg] = registers [ir.reg] & registers [ir.address]; } else if (ir.opcode == OR) { registers [ir.reg] = registers [ir.reg] | registers [ir.address]; } else if (ir.opcode == EXOR) { registers [ir.reg] = registers [ir.reg] ^ registers [ir.address]; } else if (ir.opcode == CLR) { registers [ir.reg] = 0; } else if (ir.opcode == INC) { registers [ir.reg]++; } else if (ir.opcode == ADD) { registers [ir.reg] = registers [ir.reg] + registers [ir.address]; } else if (ir.opcode == SUB) { registers [ir.reg] = registers [ir.reg] - registers [ir.address]; } else if (ir.opcode == MULT) { registers [ir.reg] = registers [ir.reg] * registers [ir.address]; } else if (ir.opcode == DIV) { registers [ir.reg] = registers [ir.reg] / registers [ir.address]; } else if (ir.opcode == LOAD) { registers [ir.reg] = registers [ir.address]; } else if (ir.opcode == STOR) { registers [ir.address] = registers [ir.reg]; } else if (ir.opcode == JMP_ABS) { if (registers [ir.address] < begin_opcode || registers [ir.address] > end_opcode) { printf ("address is out of range.\n\n"); } else { pc = registers [ir.address]; } } else if (ir.opcode == JMP_REL) { if (pc + registers [ir.address] - 1 < begin_opcode || pc + registers [ir.address] - 1 > end_opcode) { printf ("address is out of range.\n\n"); } else { pc = pc + registers [ir.address] - 1; } } else if (ir.opcode == IF_POSR_JMP) { if (registers [ir.address] < begin_opcode || registers [ir.address] > end_opcode) { printf ("address is out of range.\n\n"); } else { if (registers [ir.reg] > 0) { pc = registers [ir.address]; } } } else if (ir.opcode == IF_NEGR_JMP) { if (registers [ir.address] < begin_opcode || registers [ir.address] > end_opcode) { printf ("address is out of range.\n\n"); } else { if (registers [ir.reg] < 0) { pc = registers [ir.address]; } } } else if (ir.opcode == COMP) { registers [ir.reg] = ~ registers [ir.reg]; } else if (ir.opcode == JMP_SUB) { // not used for this project. } else if (ir.opcode == RET_SUB) { // not used for this project. } else if (ir.opcode == ISZ) { if (ir.reg < begin_opcode || ir.reg > end_opcode || ir.address < begin_data || ir.address > end_data) { printf ("address is out of range.\n\n"); } else { m [ir.address].address--; if (m [ir.address].address == 0) { pc = ir.reg; } } } else if (ir.opcode == READ) { // undefined. } else if (ir.opcode == PRINT) { // undefined. } else if (ir.opcode == HALT) { state = FINISHED; } } else if (ir.mode == IMMEDIATE) { if (ir.opcode == AND) { registers [ir.reg] = registers [ir.reg] & ir.address; } else if (ir.opcode == OR) { registers [ir.reg] = registers [ir.reg] | ir.address; } else if (ir.opcode == EXOR) { registers [ir.reg] = registers [ir.reg] ^ ir.address; } else if (ir.opcode == CLR) { registers [ir.reg] = 0; } else if (ir.opcode == INC) { registers [ir.reg]++; } else if (ir.opcode == ADD) { registers [ir.reg] = registers [ir.reg] + ir.address; } else if (ir.opcode == SUB) { registers [ir.reg] = registers [ir.reg] - ir.address; } else if (ir.opcode == MULT) { registers [ir.reg] = registers [ir.reg] * ir.address; } else if (ir.opcode == DIV) { registers [ir.reg] = registers [ir.reg] / ir.address; } else if (ir.opcode == LOAD) { registers [ir.reg] = ir.address; } else if (ir.opcode == STOR) { // not defined } else if (ir.opcode == JMP_ABS) { if (ir.address < begin_opcode || ir.address > end_opcode) { printf ("address is out of range.\n\n"); } else { pc = ir.address; } } else if (ir.opcode == JMP_REL) { if (pc + ir.address - 1 < begin_opcode || pc + ir.address - 1 > end_opcode) { printf ("address is out of range.\n\n"); } else { pc = pc + ir.address - 1; } } else if (ir.opcode == IF_POSR_JMP) { if (ir.address < begin_opcode || ir.address > end_opcode) { printf ("address is out of range.\n\n"); } else { if (registers [ir.reg] > 0) { pc = ir.address; } } } else if (ir.opcode == IF_NEGR_JMP) { if (ir.address < begin_opcode || ir.address > end_opcode) { printf ("address is out of range.\n\n"); } else { if (registers [ir.reg] < 0) { pc = ir.address; } } } else if (ir.opcode == COMP) { registers [ir.reg] = ~ ir.address; } else if (ir.opcode == JMP_SUB) { // not used for this project. } else if (ir.opcode == RET_SUB) { // not used for this project. } else if (ir.opcode == ISZ) { if (ir.reg < begin_opcode || ir.reg > end_opcode || ir.address < begin_data || ir.address > end_data) { printf ("address is out of range.\n\n"); } else { m [ir.address].address--; if (m [ir.address].address == 0) { pc = ir.reg; } } } else if (ir.opcode == READ) { // undefined. } else if (ir.opcode == PRINT) { // undefined. } else if (ir.opcode == HALT) { state = FINISHED; } } else if (ir.mode == DIRECT) { if (ir.address < begin_data || ir.address > end_data && ir.opcode != ISZ) { printf ("adress is out of range.\n\n"); } else if (ir.opcode == AND) { registers [ir.reg] = registers [ir.reg] & m [ir.address].address; } else if (ir.opcode == OR) { registers [ir.reg] = registers [ir.reg] | m [ir.address].address; } else if (ir.opcode == EXOR) { registers [ir.reg] = registers [ir.reg] ^ m [ir.address].address; } else if (ir.opcode == CLR) { registers [ir.reg] = 0; } else if (ir.opcode == INC) { registers [ir.reg]++; } else if (ir.opcode == ADD) { registers [ir.reg] = registers [ir.reg] + m [ir.address].address; } else if (ir.opcode == SUB) { registers [ir.reg] = registers [ir.reg] - m [ir.address].address; } else if (ir.opcode == MULT) { registers [ir.reg] = registers [ir.reg] * m [ir.address].address; } else if (ir.opcode == DIV) { registers [ir.reg] = registers [ir.reg] / m [ir.address].address; } else if (ir.opcode == LOAD) { registers [ir.reg] = m [ir.address].address; } else if (ir.opcode == STOR) { m [ir.address].address = registers [ir.reg]; } else if (ir.opcode == JMP_ABS) { if (m [ir.address].address < begin_opcode || m [ir.address].address > end_opcode) { printf ("address is out of range.\n\n"); } else { pc = m [ir.address].address; } } else if (ir.opcode == JMP_REL) { if (m [ir.address].address + pc - 1 < begin_opcode || m [ir.address].address + pc - 1 > end_opcode) { printf ("address is out of range.\n\n"); } else { pc = m [ir.address].address + pc - 1; } } else if (ir.opcode == IF_POSR_JMP) { if (registers [ir.address] < begin_opcode || registers [ir.address] > end_opcode) { printf ("address is out of range.\n\n"); } else { if (registers [ir.reg] > 0) { pc = registers [ir.address]; } } } else if (ir.opcode == IF_NEGR_JMP) { if (registers [ir.address] < begin_opcode || registers [ir.address] > end_opcode) { printf ("address is out of range.\n\n"); } else { if (registers [ir.reg] < 0) { pc = registers [ir.address]; } } } else if (ir.opcode == COMP) { registers [ir.reg] = ~ m [ir.address].address; } else if (ir.opcode == JMP_SUB) { // not used for this project. } else if (ir.opcode == RET_SUB) { // not used for this project. } else if (ir.opcode == ISZ) { if (ir.reg < begin_opcode || ir.reg > end_opcode || ir.address < begin_data || ir.address > end_data) { printf ("address is out of range.\n\n"); } else { m [ir.address].address++; if (m [ir.address].address != 0) { pc = ir.reg; } } } else if (ir.opcode == READ) { // undefined. } else if (ir.opcode == PRINT) { // undefined. } else if (ir.opcode == HALT) { state = FINISHED; } } else if (ir.mode == INDIRECT) { if (m [ir.address].address < begin_data || m [ir.address].address > end_data && ir.opcode != ISZ) { printf ("address is out of range.\n\n"); } else if (ir.opcode == AND) { registers [ir.reg] = registers [ir.reg] & m [m [ir.address].address].address; } else if (ir.opcode == OR) { registers [ir.reg] = registers [ir.reg] | m [m [ir.address].address].address; } else if (ir.opcode == EXOR) { registers [ir.reg] = registers [ir.reg] ^ m [m [ir.address].address].address; } else if (ir.opcode == CLR) { registers [ir.reg] = 0; } else if (ir.opcode == INC) { registers [ir.reg]++; } else if (ir.opcode == ADD) { registers [ir.reg] = registers [ir.reg] + m [m [ir.address].address].address; } else if (ir.opcode == SUB) { registers [ir.reg] = registers [ir.reg] - m [m [ir.address].address].address; } else if (ir.opcode == MULT) { registers [ir.reg] = registers [ir.reg] * m [m [ir.address].address].address; } else if (ir.opcode == DIV) { registers [ir.reg] = registers [ir.reg] / m [m [ir.address].address].address; } else if (ir.opcode == LOAD) { registers [ir.reg] = m [m [ir.address].address].address; } else if (ir.opcode == STOR) { m [m [ir.address].address].address = registers [ir.reg]; } else if (ir.opcode == JMP_ABS) { if (m [m [ir.address].address].address < begin_opcode || m [m [ir.address].address].address > end_opcode) { printf ("address is out of range.\n\n"); } else { pc = m [m [ir.address].address].address; } } else if (ir.opcode == JMP_REL) { if (pc + m [m [ir.address].address].address - 1 < begin_opcode || pc + m [m [ir.address].address].address - 1 > end_opcode) { printf ("address is out of range.\n\n"); } else { pc = pc + m [m [ir.address].address].address - 1; } } else if (ir.opcode == IF_POSR_JMP) { if (m [m [ir.address].address].address < begin_opcode || m [m [ir.address].address].address > end_opcode) { printf ("address is out of range.\n\n"); } else { if (registers [ir.reg] > 0) { pc = m [m [ir.address].address].address; } } } else if (ir.opcode == IF_NEGR_JMP) { if (m [m [ir.address].address].address < begin_opcode || m [m [ir.address].address].address > end_opcode) { printf ("address is out of range.\n\n"); } else { if (registers [ir.reg] < 0) { pc = m [m [ir.address].address].address; } } } else if (ir.opcode == COMP) { registers [ir.reg] = ~ m [m [ir.address].address].address; } else if (ir.opcode == JMP_SUB) { // not used for this project. } else if (ir.opcode == RET_SUB) { // not used for this project. } else if (ir.opcode == ISZ) { if (ir.reg < begin_opcode || ir.reg > end_opcode || ir.address < begin_data || ir.address > end_data) { printf ("address is out of range.\n\n"); } else { m [ir.address].address--; if (m [ir.address].address == 0) { pc = ir.reg; } } } else if (ir.opcode == READ) { // not defined. } else if (ir.opcode = PRINT) { // not defined. } else if (ir.opcode == HALT) { state = FINISHED; } } else if (ir.mode == DATA) { // do nothing. } else if (ir.mode == INOUT) { if (ir.opcode == READ) { scanf ("%i", registers [DEDICATED]); } else if (ir.opcode == PRINT) { printf ("%i", registers [DEDICATED]); } } } // display ir (addressing mode, opcode, register, address), pc, and // registers. void operating_system :: display () { // display addressing mode. if (ir.mode == REGISTER) { printf ("register "); } else if (ir.mode == IMMEDIATE) { printf ("immediate "); } else if (ir.mode == DIRECT) { printf ("direct "); } else if (ir.mode == INDIRECT) { printf ("indirect "); } else if (ir.mode == DATA) { printf ("data "); } else if (ir.mode == INOUT) { printf ("inout "); } else { printf ("unknown mode "); } // display op-code. if (ir.opcode == AND) { printf ("and "); } else if (ir.opcode == OR) { printf ("or "); } else if (ir.opcode == EXOR) { printf ("exor "); } else if (ir.opcode == CLR) { printf ("clear "); } else if (ir.opcode == INC) { printf ("inc "); } else if (ir.opcode == ADD) { printf ("add "); } else if (ir.opcode == SUB) { printf ("sub "); } else if (ir.opcode == MULT) { printf ("mult "); } else if (ir.opcode == DIV) { printf ("div "); } else if (ir.opcode == LOAD) { printf ("load "); } else if (ir.opcode == STOR) { printf ("stor "); } else if (ir.opcode == JMP_ABS) { printf ("jmp_abs "); } else if (ir.opcode == JMP_REL) { printf ("jmp_rel "); } else if (ir.opcode == IF_POSR_JMP) { printf ("if_posr_jmp "); } else if (ir.opcode == IF_NEGR_JMP) { printf ("if_negr_jmp "); } else if (ir.opcode == COMP) { printf ("comp "); } else if (ir.opcode == JMP_SUB) { printf ("jmp_sub "); } else if (ir.opcode == RET_SUB) { printf ("ret_sub "); } else if (ir.opcode == ISZ) { printf ("isz "); } else if (ir.opcode == READ) { printf ("read "); } else if (ir.opcode == PRINT) { printf ("print "); } else if (ir.opcode == HALT) { printf ("halt "); } else { printf ("unknown instruction "); } // display register. printf ("register %i ", ir.reg); // display address. printf ("address %i ", ir.address); printf ("\n\n"); // display current pc. printf ("pc = %i ", pc); // display registers (0-7). printf ("registers (0-7) = "); for (int i = 0; i < max_registers; i++) { printf ("%i ", registers [i]); } printf ("\n\n"); // round robin sceduling. instruction_counter++; if (instruction_counter % 4 == 0 || state == FINISHED) { end_initialization (); instruction_counter = 0; } } // pause screen. void operating_system :: pause () { // character. char ch; // pause screen. fflush (stdin); printf ("press any key to continue. "); ch = getchar (); printf ("\n"); } // insert into ready queue. void operating_system :: insert (program_context_block * pcb) { // insert at end of ready queue. if (ready_queue_begin -> next == NULL) { ready_queue_end = ready_queue_begin; } pcb -> next = NULL; ready_queue_end -> next = pcb; ready_queue_end = ready_queue_end -> next; } // remove from ready queue. program_context_block * operating_system :: remove () { // remove from ready queue (didn't do the actual remove yet). if (ready_queue_begin -> next != NULL) { program_context_block * temp = ready_queue_begin -> next; ready_queue_begin -> next = temp -> next; return temp; } return NULL; } // is empty? int operating_system :: is_empty () { // return 1 if empty, otherwise return 0. if (ready_queue_begin -> next == NULL) { return 1; } return 0; } // initialize (begin). void operating_system :: begin_initialization () { // remove process from ready queue. program_context_block * pcb = remove (); // finished. if (get_processes () < 1) { // do nothing. } // not finished. else { // initialize process_id, pc, begin_opcode, end_opcode, begin_data, // and end_data. process_id = pcb -> process_id; printf ("process %i is removed from ready queue and running.\n\n", process_id); state = RUNNING; pc = pcb -> pc; begin_opcode = pcb -> begin_opcode; end_opcode = pcb -> end_opcode; begin_data = pcb -> begin_data; end_data = pcb -> end_data; // initialize page table. for (int j = 0; j < max_pagetable; j++) { page_table [j] = pcb -> page_table [j]; } // initialize registers. for (int i = 0; i < max_registers; i++) { registers [i] = pcb -> registers [i]; } // deallocate memory. delete pcb; } } // initialize (end). void operating_system :: end_initialization () { // process finished. if (state == FINISHED) { printf ("process %i has finished.\n\n", process_id); processes--; } // process not finished. else { // pcb. program_context_block * pcb = new program_context_block; // initialize process_id, pc, begin_opcode, end_opcode, begin_data, // and end_data. pcb -> process_id = process_id; printf ("process %i is inserted into the ready queue.\n\n", process_id); pcb -> state = READY; pcb -> pc = pc; pcb -> begin_opcode = begin_opcode; pcb -> end_opcode = end_opcode; pcb -> begin_data = begin_data; pcb -> end_data = end_data; // initialize page table. for (int j = 0; j < max_pagetable; j++) { pcb -> page_table [j] = page_table [j]; } // initialize registers. for (int i = 0; i < max_registers; i++) { pcb -> registers [i] = registers [i]; } // insert process into ready queue. insert (pcb); } // all processes have finished. if (get_processes () < 1) { printf ("all processes have finished.\n\n"); } } // return process count. int operating_system :: get_processes () { // return processes. return processes; } // main. void main () { // operating system. operating_system os; // fetch, execute, and display instruction. while (os.get_processes () > 0) { os.fetch (); os.execute (); os.display (); os.pause (); } } // filename: operatingsystem.out author: anthony f. ortiz process 0 is removed from ready queue and running. immediate load register 0 address -30 pc = 1 registers (0-7) = -30 0 0 0 0 0 0 0 press any key to continue. etc., etc., etc.
BACK TO CS6560 PAGE.