Marta Santos Postado Abril 14, 2021 em 14:12 Compartilhar Postado Abril 14, 2021 em 14:12 Boa tarde, estou a fazer um exercício de C. Consiste em programar o ciclo de fetch, decode e execute para simular a execução das instruções na memória. A main já foi fornecida, apenas tenho que fazer as instruções pedidas. O meu programa está com Time Limit Exceeded e não tenho bem a certeza se todas as instruções estão corretas. Alguém me pode ajudar??? 16 bits words 12 bits addresses (max memory 2^12 words but less may be installed) 1 register (AC) Code Assembly Desciption 0x0XXX HALT halts CPU 0x1EEE LOAD EEE AC <- Mem[EEE] 0x2EEE STORE EEE Mem[EEE] <- AC 0x3EEE ADD EEE AC <- AC + Mem[EEE] 0x4EEE SUB EEE AC <- AC - Mem[EEE] 0x5EEE JUMP EEE PC <- EEE 0x6EEE JZ EEE if AC == 0 PC <- EEE 0x7EEE JA EEE if AC > 0 PC <- EEE 0x8EEE JB EEE if AC < 0 PC <- EEE 0x9XXX CLEAR AC <- 0 */ extern unsigned short int Mem[]; void dorun(){ unsigned short int pc; // program counter unsigned short int ir; // instruction register unsigned short int ac; // accumulator unsigned short int opcode; unsigned short int address; pc = 0; int continuar = 1; while(continuar) { ir = Mem[pc]; opcode = (ir & 0xf000)>>12; address = ir & 0x0fff; switch(opcode) { case 0x00: /* HALT */ continuar = 0; break; case 0x01: /* LOAD */ ac = Mem[address]; pc = pc + 1; break; case 0x02: /* STORE */ Mem[address] = ac; pc = pc + 1; break; case 0x03: /* ADD */ ac = ac + Mem[address]; break; case 0x04: /* SUB */ ac = ac - Mem[address]; break; case 0x05: /* JUMP */ pc = address; break; case 0x06: /* JZ */ if(ac == 0) pc = address; break; case 0x07: /* JA */ if(ac > 0) pc = address; break; case 0x08: /* JB */ if(ac < 0) pc = address; break; case 0x09: /* CLEAR */ ac = 0; break; } } } Link para o comentário Compartilhar em outros sites More sharing options...
codando Postado Abril 14, 2021 em 16:24 Compartilhar Postado Abril 14, 2021 em 16:24 Você está utilizando a memória de dados e de programa como sendo a mesma? poderia enviar seu array Mem? Link para o comentário Compartilhar em outros sites More sharing options...
Felipe.Silva Postado Abril 14, 2021 em 16:44 Compartilhar Postado Abril 14, 2021 em 16:44 Você não está atualizando o registrador "pc" corretamente. Remova as linhas "pc = pc + 1;" e, ao invés disso, atualize o pc imediatamente após carregar a instrução da memória. Tu pode fazer assim: ir = Mem[pc++]; O pc precisa ser atualizado sempre que uma instrução for executada. Como você só estava atualizando em algumas instruções, o loop ficava rodando indefinidamente porque pc estava sempre apontando para a mesma instrução. Sobre saber se as instruções fazem o que era esperado... Para isso eu sugiro que você compile o código no seu PC, execute e veja se o resultado foi o esperado. Eu testei aqui as instruções load, store e add e funcionaram conforme o esperado... Esse foi o código que usei para testar: #include <stdio.h> unsigned short int Mem[] = { 0x1004, 0x3005, 0x2004, 0x0000, // Data 0x0005, 0x0002, }; void dorun() { // etc... } int main(void) { dorun(); for (int i = 0; i < sizeof Mem / sizeof *Mem; i++) { printf("%04x, ", Mem[i]); } putchar('\n'); return 0; } Não testei as outras instruções, mas com base nisso daí tu pode testar elas... Ou meter o louco e já submeter após corrigir a atualização do pc e ver no que dá. ? Link para o comentário Compartilhar em outros sites More sharing options...
Marta Santos Postado Abril 14, 2021 em 17:26 Autor Compartilhar Postado Abril 14, 2021 em 17:26 Eu corrigi algumas coisas e ficou quase tudo bem. Apenas me falta as instruções de jump (JZ, JA, JB), porque tenho que verificar se o que está em ac é um numero positivo ou negativo, mas em complemento para 2. switch(opcode) { case 0x00: /* HALT */ continuar = 0; break; case 0x01: /* LOAD */ ac = Mem[address]; pc++; break; case 0x02: /* STORE */ Mem[address] = ac; pc++; break; case 0x03: /* ADD */ ac += Mem[address]; pc++; break; case 0x04: /* SUB */ ac -= Mem[address]; pc++; break; case 0x05: /* JUMP */ pc = address; break; case 0x06: /* JZ */ if(ac == 0) pc = address; else pc++; break; case 0x07: /* JA */ if(ac > 0) pc = address; else pc++; break; case 0x08: /* JB */ if(ac < 0) pc = address; else pc++; break; case 0x09: /* CLEAR */ ac = 0; pc++; break; } Link para o comentário Compartilhar em outros sites More sharing options...
Felipe.Silva Postado Abril 14, 2021 em 17:41 Compartilhar Postado Abril 14, 2021 em 17:41 Acontece que ac é unsigned short int, por isso a comparação do if do C não interpreta como um número sinalizado. Mas aí é só você fazer um casting para um número sinalizado que o código já vai estar correto. Exemplo: if((short int)ac < 0) pc = address; Mas se por algum motivo você quiser fazer a verificação manualmente, bastaria você pegar o bit mais significativo (MSB) do número e ver se ele está ligado ou não. Se estiver, significa que o número é negativo... Mas como eu disse, isso não é necessário. Link para o comentário Compartilhar em outros sites More sharing options...
Marta Santos Postado Abril 14, 2021 em 17:47 Autor Compartilhar Postado Abril 14, 2021 em 17:47 Eu sei a lógica da operação, mas não entendo como faço para pegar o bit mais significativo Link para o comentário Compartilhar em outros sites More sharing options...
Marta Santos Postado Abril 14, 2021 em 17:52 Autor Compartilhar Postado Abril 14, 2021 em 17:52 Porque não posso fazer um casting como o felipe mostrou... Link para o comentário Compartilhar em outros sites More sharing options...
Felipe.Silva Postado Abril 14, 2021 em 18:05 Compartilhar Postado Abril 14, 2021 em 18:05 opcode = (ir & 0xf000)>>12; Quando você fez isso daqui, você pegou os 4 bits mais significativos de ir. Para pegar só 1 é a mesma coisa, só vai mudar o número de bits setados no valor com que está sendo feito o AND. if ( ac & (1 << 15) ) pc = address; // Negativo! ac é menor que zero if ( ac && !(ac & (1 << 15)) ) pc = address; // ac é diferente de zero e positivo. Link para o comentário Compartilhar em outros sites More sharing options...
Posts Recomendados
Arquivado
Este tópico foi arquivado e está fechado para novas respostas.