Baixe o app para aproveitar ainda mais
Prévia do material em texto
Raul F. Weber & Carlos A. L. Lisboa 1-1 Capítulo UM Computador Ramses RAMSES possui todas as características do computador NEANDER e incorpora, adicionalmente, recursos que visam facilitar sua programação. Estes recursos compreendem: • quatro modos de endereçamento, • dois registradores de uso geral, • um registrador de índice, • indicadores de carry, negativo e zero, • instruções adicionais (chamada de subrotina, negação e deslocamento de bits, etc ...). RAMSES é compatível com NEANDER. Todos os programas desenvolvidos para NEANDER também são executáveis em RAMSES. A compatibilidade entre os dois computadores, entretanto, só é válida em um sentido: programas RAMSES não rodam em NEANDER. Esta característica é freqüentemente encontrada em famílias de computadores comerciais. Para que RAMSES execute programas escritos para NEANDER é necessário que os quatro bits menos significativos da palavra de instrução de NEANDER sejam ocupados com zeros. 1.1 Características do computador RAMSES O computador RAMSES tem as seguintes características: • Largura de dados e endereços de 8 bits • Dados representados em complemento de dois • 2 registradores de uso geral (A e B), de 8 bits • 1 registrador de índice (X), de 8 bits • 1 apontador de programa de 8 bits (PC) • 1 registrador de estado com 3 códigos de condição: negativo (N), zero (Z) e carry (C) 1.2 Formato das instruções As instruções de RAMSES são formadas por um ou dois bytes, ou seja, ocupam uma ou duas posições na memória (figura 1.1). O primeiro byte contém o código (4 bits mais significativos), uma referência a um registrador (bits 3 e 2), e indicação de um modo de endereçamento (bits 1 e 0). Nas instruções que fazem referência à memória, o segundo byte contém um endereço ou um dado imediato. Observe a semelhança existente com o formato de instruções do NEANDER (figura 1.2). Raul F. Weber & Carlos A. L. Lisboa1-2 reg endereço ou dado imediato 7 34 02 1 modocódigo Figura 1.1 - Formato das instruções de RAMSES 1.3 Modos de endereçamento Os modos de endereçamento são quatro, codificados através dos dois bits menos significativos da instrução: 00 -direto : o endereço (8 bits) do operando segue a palavra de código da instrução (figura 1.2). 01 -indireto : o endereço (8 bits) do endereço do operando segue a palavra de código da instrução (figura 1.3). 10 -imediato : o operando (8 bits) segue a palavra de código da instrução (figura 1.4). 11 -indexado : o deslocamento (8 bits) que segue a palavra de código da instrução é somado ao RX para formar o endereço do operando (figura 1.5). O deslocamento é representado em complemento de dois. endereço memória operando instrução Figura 1.2 - Modo 0 de endereçamento (direto) Raul F. Weber & Carlos A. L. Lisboa 1-3 endereço memória operando instrução endereço Figura 1.3 - Modo 1 (endereçamento indireto) operando memória instrução Figura 1.4 - Modo 2 (endereçamento imediato) deslocamento memória operando instrução endereço Reg. X + Figura 1.5 - Modo 3 (endereçamento indexado) Raul F. Weber & Carlos A. L. Lisboa1-4 Nas instruções de desvio, os modos de endereçamento fornecem o endereço de desvio, ao invés do endereço de operando. Por essa razão, o modo de endereçamento imediato é ilegal para instruções de desvio. Na tabela 1.1, abaixo, são mostrados os mnemônicos usados para codificar os modos de endereçamento de RAMSES. Nesta tabela, n representa um endereço (modos 0, 1 e 3) ou um dado (modo 2). Código Modo de EndereçamentoMnemônico 00 direto n 01 indireto n,I 10 imediato #n 11 indexado n,X Tabela 1.1 - Codificação dos modos de endereçamento 1.4 Conjunto de instruções As instruções de manipulação de dados operam sobre um dos três registradores da arquitetura, codificados através dos bits 3 e 2 da instrução : 00 = A (registrador RA) 01 = B (registrador RB) 10 = X (registrador de índice) 11 = nenhum registrador é selecionado. RAMSES possui 16 instruções, codificadas através dos quatro bits mais significativos da instrução, conforme mostrado na tabela 1.2. Observe-se que as 11 instruções originais do NEANDER mantêm seu significado. Estas 11 instruções só foram acrescidas dos modos de endereçamento e dos registradores extras. Código Instrução Operação Executada 0000 NOP nenhuma operação 0001 STR r end armazena registrador na memória - (store) 0010 LDR r end carrega registrador da memória - (load) 0011 ADD r end adição - soma memória ao registrador 0100 OR r end "ou" (adição lógica) - resultado no registrador 0101 AND r end "e" (multiplicação lógica) - resultado no registrador 0110 NOT r inverte (complementa para 1) registrador 0111 SUB r end subtração - subtrai memória do registrador 1000 JMP end desvio incondicional - (jump) 1001 JN end desvio condicional se < Ø - (jump on negative) 1010 JZ end desvio condicional se = Ø - (jump on zero) 1011 JC end desvio condicional se carry = 1 - (jump on carry) 1100 JSR end desvio para subrotina - (jump subroutine) 1101 NEG r troca de sinal - (negate) 1110 SHR r deslocamento para a direita - (shift right) 1111 HLT parada - (halt) Tabela 1.2 - Conjunto de instruções 1-5 As operações efetuadas por cada uma das instruções podem ser vistas na tabela a seguir. Instrução Operação Efetuada NOP Nenhuma operação STR r end MEM(end) r LDR r end r MEM(end) ADD r end r MEM(end) + r OR r end r MEM(end) OR r AND r end r MEM(end) AND r NOT r r NOT r SUB r end r r - MEM(end) JMP end PC end JN end IF N=1 THEN PC end JZ end IF Z=1 THEN PC end JC end IF C=1 THEN PC end JSR end MEM(end) PC ; PC end+1 NEG r r - r SHR r r r/2 Tabela 1.3 - Ações executadas pelas instruções Nas tabelas acima, end representa o endereço, tal como calculado pelo modo de endereçamento, e r indica o registrador utilizado na instrução (A, B ou X). No modo de endereçamento imediato, MEM(end) corresponde à posição de memória que segue a instrução. Para instruções de desvio, o modo imediato é tratado exatamente como se fosse o modo direto. 1.5 Códigos de condição A unidade lógica e aritmética de RAMSES fornece os seguintes códigos de condição: N - (negativo) - sinal do resultado 1 - resultado é negativo 0 - resultado é positivo Z - (zero) - indica resultado igual a zero 1 - resultado é igual a zero 0 - resultado é diferente de zero C - (carry) - carry-out de operações aritméticas 1 - carry-out é igual a um 0 - carry-out é igual a zero As instruções de RAMSES afetam os três códigos de condição (N, Z e C) de acordo com o mostrado na tabela 1.4. As instruções não indicadas na tabela (STR, JMP, JN, JZ, JC, JSR, NOP e HLT) não afetam os códigos de condição. Observe-se que os códigos de condição sempre refletem o estado da última operação lógica ou aritmética que foi executada, independente de qual registrador foi utilizado (A, B ou X). Os códigos de condição não refletem o conteúdo atual de nenhum registrador. Raul F. Weber & Carlos A. L. Lisboa1-6 Códigos de condição Instrução N Z C 0010 - LDR n z - 0011 - ADD n z c 0100 - OR n z - 0101 - AND n z - 0110 - NOT n z - 0111 - SUB n z c 1101 - NEG n z c 1110 - SHR n z c (lsb) Tabela 1.4 - Alteração dos códigos de condição Na instrução SHR, o bit menos significativo do registrador é deslocado para o bit de carry (C). 1.6 Programação em linguagem simbólica RAMSES possui um montador de linha, que permite a entrada de instruções na forma simbólica, usando os mesmos mnemônicos encontrados nas tabelas desse capítulo. Este montador manipula apenas uma instrução de cada vez. Endereçamento simbólico (rótulos/labels) não pode ser utilizado. Erros durante a montagem da instrução são sinalizados através da linha de mensagens, e nestes casos nenhum código é gerado (nem armazenado). Cuidado especial deve ser tomado nas regiõessuperiores da memória, pois o montador não passa automaticamente do endereço 256 para o endereço 0, somente indicando erro (excedido limite da memória). O exemplo a seguir ilustra os três tipos possíveis de entrada. O modo simbólico é obtido através do montador, e os modos hexa e decimal são obtidos através do editor de memória. Simbólico Hexa Decimal LDR A 128 20 80 32 128 ADD A 129 30 81 48 129 ADD A 130 30 82 48 130 STR A 131 10 83 16 131 HLT F0 240 Observe que: - os códigos de máquina são exatamente os mesmos aceitos por NEANDER (mera coincidência ?!). - como existem três registradores em RAMSES (RA, RB e RX), deve ser assinalado qual o registrador a ser utilizado, usando os mnemônicos A, B e X. - o modo de endereçamento direto não precisa ser assinalado com nenhum símbolo especial no programa simbólico. 1.7 Subrotinas Uma subrotina é uma seqüência de instruções que pode ser ativada (chamada) de qualquer ponto de um programa. Após a execução de uma subrotina, o controle retorna à instrução seguinte àquela que a ativou. Em linguagens de baixo nível, instruções que permitem a ativação de uma subrotina são denominadas instruções de desvio para subrotina. JSR (jump to subroutine) no RAMSES é um exemplo. Raul F. Weber & Carlos A. L. Lisboa 1-7 Quando JSR é executada, o controle do programa passa à subrotina que se encontra no endereço indicado por JSR. Assim, uma chamada de subrotina se assemelha a um desvio incondicional (JMP). A diferença entre JSR e JMP reside no seguinte fato: no final da execução da subrotina deve ocorrer um desvio para a posição que segue imediatamente a instrução que chamou essa subrotina. Esse desvio é chamado de retorno. Existem várias maneiras possíveis de efetuar o retorno da subrotina para a posição adequada no programa. Todas elas implicam em armazenar o endereço do retorno. O endereço de retorno é o endereço da instrução que segue a instrução que chamou a subrotina. Esse endereço é o próprio valor que o PC assume após a decodificação da instrução de JSR . A forma e o lugar em que está armazenado o endereço de retorno determinam as seguintes características de uma subrotina: a) recursividade - capacidade de um subrotina de se chamar a si própria. b) reentrância - possibilidade de vários programas em um ambiente multiprogramado compartilharem uma única cópia de uma mesma subrotina. c) número de níveis de aninhamento de subrotinas - subrotinas aninhadas são subrotinas que foram chamadas por subrotinas, que foram chamadas por subrotinas, que foram chamadas por subrotinas ... Em RAMSES, quando JSR é executada, o endereço de retorno é armazenado na primeira palavra da subrotina (ou seja, a posição correspondente a end de JSR end). Não existe instrução de retorno em RAMSES. O retorno é realizado através da instrução JMP, usando a primeira palavra da subrotina como endereço indireto para desvio. JSR end MEM(end) ¬ PC PC ¬ end+1 Exemplo: Considere como exemplo uma subrotina que calcula o complemento de dois de um dado armazenado no registrador B. Essa subrotina está armazenada na posição 60 de memória. 60 NOP % início da subrotina 61 NOT B 62 ADD B #1 64 JMP 60,I% retorno da subrotina A chamada dessa subrotina, no programa, é feita através de JSR 60. Considere um programa que tem um JSR 60 na posição 10 e outro na posição 16. Na posição 60 de memória (que corresponde à instrução NOP) será armazenado: - após a execução da instrução na posição 10, o valor 12, - após a execução da instrução na posição 16, o valor 18. Em ambos os casos, após a execução de JSR, o PC assume valor 61. Nota: a subrotina mostrada acima ocupará 6 palavras na memória; como poderia ser codificada para ocupar apenas 4 palavras, produzindo o mesmo resultado ? Fim de exemplo. Raul F. Weber & Carlos A. L. Lisboa1-8 O mecanismo de chamada de subrotina em RAMSES não permite recursividade nem reentrância. Entretanto, não existe limite para o número de chamadas de subrotinas que podem ser aninhadas. Uma convenção que deve ser adotada é a forma como os parâmetros são passados para a subrotina. Um parâmetro pode ser passado por valor (fornecendo-se o valor de uma variável) ou por nome (fornecendo-se o endereço da variável). Além disso, os parâmetros podem ser passados através de registradores, posições pré-estabelecidas de memória, estrutura de dados pré-estabelecida (também na memória) e vários outros métodos, inclusive misturando-se os métodos entre si (alguns parâmetros por registrador e outros por memória, por exemplo). Seja por exemplo uma subrotina que realize multiplicação. Esta rotina recebe os dois valores a serm multiplicados e devolve o resultado. Por simplicidade, assuma-se que todos os operandos são de oito bits, inteiros positivos. Os parâmetros no programa principal estão em três posições de memória: primeiro_operando, segundo_operando e resultado. A subrotina utiliza três outras posições: op1, op2 e resul. Um primeiro caso poderia envolver somente registradores: os valores dos operandos são recebidos nos registradores A e B, e o resultado é devolvido no registrador A (note que isto é uma convenção - inúmeras variações são possíveis). Programa principal Subrotina LDR A primeiro_operando NOP LDR B segundo_operando STR A op1 JSR multiplica STR B op2 STR A resultado <multiplicação> LDR A resul JMP multiplica,I Em um segundo caso, poderiam ser utilizadas posições pré-estabelecidas de memória. Por exemplo, sejam as posições param1, param2 e param3, conhecidas tanto pelo programa principal como pela subrotina. Então a chamada e o corpo da subrotina ficam: Programa principal Subrotina LDR A primeiro_operando NOP STR A param1 LDR A param1 LDR A segundo_operando STR A op1 STR A param2 LDR A param2 JSR multiplica STR A op2 LDR A param3 <multiplicação> STR A resultado LDR A resul STR A param3 JMP multiplica,I Outro esquema interessante é colocar os parâmetros da subrotina imediatamnte após a instrução de desvio. A subrotina utiliza então o endereço de retorno como ponteiro para esta lista de parâmetros. No caso do exemplo de multiplicacação, a chamada poderia ser: JSR multiplica <valor do primeiro operando> <valor do segundo operando> <endereço do resultado> << instrução seguinte >> A subrotina obteria os parâmetros e atualizaria o endereço de retorno com o seguinte programa: multiplica:NOP Raul F. Weber & Carlos A. L. Lisboa 1-9 LDR A multiplica,I ; obtem valor do primeiro operando STR A param1 LDR multiplica ; atualiza endereço de retorno ADD A #1 STR multiplica LDR A multiplica,I ; obtem valor do segundo operando STR A param2 LDR multiplica ; atualiza endereço de retorno ADD A #1 STR multiplica <multiplicação> LDR A multiplica,I ; obtem endereco do terceiro operando STR A param3 LDR B resul ; obtem resultado da rotina STR B param3, I ; salva resultado no endereço do terceiro parâmetro LDR A multiplica ; atualiza endereço de retorno ADD A #1 STR A multiplica JMP multiplica, I ; retorna da subrotina Em linguagens de baixo nível, a passagem de parâmetros de e para subrotinas é feita obedecendo alguma convenção estabelecida pela equipe de programadores. Podem ser reservados alguns registradores ou alguma área de memória para tal fim. Em linguagens de alto nível, também se segue alguma convenção, estabelecida pelo compilador. 1.8 Programação RAMSES Os recursos adicionais do RAMSES sobre o NEANDER permitem escrever programas mais curtos, mais rápidos e mais legíveis. Para exemplificar isto, considere-se um programa NEANDER para somar (totalizar) n posições consecutivas de memória, a partir do endereço inicial e. Não é feita nenhuma consistência sobre os valores de n e e. Em alto nível, o programa seria: total:=0 ponteiro := e contador := n laço: if contador = 0, termina total := total + mem(ponteiro) ponteiro := ponteiro + 1 contador:= contador – 1 goto laço Considerando a seguinte área de dados na memória: Endereço Conteúdo 128 n 129 e 130 total 131 contador 132 constante 0 (zero) 133 constante 255 (-1) 134 constante 1 (um) Um possível programa NEANDER seria: Raul F. Weber & Carlos A. L. Lisboa1-10 Endereço Instrução 0 LDA 132 ; inicializa (zera) o total 2 STA 130 4 LDA 129 ; inicializa ponteiro 6 STA ponteiro 8 LDA 128 ; inicializa contador 10 STA 131 12 JZ 34 ; testa se contador é zero 14 LDA 130 ; carrega total no acumulador 16 ADD mem(ponteiro) ; soma com posição de memória 18 STA 130 ; atualiza total 20 LDA ponteiro ; incrementa ponteiro 22 ADD 134 24 STA ponteiro 26 LDA 131 ; decrementa contador 28 ADD 133 30 STA 131 32 JMP 12 ; retorna ao início do laço 34 HLT O programa é praticamente uma tradução direta do programa de alto nível. O único ponto crítico está na variável “ponteiro”. O computador NEANDER não tem recursos para trabalhar com ponteiros, e assim a solução adotada é fazer o programa se auto-modificar, ou seja, armazenar a variável “ponteiro” no próprio código do programa. A instrução que soma a posição de memória indicado por ponteiro está no endereço 16, o que significa que o campo de endereço está no byte 17. Esta é a posição da variável “ponteiro”, e com isto o programa fica: Endereço Instrução 0 LDA 132 ; inicializa (zera) o total 2 STA 130 4 LDA 129 ; inicializa ponteiro 6 STA 17 ; na posição 17 8 LDA 128 ; inicializa contador 10 STA 131 12 JZ 34 ; testa se contador é zero 14 LDA 130 ; carrega total no acumulador 16 ADD 0 ; soma com posição de memória 18 STA 130 ; atualiza total 20 LDA 17 ; incrementa ponteiro 22 ADD 134 24 STA 17 26 LDA 131 ; decrementa contador 28 ADD 133 30 STA 131 32 JMP 12 ; retorna ao início do laço 34 HLT No programa acima, dois pontos são importantes: · Quatro instruções (endereços 4, 16, 20 e 24) manipulam um endereço (17) que faz parte do próprio programa. · A instrução do endereço 16 (ADD 17) terá o seu campo de endereço inicializado pela instrução do endereço 6 (STA 17) para o valor de e; e depois consecutivamente incrementado pelas instruções 20 a 24 (LDA 17, ADD 134, STA 17) para e+1, e+2, ... e+31. Raul F. Weber & Carlos A. L. Lisboa 1-11 Transcrevendo o programa para o RAMSES (sem realizar nenhuma alteração quanto a registradores e modos de endereçamento), tem-se a troca dos mnemônicos LDA e STA por LDR e STR e a indicação explícita do uso do registrador A. Endereço Instrução 0 LDR A 132 ; inicializa (zera) o total 2 STR A 130 4 LDR A 129 ; inicializa ponteiro 6 STR A 17 ; na posição 17 8 LDR A 128 ; inicializa contador 10 STR A 131 12 JZ 34 ; testa se contador é zero 14 LDR A 130 ; carrega total no acumulador 16 ADD A 17 ; soma com posição de memória 18 STR A 130 ; atualiza total 20 LDR A 17 ; incrementa ponteiro 22 ADD A 134 24 STR A 17 26 LDR A 131 ; decrementa contador 28 ADD A 133 30 STR A 131 32 JMP 12 ; retorna ao início do laço 34 HLT A primeira alteração a ser realizada está no uso do modo imediato. Três instruções utilizam posições de memória para armazenar constantes. Substituindo a indicação do endereço da constante pela própria indicação da constante, economizam-se três posições de memória na área de dados. Os endereços 132, 133 e 134 não são mais necessários. As alterações estão indicadas em negrito: Endereço Instrução 0 LDR A #0 ; inicializa (zera) o total 2 STR A 130 4 LDR A 129 ; inicializa ponteiro 6 STR A 17 ; na posição 17 8 LDR A 128 ; inicializa contador 10 STR A 131 12 JZ 34 ; testa se contador é zero 14 LDR A 130 ; carrega total no acumulador 16 ADD A 17 ; soma com posição de memória 18 STR A 130 ; atualiza total 20 LDR A 17 ; incrementa ponteiro 22 ADD A #1 24 STR A 17 26 LDR A 131 ; decrementa contador 28 ADD A #255 30 STR A 131 32 JMP 12 ; retorna ao início do laço 34 HLT Área de dados na memória fica então: Endereço Conteúdo 128 n 129 e 130 total 131 contador Raul F. Weber & Carlos A. L. Lisboa1-12 A segunda alteração está no uso do modo indireto para implementar a variável “ponteiro”. Para isto é utilizada o endereço de memória 132. Para acessar a posição de memória apontada pelo ponteiro utiliza-se o modo de endereçamento indireto. As alterações estão indicadas em negrito. Endereço Instrução 0 LDR A #0 ; inicializa (zera) o total 2 STR A 130 4 LDR A 129 ; inicializa ponteiro 6 STR A 132 ; na posição 132 8 LDR A 128 ; inicializa contador 10 STR A 131 12 JZ 34 ; testa se contador é zero 14 LDR A 130 ; carrega total no acumulador 16 ADD A 132,I ; soma com posição de memória 18 STR A 130 ; atualiza total 20 LDR A 132 ; incrementa ponteiro 22 ADD A #1 24 STR A 132 26 LDR A 131 ; decrementa contador 28 ADD A #255 30 STR A 131 32 JMP 12 ; retorna ao início do laço 34 HLT Área de dados na memória: Endereço Conteúdo 128 n 129 e 130 total 131 contador 132 ponteiro A terceira alteração está no uso do registrador B. Como RAMSES possui três registradores, as variáveis (total, contador e ponteiro) não necessitam estar localizadas necessariamente na memória. Transferindo a variável “contador” para o registrador B economiza-se uma posição na área de dados e as instruções de transferência de e para a memória desta variável (posições 10, 26 e 30 no programa acima). Assim, o programa ocupa menos memória e executa mais rápido. As alterações relevantes estão marcadas em negrito (observe-se que alguns endereços são modificados pelo fato que o programa diminuiu). Endereço Instrução 0 LDR A #0 ; inicializa (zera) o total 2 STR A 130 4 LDR A 129 ; inicializa ponteiro 6 STR A 132 8 LDR B 128 ; inicializa contador (reg B) 10 JZ 28 ; testa se contador é zero 12 LDR A 130 ; carrega total no acumulador 14 ADD A 132,I ; soma com posição de memória 16 STR A 130 ; atualiza total 18 LDR A 132 ; incrementa ponteiro 20 ADD A #1 22 STR A 132 24 ADD B #255 ; decrementa contador 26 JMP 10 ; retorna ao início do laço 28 HLT Raul F. Weber & Carlos A. L. Lisboa 1-13 Área de dados na memória: Endereço Conteúdo 128 n 129 e 130 total 132 ponteiro A quarta alteração está no uso do registrador X para a variável “ponteiro”. Isto libera a posição 132 da área de dados, mas requerer uma pequena alteração no modo de endereçamento. Já que o ponteiro está no registrador X, o modo indireto deve ser substituído pelo indexado, onde o endereço base é o endereço zero. Note-se que com isto não está se utilizando o modo indexado na sua capacidade plena (soma de dois valores), mas sim como um “modo registrador indireto”. O programa novamente diminui de tamanho e tem seu tempo de execução reduzido. Isto é consequência da passagens de variáveis de memória para registradores, o que permite eliminar uma série de instruções de movimentação de dados (LDR e STR). Área de dados na memória fica: Endereço Conteúdo 128 n 129 e 130 total E o programa fica (as alterações relevantes estão marcadas em negrito): Endereço Instrução 0 LDR A #0 ; inicializa (zera) o total 2 STR A 130 4 LDR X 129 ; inicializa ponteiro (reg X) 6 LDR B 128 ; inicializa contador (reg B) 8 JZ 22 ; testa se contador é zero 10 LDR A 130 ; carrega total no acumulador 12 ADD A 0,X ; soma com posição de memória 14 STR A 130 ; atualiza total 16 ADD X #1 ; incrementa ponteiro 18 ADD B #255 ; decrementa contador 20 JMP 8 ; retorna ao início do laço 22 HLT A quinta alteração está no uso do registrador A para a variável “total”. Esta alteração vem naturalmente, uma vez que o registrador A não está sendo usando para nenhuma outra finalidade, e assim não existe mais a necessidade de buscar o total da memória e atualizá-lo na memória a cada passagem do laço. Com isto cada registrador tem uma função específica. O registrador A contém o total, B contém o contador e X contém o ponteiro. Note-se que a variável total, localizada no endereço 130, somente é atualizada no fim do programa.Endereço Instrução 0 LDR A #0 ; inicializa (zera) total (reg A) 2 LDR X 129 ; inicializa ponteiro (reg X) 4 LDR B 128 ; inicializa contador (reg B) 6 JZ 16 ; testa se contador é zero 8 ADD A 0,X ; soma com posição de memória 10 ADD X #1 ; incrementa ponteiro 12 ADD B #255 ; decrementa contador 14 JMP 6 ; retorna ao início do laço 16 STR A 130 ; atualiza total Raul F. Weber & Carlos A. L. Lisboa1-14 18 HLT Por questões de legibilidade, a instrução ADD B #225 é na realidade uma subtração e pode ser substituída por um SUB B #1. Com isto a versão final do programa fica: Endereço Instrução 0 LDR A #0 ; inicializa (zera) total (reg A) 2 LDR X 129 ; inicializa ponteiro (reg X) 4 LDR B 128 ; inicializa contador (reg B) 6 JZ 16 ; testa se contador é zero 8 ADD A 0,X ; soma com posição de memória 10 ADD X #1 ; incrementa ponteiro 12 SUB B #1 ; decrementa contador 14 JMP 6 ; retorna ao início do laço 16 STR A 130 ; atualiza total 18 HLT 1.9 Organização Devido aos quatro modos de endereçamento, aos três registradores (A, B e X) e às instruções extras, a organização do RAMSES é mais complexa que a do NEANDER. A seguir são listadas as diversas seqüências de transferências necessárias para realizar cada instrução. Para simplificar estas sequências, o uso alternativo dos registradores A, B e X foi simplesmente indicado por r. Fase de Busca, todas as instruções: REM ¬ PC Read; PC ¬ PC + 1 RI ¬ RDM Execução da instrução NOP Nenhuma operação Execução da instrução STR Modo Direto Modo Indireto Modo Imediato Modo Indexado REM ¬ PC REM ¬ PC PC ¬ PC +1 REM ¬ PC Read; PC ¬ PC +1 Read; PC ¬ PC +1 Read; PC ¬ PC +1 REM ¬ RDM REM ¬ RDM REM ¬ RDM + X RDM ¬ r Read RDM ¬ r Write REM ¬ RDM Write RDM ¬ r Write Execução da instrução LDR Modo Direto Modo Indireto Modo Imediato Modo Indexado REM ¬ PC REM ¬ PC REM ¬ PC REM ¬ PC Read; PC ¬ PC +1 Read; PC ¬ PC +1 Read; PC ¬ PC +1 Read; PC ¬ PC +1 REM ¬ RDM REM ¬ RDM r, N, Z ¬ RDM REM ¬ RDM + X Read Read Read r, N, Z ¬ RDM REM ¬ RDM r, N, Z ¬ RDM Read r, N, Z ¬ RDM Raul F. Weber & Carlos A. L. Lisboa 1-15 Execução da instrução ADD Modo Direto Modo Indireto Modo Imediato Modo Indexado REM ¬ PC REM ¬ PC REM ¬ PC REM ¬ PC Read; PC ¬ PC +1 Read; PC ¬ PC +1 Read; PC ¬ PC +1 Read; PC ¬ PC +1 REM ¬ RDM REM ¬ RDM r,N,Z,C ¬ r + RDM REM ¬ RDM + X Read Read Read r,N,Z,C ¬ r + RDM REM ¬ RDM r,N,Z,C ¬ r + RDM Read r,N,Z,C ¬ r + RDM Execução da instrução OR Modo Direto Modo Indireto Modo Imediato Modo Indexado REM ¬ PC REM ¬ PC REM ¬ PC REM ¬ PC Read; PC ¬ PC +1 Read; PC ¬ PC +1 Read; PC ¬ PC +1 Read; PC ¬ PC +1 REM ¬ RDM REM ¬ RDM r,N,Z ¬ r or RDM REM ¬ RDM + X Read Read Read r,N,Z ¬ r or RDM REM ¬ RDM r,N,Z ¬ r or RDM Read r,N,Z ¬ r or RDM Execução da instrução AND Modo Direto Modo Indireto Modo Imediato Modo Indexado REM ¬ PC REM ¬ PC REM ¬ PC REM ¬ PC Read; PC ¬ PC +1 Read; PC ¬ PC +1 Read; PC ¬ PC +1 Read; PC ¬ PC +1 REM ¬ RDM REM ¬ RDM r,N,Z ¬ r and RDM REM ¬ RDM + X Read Read Read r,N,Z ¬ r and RDM REM ¬ RDM r,N,Z ¬ r and RDM Read r,N,Z ¬ r and RDM Execução da instrução SUB Modo Direto Modo Indireto Modo Imediato Modo Indexado REM ¬ PC REM ¬ PC REM ¬ PC REM ¬ PC Read; PC ¬ PC +1 Read; PC ¬ PC +1 Read; PC ¬ PC +1 Read; PC ¬ PC +1 REM ¬ RDM REM ¬ RDM r,N,Z,C ¬ r - RDM REM ¬ RDM + X Read Read Read r,N,Z,C ¬ r - RDM REM ¬ RDM r,N,Z,C ¬ r - RDM Read r,N,Z,C ¬ r - RDM Execução da instrução NEG r, N, Z, C ¬ – (r) Execução da instrução NOT r, N, Z ¬ not(r) Execução da instrução SHR r, N, Z, C ¬ shr(r) Raul F. Weber & Carlos A. L. Lisboa1-16 Execuções das instruções JMP, JN com N=1, JZ com Z=1, JC com C=1 Modo Direto Modo Indireto Modo Imediato Modo Indexado REM ¬ PC REM ¬ PC PC ¬ PC +1 REM ¬ PC Read Read Read PC ¬ RDM REM ¬ RDM PC ¬ RDM + X Read PC ¬ RDM Execuções das instruções JN com N=1, JZ com Z=1, JC com C=1 (iguais à execução de JMP) Modo Direto Modo Indireto Modo Imediato Modo Indexado REM ¬ PC REM ¬ PC PC ¬ PC +1 REM ¬ PC Read Read Read PC ¬ RDM REM ¬ RDM PC ¬ RDM + X Read PC ¬ RDM Execuções das instruções JN com N=0, JZ com Z=0, JC com C=0 Modo Direto Modo Indireto Modo Imediato Modo Indexado PC ¬ PC +1 PC ¬ PC +1 PC ¬ PC +1 PC ¬ PC +1 Execução da instrução JSR Modo Direto Modo Indireto Modo Imediato Modo Indexado REM ¬ PC REM ¬ PC PC ¬ PC +1 REM ¬ PC Read; PC ¬ PC +1 Read; PC ¬ PC +1 Read; PC ¬ PC +1 temp ¬ RDM REM ¬ RDM temp ¬ RDM + X REM ¬ temp Read REM ¬ temp RDM ¬ PC temp ¬ RDM RDM ¬ PC Write; PC ¬ temp + 1 REM ¬ temp Write; PC ¬ temp + 1 RDM ¬ PC Write; PC ¬ temp + 1 Execução da instrução HLT Parar o processamento As três figuras seguintes mostram três possíveis organizações que implementam as sequências acima. Note-se que os recursos utilizados em termos de registradores, seletores e unidades aritméticas variam em função da forma exata como as diversas seqüências são implementadas. A primeira organização (figura 1.6) utiliza duas unidades aritméticas. Uma, com maiores capacidades, é utilizada para implementar as instruções, e a outra, mais especializada, é usada especificamente para tratar o modo de endereçamento indexado. Raul F. Weber & Carlos A. L. Lisboa 1-17 A segunda organização (figura 1.7) utiliza somente uma unidade aritmética, tratado a soma do modo indexado também na UAL das instruções. Isto altera significativamente os caminhos (ligações) entre os registradores, notadamente o PC e o RDM. A terceira organização (figura 1.8) introduz um elemento extra, o registrador auxiliar (Raux), mas simplifica as ligações entre os registradores. Note-se que nesta organização todos os registradores (com exceção do RI) recebem o seu valor da UAL, ou seja, todas as transferências passam pela UAL (com exceção de RI <- RDM). A escolha final entre estas três organizações (e outras possíveis) deve ser feita levando-se em conta diversos fatores: • velocidade de execução • número de elementos utilizados, seus tipos e conexões • elementos disponíveis • potencialidade de inclusão de novas instruções, registradores e modos de endereçamento • facilidade de implementação de outras arquiteturas • facilidade de projeto • automatização do projeto Estes fatores saem do escopo desta apostilha, e serão analisados em outras disciplinas. Raul F. Weber & Carlos A. L. Lisboa1-18 s3 , s4 R X R B R A R D M R E M M E M + U A L X Y C N Z P C U n id a d e d e C o n tr o le S in a is d e C o n tr o le p a ra a U C P ca rg a R X ca rg a R B ca rg a R A ca rg a P C ca rg a R E M ca rg a R D M re a d w ri te s1 , s2 O p e ra çõ e s d a U A L X + Y X - Y X a n d Y X o r Y n o t X n e g X sh r X Y s5 , s6 s7 M E R E G C ó d . O p . R I ca rg a R I D E C O D . ca rr y i n ca rg a N /Z ca rg a C in cr e m e n ta r P C Figura 1.6 - Organização do RAMSES com duas unidades aritméticas Raul F. Weber & Carlos A. L. Lisboa 1-19 s3 ,s 4 R X R B R A R D M R E M M E M U A L X Y C N Z P C U n id a d e d e C o n tr o le S in a is d e C o n tr o le p a ra a U C P ca rg a R X ca rg a R B ca rg a R A ca rg a P C ca rg a R E M ca rg a R D M re a d w ri tes1 , s2 O p e ra çõ e s d a U A L X + Y X - Y X a n d Y X o r Y n o t X n e g X sh r X Y s5 M E R E G C ó d . O p . R I ca rg a R I D E C O D . ca rr y i n ca rg a N /Z ca rg a C in cr e m e n ta r P C Figura 1.7 - Organização do RAMSES com uma única unidade aritmética Raul F. Weber & Carlos A. L. Lisboa1-20 R X R B R A R D M R E M M E M U A L X Y C N Z P C U n id a d e d e C o n tr o le S in a is d e C o n tr o le p a ra a U C P ca rg a R X ca rg a R B ca rg a R A ca rg a P C ca rg a R E M ca rg a R D M re a d w ri te s1 , s2 O p e ra çõ e s d a U A L X X + Y X - Y X a n d Y X o r Y n o t X n e g X sh r X Y M E R E G C ó d . O p . R I ca rg a R I D E C O D . ca rr y i n ca rg a N /Z ca rg a C in cr e m e n ta r P C s3 ,s 4 R a u x ca rg a R a u x Figura 1.8 - Organização do RAMSES com registrador auxiliar Raul F. Weber & Carlos A. L. Lisboa 1-21 1.10 Conclusão RAMSES, apesar de mais poderoso que NEANDER no tocante aos recursos de programação, ainda é um computador muito simples. Processadores modernos são ainda mais sofisticados que RAMSES, apesar de possuírem os mesmos elementos básicos. 1.11 Exercícios Os exercícios apresentados aqui devem ser programados em RAMSES. Para todos os programas sugeridos, vale a seguinte convenção: início do programa - posição 0 - 0H início da área de dados- posição 128 - 80H Essa convenção é adotada apenas para facilitar a correção dos programas. 1. Explique a diferença entre as seguintes instruções: LDR B 128 LDR B 128,I LDR B #128 LDR B 128,X Considerando que a posição 128 contém 130, a posição 130 contém 128, e o registrador X contém 2, qual o conteúdo dos registradores A, B e X após a execução de cada uma das instruções acima? 2. Somar duas variáveis de 16 bits: faça um programa para somar duas variáveis de 16 bits representadas em complemento de dois. As variáveis e o resultado estão dispostos segundo o mapa de memória abaixo: posição 128: byte mais significativo da primeira variável posição 129: byte menos significativo da primeira variável posição 130: byte mais significativo da segunda variável posição 131: byte menos significativo da segunda variável posição 132: byte mais significativo do resultado posição 133: byte menos significativo do resultado 3. Limpeza de uma área de memória de n posições: faça um programa para zerar um número qualquer de posições consecutivas na memória. O número de posições é determinado pelo conteúdo da posição 128 de memória, e a posição inicial da memória a ser zerada é dada pelo conteúdo da posição 129 de memória. posição 128: número de posições posição 129: posição inicial 4. Movimento de blocos de n posições: faça um programa para mover (sem zerar a origem) um número qualquer de posições consecutivas na memória. O número de posições é determinado pelo conteúdo da posição 128 de memória, a posição inicial do bloco de memória a ser movido é dada pelo conteúdo da posição 129 de memória e endereço inicial do bloco de destino é dado pela posição 130. posição 128: número de posições posição 129: posição inicial da origem posição 130: posição inicial do destino 5. Multiplicação: faça um programa que multiplique duas variáveis positivas de 8 bits e forneça o resultado em 16 bits. Raul F. Weber & Carlos A. L. Lisboa1-22 posição 128: multiplicando posição 129: multiplicador posição 130: resultado (byte mais significativo) posição 131: resultado (byte menos significativo) 6. Multiplicação: faça um programa que multiplique duas variáveis positivas de 8 bits e forneça o resultado em 8 bits, indicando a ocorrência de overflow. posição 128:multiplicando posição 129:multiplicador posição 130:resultado posição 131:conteúdo = 0H quando não ocorreu overflow conteúdo = FFH quando ocorreu overflow 7. Conversão de código: faça um programa que converta 3 dígitos numéricos codificados em ASCII em um número binário positivo em complemento de dois armazenado em 16 bits e indique a ocorrência de overflow na conversão. posição 129: dígito ASCII mais significativo até posição 131: dígito ASCII menos significativo posição 132: resultado posição 133:conteúdo = 0H quando não ocorreu overflow conteúdo = FFH quando ocorreu overflow 8. Conversão de código: idem ao (6) mas com a posição 128 contendo um caracter ASCII espaço ou "+" indicando números positivos e "-" indicando números negativos. O resultado será positivo ou negativo, dependendo desse caracter. 9. Subrotinas: o programa (6) deve ser escrito como uma subrotina e ser chamado em um programa principal (por exemplo, o do exercício 8). 10. Subrotinas: escrever uma subrotina para contar o número de bits que estão com valor 1 em uma palavra cujo endereço está armazenado na posição 128 da memória.
Compartilhar