Transições incondicionais. Noções básicas de programação de dispositivos MP (Aula) Comandos de transferência de controle

  • 10.01.2024

Junto com os meios de cálculos aritméticos, o sistema de instruções do microprocessador também possui meios de conversão lógica de dados. Por lógico queremos dizer tais transformações de dados, que são baseadas em regras da lógica formal.

A lógica formal funciona no nível de afirmações verdadeiras e falsas. Para um microprocessador, isso geralmente significa 1 e 0, respectivamente. O computador é nativo da linguagem de zeros e uns, mas a menor unidade de dados na qual as instruções de máquina operam é o byte. Entretanto, no nível do sistema, muitas vezes é necessário poder operar em um nível extremamente baixo – o nível de bits.

Arroz. 29. Ferramentas lógicas de processamento de dados


Os meios de transformação lógica de dados incluem comandos lógicos e operações lógicas. O operando de uma instrução assembler geralmente pode ser uma expressão, que por sua vez é uma combinação de operadores e operandos. Entre esses operadores também podem existir operadores que implementam operações lógicas em objetos de expressão.

Antes de examinar essas ferramentas em detalhes, vamos considerar o que são os dados lógicos em si e quais operações são executadas neles.

Dados lógicos

A base teórica para o processamento lógico de dados é lógica formal. Existem vários sistemas de lógica. Um dos mais famosos é cálculo proposicional. Uma afirmação é qualquer afirmação que possa ser dita tanto para verdadeiro, ou falso.

O cálculo proposicional é um conjunto de regras usadas para determinar a verdade ou falsidade de alguma combinação de afirmações.

O cálculo proposicional é combinado de forma muito harmoniosa com os princípios de operação do computador e os métodos básicos de sua programação. Todos os componentes de hardware do computador são construídos em chips lógicos. O sistema de representação de informações em um computador de nível inferior é baseado no conceito de bit. Um bit, tendo apenas dois estados (0 (falso) e 1 (verdadeiro)), cabe naturalmente no cálculo proposicional.

De acordo com a teoria, as seguintes operações lógicas podem ser realizadas em instruções (em bits).


1. Negação (lógica NÃO) - uma operação lógica em um operando cujo resultado é o inverso do operando original.

Esta operação é caracterizada exclusivamente pela seguinte tabela verdade (Tabela 12).

Tabela 12. Tabela verdade para negação lógica

2. Adição lógica (lógica inclusiva OU) - uma operação lógica em dois operandos cujo resultado é verdadeiro (1) se um ou ambos os operandos forem verdadeiros (1) e falso (0) se ambos os operandos forem falsos (0).

Esta operação é descrita usando a seguinte tabela verdade (Tabela 13).

Tabela 13. Tabela verdade para OR inclusivo lógico

3. Multiplicação lógica (lógica E) - uma operação lógica em dois operandos que é avaliada como verdadeira (1) somente se ambos os operandos forem avaliados como verdadeiro (1). Em todos os outros casos, o valor da operação é falso (0).

Esta operação é descrita usando a seguinte tabela verdade (Tabela 14).

Tabela 14. Tabela verdade para AND lógico

4. Adição exclusiva lógica (exclusiva lógica OU) - uma operação lógica em dois operandos cujo resultado é verdadeiro (1) se apenas um dos dois operandos for verdadeiro (1) e falso (0) se ambos os operandos forem falsos (0) ou "verdadeiros" (1). Esta operação é descrita usando a seguinte tabela verdade (Tabela 15).

Tabela 15. Tabela verdade para OR exclusivo lógico

O sistema de instruções do microprocessador contém cinco instruções que suportam essas operações. Estas instruções realizam operações lógicas nos bits dos operandos. As dimensões dos operandos, naturalmente, devem ser iguais. Por exemplo, se o tamanho dos operandos for uma palavra (16 bits), então a operação lógica é executada primeiro nos bits zero dos operandos e seu resultado é escrito no lugar do bit 0 do resultado. Em seguida, o comando repete sequencialmente essas ações em todos os bits, do primeiro ao décimo quinto.

Comandos lógicos

O sistema de instruções do microprocessador possui o seguinte conjunto de comandos que suportam o trabalho com dados lógicos:

1) e operando_1, operando_2 – operação de multiplicação lógica. O comando executa uma operação AND lógica bit a bit (conjunção) nos bits dos operandos operando_1 e operando_2. O resultado é gravado no operando_1;

2) e operando_1, operando_2 – operação de adição lógica. O comando executa uma operação OR lógica bit a bit (disjunção) nos bits dos operandos operando_1 e operando_2. O resultado é gravado no operando_1;

3) hog operando_1, operando_2 – operação de adição lógica exclusiva. A instrução executa uma operação OR exclusiva lógica bit a bit nos bits dos operandos operando_1 e operando_2. O resultado é escrito no lugar do operando;

4) testar operando_1, operando_2 – operação de “verificação” (usando multiplicação lógica). O comando executa uma operação AND lógica bit a bit nos bits dos operandos operando_1 e operando_2. O estado dos operandos permanece o mesmo, apenas os flags zf, sf e pf mudam, o que permite analisar o estado dos bits individuais do operando sem alterar seu estado;

5) não operando – operação de negação lógica. O comando realiza uma inversão bit a bit (substituindo o valor pelo oposto) de cada bit do operando. O resultado é escrito no lugar do operando.

Para compreender o papel das instruções lógicas no sistema de instruções do microprocessador, é muito importante compreender o escopo de sua aplicação e as técnicas típicas para utilizá-las na programação.

Usando comandos lógicos é possível alocação bits individuais no operando com a finalidade de configurar, redefinir, inverter ou simplesmente verificar um determinado valor.

Para organizar esse trabalho com bits, o operando_2 geralmente desempenha o papel de uma máscara. Utilizando os bits definidos em 1 bit desta máscara, são determinados os bits operando_1 necessários para uma operação específica. Vamos mostrar quais comandos lógicos podem ser usados ​​para esse propósito:

1) para definir certos bits como 1, use o comando og operando_1, operando_2.

Nesta instrução, o operando_2, que atua como máscara, deve conter um bit no lugar daqueles bits que devem ser definidos como 1 no operando_1;

2) para redefinir determinados bits para 0, use o comando e operando_1, operando_2.

Nesta instrução, o operando_2, que atua como máscara, deve conter zero bits no lugar daqueles bits que devem ser definidos como 0 no operando_1;

3) comando hog operando_1, operando_2 é aplicado:

a) descobrir quais bits no operando_1 e no operando são diferentes;

b) inverter o estado dos bits especificados no operando_1.

Ao executar o comando hog, os bits da máscara que nos interessam (operando_2) devem ser um, o restante deve ser zero;

Para verificar o status dos bits especificados, use o comando test operando_1, operando_2 (check operando_1).

Os bits verificados do operando_1 na máscara (operando_2) devem ter valor um. O funcionamento do comando test é semelhante ao algoritmo do comando and, mas não altera o valor do operando_1. O resultado do comando é definir o valor do sinalizador zero zf:

1) se zf = 0, então a multiplicação lógica resultou em resultado zero, ou seja, um bit unitário da máscara, que não correspondeu ao bit correspondente do operando;

2) se zf = 1, então a multiplicação lógica resultou em um resultado diferente de zero, ou seja, pelo menos um o bit da máscara corresponde ao bit correspondente do operando_1.

Para reagir ao resultado do comando de teste, é aconselhável utilizar o comando de salto jnz label (Jump if Not Zero) - pular se o sinalizador zero zf for diferente de zero, ou um comando com ação oposta - jz label (Jump if Zero) - salta se o sinalizador zero zf = 0.

Os próximos dois comandos procuram o primeiro bit do operando definido como 1. Você pode pesquisar do início ou do final do operando:

1) bsf operando_1, operando_2 (Bit Scanning Forward) – varredura de bits para frente. A instrução varre os bits do operando_2 do menos significativo para o mais significativo (do bit 0 ao bit mais significativo) procurando o primeiro bit definido como 1. Se for encontrado, o número deste bit é inserido no operando_1 como um valor inteiro. Se todos os bits do operando_2 forem 0, então o sinalizador zero zf será definido como 1, caso contrário, o sinalizador zf será redefinido para 0;

2) bsr operando_1, operando_2 (Bit Scanning Reset) – varredura de bits na ordem inversa. A instrução procura (varre) os bits do operando_2 do mais significativo para o menos significativo (do bit mais significativo para o bit 0) procurando o primeiro bit definido como 1. Se for encontrado, o número deste bit é inserido no operando_1 como um valor inteiro. É importante que a posição do primeiro bit à esquerda ainda seja contada em relação ao bit 0. Se todos os bits do operando_2 forem iguais a 0, então o sinalizador zero zf será definido como 1, caso contrário, o sinalizador zf será redefinido para 0 .

Nos modelos mais recentes de microprocessadores Intel, vários outros comandos apareceram no grupo de comandos lógicos que permitem acesso a um bit específico do operando. O operando pode estar localizado na memória ou em um registrador de uso geral. A posição do bit é especificada pelo deslocamento do bit em relação ao bit menos significativo do operando. O valor de deslocamento pode ser especificado como um valor direto ou contido em um registro de uso geral. Você pode usar os resultados dos comandos bsr e bsf como valor de deslocamento. Todas as instruções atribuem o valor do bit selecionado ao flag CE

1) operando bt, deslocamento de bit (teste de bit) – verifique o bit. O comando transfere o valor do bit para o sinalizador cf;

2) operando bts, deslocamento de bit (Bit Test and Set) – verificação e configuração do bit. A instrução transfere o valor do bit para o flag CF e então define o bit a ser testado como 1;

3) btr operacional, bit offset (Bit Test and Reset) – verificação e reset do bit. A instrução transfere o valor de um bit para o flag CF e então define esse bit como 0;

4) operando btc, deslocamento de bit (Bit Test and Convert) – verifica e inverte o bit. A instrução transfere o valor de um bit para o sinalizador cf e então inverte o valor desse bit.

Comandos de mudança

As instruções deste grupo também fornecem manipulação de bits individuais dos operandos, mas de uma forma diferente das instruções lógicas discutidas acima.

Todas as instruções de deslocamento movem bits no campo do operando para a esquerda ou para a direita, dependendo do código de operação. Todas as instruções shift têm a mesma estrutura - operando cop, shift_counter.

Número de bits deslocados – contador_de_shift – está localizado no lugar do segundo operando e pode ser especificado de duas maneiras:

1) estatisticamente, que envolve a especificação de um valor fixo usando um operando imediato;

2) dinamicamente, o que significa armazenar o valor do contador de deslocamento no registrador cl antes de executar a instrução shift.

Com base no tamanho do registrador cl, fica claro que o valor do contador de deslocamento pode variar de 0 a 255. Mas, na verdade, isso não é inteiramente verdade. Para fins de otimização, o microprocessador aceita apenas o valor cinco bits menos significativos contador, ou seja, o valor varia de 0 a 31.

Todos os comandos shift definem o sinalizador de transporte cf.

À medida que os bits são deslocados além do operando, eles primeiro atingem o sinalizador de transporte, definindo-o como igual ao valor do próximo bit que termina fora do operando. O próximo destino desse bit depende do tipo de instrução de deslocamento e do algoritmo do programa.

Com base no princípio de funcionamento, os comandos shift podem ser divididos em dois tipos:

1) comandos de deslocamento linear;

2) comandos de mudança cíclica.

Comandos de mudança linear

Comandos deste tipo incluem comandos que realizam uma mudança de acordo com o seguinte algoritmo:

1) o próximo bit “empurrado” define o sinalizador CF;

2) o bit introduzido no operando pela outra extremidade tem o valor 0;

3) quando o próximo bit é deslocado, ele vai para o sinalizador CF e o valor do bit deslocado anterior é perdido! Os comandos de deslocamento linear são divididos em dois subtipos:

1) comandos lógicos de mudança linear;

2) comandos de deslocamento linear aritmético.

Os comandos de deslocamento linear lógico incluem o seguinte:

1) operando shl, shift_counter (Shift Logical Left) – deslocamento lógico para a esquerda. O conteúdo do operando é deslocado para a esquerda pelo número de bits determinado pelo valor shift_count. À direita (na posição do bit menos significativo) são inseridos zeros;

2) operando shr, shift_counter (Shift Logical Right) – deslocamento lógico para a direita. O conteúdo do operando é deslocado para a direita pelo número de bits determinado pelo valor shift_count. À esquerda (na posição do bit de sinal mais significativo) são inseridos zeros.

A Figura 30 mostra como esses comandos funcionam.

Arroz. 30. Esquema de operação de comandos de mudança lógica linear


As instruções de deslocamento linear aritmético diferem das instruções de deslocamento lógico porque operam de maneira especial no bit de sinal do operando.

1) operando sal, shift_counter (Shift Arithmetic Left) – deslocamento aritmético para a esquerda. O conteúdo do operando é deslocado para a esquerda pelo número de bits determinado pelo valor shift_count. À direita (na posição do bit menos significativo) estão zeros. O comando sal não preserva o sinal, mas define bandeira com/em caso de mudança de sinal outra broca retrátil. Caso contrário, o comando sal é completamente semelhante ao comando shl;

2) operando sar, shift_counter (Shift Arithmetic Right) – deslocamento aritmético para a direita. O conteúdo do operando é deslocado para a direita pelo número de bits determinado pelo valor contador_de_shift.À esquerda, zeros são inseridos no operando. O comando sar preserva o sinal, restaurando-o após mudar cada bit seguinte.

A Figura 31 mostra como funcionam as instruções de deslocamento aritmético linear.


Arroz. 31. Esquema de operação de comandos de deslocamento aritmético linear

Comandos de rotação

Comandos Rotate Shift são comandos que armazenam os valores dos bits que estão sendo deslocados. Existem dois tipos de comandos de rotação:

1) comandos simples de mudança cíclica;

2) comandos de deslocamento cíclico através do sinalizador de transporte cf.

Para as equipes cíclico simples os turnos incluem:

1) operando rol, shift_counter (Girar para a esquerda) – deslocamento cíclico para a esquerda. O conteúdo do operando é deslocado para a esquerda pelo número de bits determinado pelo operando contador_de_shift. Os bits deslocados para a esquerda são gravados no mesmo operando à direita;

2) operando gog, shift_counter (Rotate Right) – deslocamento cíclico para a direita. O conteúdo do operando é deslocado para a direita pelo número de bits determinado pelo operando contador_de_shift. Os bits deslocados para a direita são gravados no mesmo operando à esquerda.

Arroz. 32. Esquema de operação de comandos simples de deslocamento cíclico


Como pode ser visto na Figura 32, instruções simples de deslocamento cíclico executam uma ação útil durante sua operação, a saber: o bit deslocado ciclicamente não é apenas empurrado para o operando a partir da outra extremidade, mas ao mesmo tempo seu valor se torna o valor do Bandeira CE

Comandos de rotação via carry flag CF diferem dos comandos simples de deslocamento cíclico porque o bit que está sendo deslocado não vai imediatamente para o operando de sua outra extremidade, mas é primeiro escrito no sinalizador de transporte CE Somente a próxima execução desta instrução shift (assumindo que ela seja executada em um loop) resulta no bit deslocado anteriormente sendo colocado na outra extremidade do operando.(Fig. 33).

Para comandos de mudança cíclica via bandeira de transporte o seguinte está relacionado:

1) operando rcl, shift_counter (Rotate through Carry Left) – deslocamento cíclico para a esquerda através de carry.

O conteúdo do operando é deslocado para a esquerda pelo número de bits determinado pelo operando contador_de_shift. Os bits deslocados tornam-se alternadamente o valor do sinalizador de transporte cf.

2) operando rcg, shift_counter (Rotate through Carry Right) – deslocamento cíclico para a direita através do carry.

O conteúdo do operando é deslocado para a direita pelo número de bits determinado pelo operando contador_de_shift. Os bits deslocados tornam-se alternadamente o valor do sinalizador de transporte CF.

Arroz. 33. Comandos de mudança cíclica via carry flag CF


Da Figura 33 fica claro que ao mudar através do sinalizador de transporte, aparece um elemento intermediário, com a ajuda do qual, em particular, é possível substituir bits deslocados ciclicamente, em particular, incompatibilidade sequências de bits.

Por incompatibilidade de uma sequência de bits daqui em diante entendemos uma ação que nos permite de alguma forma localizar e extrair as seções necessárias desta sequência e gravá-las em outro local.

Comandos de mudança adicionais

O sistema de comando dos modelos mais recentes de microprocessadores Intel, começando com o i80386, contém comandos shift adicionais que expandem os recursos discutidos anteriormente. Estes são comandos de mudança dupla precisão: 1) shld operando_1, operando_2, shift_counter – deslocamento à esquerda de precisão dupla. O comando shld realiza uma substituição deslocando os bits do operando_1 para a esquerda, preenchendo seus bits à direita com os valores dos bits deslocados do operando_2 conforme diagrama da Fig. 34. O número de bits a serem deslocados é determinado pelo valor contador_de_shift, operando_2 não muda.


Arroz. 34. Esquema do comando shld


2) shrd operando_1, operando_2, shift_counter – deslocamento para a direita de precisão dupla. A instrução realiza a substituição deslocando os bits do operando_1 para a direita, preenchendo seus bits à esquerda com os valores dos bits deslocados do operando_2 conforme diagrama da Figura 35. A quantidade de bits deslocados é determinada pelo valor contador_de_shift, que pode estar no intervalo 0... 31. Este valor pode ser especificado como um operando imediato ou contido no registro cl. Significado operando_2 não muda.

Arroz. 35. Esquema do comando shrd


Como observamos, os comandos shld e shrd realizam deslocamentos de até 32 bits, mas devido às peculiaridades de especificação dos operandos e do algoritmo de operação, esses comandos podem ser utilizados para trabalhar com campos de até 64 bits de comprimento.

2. Comandos de transferência de controle

Conhecemos algumas das equipes que compõem linear seções do programa. Cada um deles geralmente executa algumas ações para converter ou transferir dados, após as quais o microprocessador transfere o controle para o próximo comando. Mas muito poucos programas funcionam de forma tão consistente. Geralmente há pontos em um programa nos quais uma decisão deve ser tomada sobre qual comando será executado em seguida. Esta solução poderia ser:

1) incondicional - neste ponto é necessário transferir o controle não para o próximo comando, mas para outro, que esteja localizado a alguma distância do comando atual;

2) condicional - a decisão sobre qual comando será executado a seguir é tomada com base na análise de algumas condições ou dados.

Um programa é uma sequência de comandos e dados que ocupam uma certa quantidade de espaço na RAM. Este espaço de memória pode ser contíguo ou composto de múltiplos fragmentos.

O microprocessador sabe qual instrução de programa deve ser executada em seguida pelo conteúdo de um par de registradores cs:(e)ip:

1) cs – registrador de código de segmento, que contém o endereço físico (base) do segmento de código atual;

2) eip/ip – registrador de ponteiro de instrução, que contém um valor que representa o deslocamento de memória da próxima instrução a ser executada em relação ao início do segmento de código atual.

Qual registro específico será usado depende se o modo de endereçamento está definido como use16 ou use32. Se use 16 for especificado, então ip será usado, se use32, então eip será usado.

Assim, as instruções de transferência de controle alteram o conteúdo dos registradores cs e eip/ip, como resultado o microprocessador seleciona para execução não o próximo comando do programa na ordem, mas um comando em alguma outra seção do programa. O transportador dentro do microprocessador é reiniciado.

Com base no princípio de funcionamento, os comandos do microprocessador que garantem a organização das transições no programa podem ser divididos em 3 grupos:

1. Comandos para transferência incondicional de controle:

1) comando de salto incondicional;

2) comando para chamar um procedimento e retornar de um procedimento;

3) comando para chamar interrupções de software e retornar de interrupções de software.

2. Transferência condicional de comandos de controle:

1) comandos de salto com base no resultado do comando de comparação de páginas;

2) comandos de transição baseados no estado de uma determinada bandeira;

3) comandos para navegar pelo conteúdo do registro ecx/cx.

3. Comandos de controle de ciclo:

1) comando para organização de ciclo com contador ecx/cx;

2) um comando para organizar um ciclo com contador ecx/cx com possibilidade de saída antecipada do ciclo sob condição adicional.

Saltos incondicionais

A discussão anterior revelou alguns detalhes do mecanismo de transição. As instruções de salto modificam o registro do ponteiro de instrução eip/ip e possivelmente o registro do segmento de código cs. O que exatamente precisa ser modificado depende de:

1) sobre o tipo de operando no comando de salto incondicional (próximo ou distante);

2) da indicação antes do endereço de salto (no comando de salto) modificador; neste caso, o próprio endereço de salto pode estar localizado diretamente no comando (salto direto) ou em um registro ou célula de memória (salto indireto).

Modificador pode assumir os seguintes valores:

1) próximo ao ptr – transição direta para um rótulo dentro do segmento de código atual. Somente o registro eip/ip é modificado (dependendo do tipo de segmento de código especificado use16 ou use32) com base no endereço (rótulo) especificado no comando ou em uma expressão usando o caractere de extração de valor - $;

2) far ptr – transição direta para um rótulo em outro segmento de código. O endereço de salto é especificado como um operando imediato ou endereço (rótulo) e consiste em um seletor de 16 bits e um deslocamento de 16/32 bits, que são carregados nos registradores cs e ip/eip, respectivamente;

3) palavra ptr – transição indireta para um rótulo dentro do segmento de código atual. Somente eip/ip é modificado (pelo valor de deslocamento da memória no endereço especificado no comando ou do registro). Tamanho de deslocamento 16 ou 32 bits;

4) dword ptr – transição indireta para um rótulo em outro segmento de código. Ambos os registradores – cs e eip/ip – são modificados (por um valor da memória - e somente da memória, de um registrador). A primeira palavra/dword deste endereço representa o deslocamento e é carregada em ip/eip; a segunda/terceira palavra é carregada em cs. comando de salto incondicional jmp

A sintaxe do comando de salto incondicional é jmp [modificador] jump_address - um salto incondicional sem armazenar informações sobre o ponto de retorno.

O jump_address é um endereço de rótulo ou o endereço da área de memória onde o ponteiro de salto está localizado.

No total, o sistema de instruções do microprocessador contém vários códigos de instrução de máquina de salto incondicional jmp.

Suas diferenças são determinadas pela distância de transição e pelo método de especificação do endereço de destino. Faixa a transição é determinada pela localização do operando endereço_de_transição. Este endereço pode estar no segmento de código atual ou em algum outro segmento. No primeiro caso, a transição é chamada intrasegmentar, ou entes queridos, no segundo - intersegmentar, ou distante Um salto intra-segmento assume que apenas o conteúdo do registro eip/ip é alterado.

Existem três opções para uso intrasegmento do comando jmp:

1) direto curto;

2) direto;

3) indireto.


Procedimentos

A linguagem assembly possui diversas ferramentas que resolvem o problema de duplicação de seções de código de programa. Esses incluem:

1) mecanismo de procedimentos;

2) macro montador;

3) mecanismo de interrupção.

O procedimento, muitas vezes chamado sub-rotina - esta é a unidade funcional básica de decomposição (divisão em várias partes) de alguma tarefa. Um procedimento é um grupo de comandos para resolver uma subtarefa específica e possui os meios de obter controle a partir do ponto de chamar uma tarefa de nível superior e devolver o controle a este ponto.

No caso mais simples, um programa pode consistir em um procedimento. Em outras palavras, um procedimento pode ser definido como um conjunto de comandos formatados corretamente, que, uma vez descritos, podem ser chamados, se necessário, em qualquer lugar do programa.

Para descrever uma sequência de comandos como um procedimento, a linguagem assembly usa duas diretivas: PROC e ENDP.

A sintaxe para descrever o procedimento é a seguinte (Fig. 36).


Arroz. 36. Sintaxe para descrever um procedimento em um programa


Na Figura 36 pode-se observar que no cabeçalho do procedimento (diretiva PROC) apenas o nome do procedimento é necessário. Dentre o grande número de operandos da diretriz PROC, [distância] merece destaque especial. Este atributo pode assumir valores próximos ou distantes e caracteriza a possibilidade de chamar um procedimento a partir de outro segmento de código. Por padrão, o atributo [distância] está definido como próximo.

O procedimento pode ser colocado em qualquer lugar do programa, mas de forma que o controle não caia acidentalmente sobre ele. Se um procedimento for simplesmente inserido no fluxo de comando geral, o microprocessador perceberá os comandos do procedimento como parte desse fluxo e, consequentemente, executará os comandos do procedimento.

Saltos condicionais

O microprocessador possui 18 instruções de salto condicional. Esses comandos permitem que você verifique:

1) a relação entre operandos assinados (“mais – menos”);

2) a relação entre operandos sem sinal (“acima – abaixo”);

3) estados das bandeiras aritméticas ZF, SF, CF, OF, PF (mas não AF).

Os comandos de salto condicional têm a mesma sintaxe:

jcc transição_rótulo

Como você pode ver, o código mnemônico de todos os comandos começa com “j” - da palavra pular(quicar), dela - define a condição específica analisada pelo comando.

Em relação ao operando rótulo_de_transição, então esse rótulo só pode ser localizado dentro do segmento de código atual; a transferência de controle entre segmentos em transições condicionais não é permitida. Nesse sentido, desaparece a questão do modificador, que estava presente na sintaxe dos comandos de salto incondicional. Nos primeiros modelos de microprocessadores (i8086, i80186 e i80286), as instruções de salto condicional só podiam fazer saltos curtos - uma distância de -128 a +127 bytes da instrução seguinte à instrução de salto condicional. A partir do modelo de microprocessador 80386, essa limitação foi removida, mas, como você pode ver, apenas dentro do segmento de código atual.

Para tomar uma decisão sobre para onde o controle será transferido com um comando de salto condicional, primeiro deve ser gerada uma condição com base na qual será tomada a decisão de transferir o controle.

As fontes de tal condição podem ser:

1) qualquer comando que altere o estado dos sinalizadores aritméticos;

2) a página de comando compare, que compara os valores de dois operandos;

3) estado do registro ecx/cx.


comando de comparação cmp

O comando compare page tem um princípio de funcionamento interessante. É absolutamente igual ao comando de subtração - suboperando, operando_2.

O comando page, assim como o subcomando, subtrai operandos e define sinalizadores. A única coisa que não faz é escrever o resultado da subtração no lugar do primeiro operando.

A sintaxe do comando page é página operando_1, operando_2 (comparar) – compara dois operandos e define sinalizadores com base nos resultados da comparação.

Os sinalizadores definidos pelo comando page podem ser analisados ​​usando comandos especiais de ramificação condicional. Antes de examiná-los, vamos prestar um pouco de atenção aos mnemônicos desses comandos de salto condicional (Tabela 16). Compreender a notação ao formar os nomes dos comandos de salto condicional (o elemento no nome do comando jcc, designado por nós) facilitará sua memorização e posterior uso prático.

Tabela 16. Significado das abreviaturas no nome do comando jcc
Tabela 17. Lista de comandos de salto condicional para página de comando operando_1, operando_2

Não se surpreenda com o fato de que os mesmos valores de sinalizador correspondem a vários códigos mnemônicos diferentes de comandos de salto condicional (eles são separados uns dos outros por uma barra na Tabela 17). A diferença no nome se deve ao desejo dos projetistas de microprocessadores de facilitar o uso de instruções de salto condicional em combinação com certos grupos de instruções. Portanto, nomes diferentes refletem orientações funcionais diferentes. Porém, o fato desses comandos responderem aos mesmos flags os torna absolutamente equivalentes e iguais no programa. Portanto, na Tabela 17 eles são agrupados não por nome, mas pelos valores das bandeiras (condições) aos quais reagem.


Instruções e sinalizadores de ramificação condicional

A notação mnemônica para alguns comandos de salto condicional reflete o nome do sinalizador em que operam e tem a seguinte estrutura: o caractere "j" vem primeiro. (Pular, transição), o segundo é a designação da bandeira ou o símbolo de negação “n”, seguido do nome da bandeira. Esta estrutura de equipe reflete seu propósito. Se não houver o caracter “n”, então o estado do sinalizador é verificado; se for igual a 1, é feita uma transição para o rótulo de salto. Se o caractere “n” estiver presente, o estado do sinalizador será verificado quanto à igualdade 0 e, se for bem-sucedido, um salto será feito para o rótulo de salto.

Os códigos mnemônicos de comando, os nomes dos sinalizadores e as condições de transição são fornecidos na Tabela 18. Esses comandos podem ser usados ​​após qualquer comando que altere os sinalizadores especificados.

Tabela 18. Comandos e sinalizadores de salto condicional

Se você observar atentamente as Tabelas 17 e 18, poderá ver que muitos dos comandos de salto condicional nelas são equivalentes, já que ambos são baseados na análise dos mesmos sinalizadores.


Instruções de salto condicional e o registro ecx/cx

A arquitetura do microprocessador envolve o uso específico de muitos registradores. Por exemplo, o registro EAX/AX/AL é usado como acumulador, e os registros BP e SP são usados ​​para trabalhar com a pilha. O registro ESH/CX também tem uma finalidade funcional específica: desempenha a função contador em comandos de controle de loop e ao trabalhar com cadeias de caracteres. É possível que funcionalmente o comando de salto condicional associado ao registro ecx/cx seja classificado mais corretamente como este grupo de comandos.

A sintaxe para este comando de ramificação condicional é:

1) jcxz jump_label (Pular se ex for Zero) – pular se cx for zero;

2) jecxz jump_label (Jump Equal exx Zero) – salta se exx for zero.

Esses comandos são muito convenientes para usar ao organizar um loop e ao trabalhar com sequências de caracteres.

Deve-se observar que existe uma limitação inerente ao comando jcxz/jecxz. Ao contrário de outras instruções de transferência de controle condicional, a instrução jcxz/jecxz só pode endereçar saltos curtos - em -128 bytes ou +127 bytes da próxima instrução.

Organizando ciclos

O ciclo, como você sabe, é uma importante estrutura algorítmica, sem a qual, provavelmente, nenhum programa pode prescindir. Você pode organizar a execução cíclica de uma determinada seção do programa, por exemplo, usando comandos de transferência condicional ou o comando de salto incondicional jmp. Com este tipo de organização do ciclo, todas as operações relacionadas à sua organização são realizadas manualmente. Mas, dada a importância de um elemento algorítmico como um ciclo, os desenvolvedores do microprocessador introduziram um grupo de três comandos no sistema de comando para facilitar a programação dos ciclos. Esses comandos também usam o registro ecx/cx como contador de ciclos.

Vamos dar uma breve descrição desses comandos: 1) loop jump_label (Loop) – repete o ciclo. O comando permite organizar loops semelhantes aos loops for em linguagens de alto nível com decremento automático do contador de loops. O trabalho da equipe é fazer o seguinte:

b) comparar o registrador ESX/CX com zero: se (ECX/CX) = 0, então o controle é transferido para o próximo comando após o loop;

2) loope/loopz rótulo_de_transição

Os comandos loope e loopz são sinônimos absolutos. O trabalho dos comandos é realizar as seguintes ações:

a) decremento do cadastro ESH/CX;

c) análise do estado do flag zero ZF se (ECX/CX) = 0 ou XF = 0, o controle é transferido para o próximo comando após o loop.

3) rótulo_de_transição loopne/loopnz

Os comandos loopne e loopnz também são sinônimos absolutos. O trabalho dos comandos é realizar as seguintes ações:

a) decremento do cadastro ESH/CX;

b) comparar o registro ESX/CX com zero;

c) análise do estado do flag zero ZF: se (ECX/CX) = 0 ou ZF = 1, o controle é transferido para o próximo comando após o loop.

Os comandos loope/loopz e loopne/loopnz são inversos em seu princípio de funcionamento. Eles estendem a ação do comando de loop analisando adicionalmente o sinalizador zf, o que permite organizar uma saída antecipada do loop, usando este sinalizador como indicador.

A desvantagem dos comandos loop, loope/loopz e loopne/loopnz é que eles implementam apenas saltos curtos (de -128 a +127 bytes). Para trabalhar com loops longos, você precisará usar comandos de ramificação condicional e o comando jmp, portanto, tente dominar os dois métodos de organização de loops.

Noções básicas de programação de dispositivos MP (palestra)

PLANO DE PALESTRA

1. Classificação dos comandos do microprocessador

2.Tipos de endereçamento

3. Estrutura e formatos de comando do MP KR580VM80

1. Classificação dos comandos do microprocessador

Como já foi observado, a vantagem fundamental do MP é a programabilidade. Isso significa que ao aplicar comandos à entrada MP, é possível garantir a sequência de operações desejada, ou seja, implementação de um algoritmo específico. O algoritmo do problema a ser resolvido pode ser tão complexo quanto desejado, bastando apenas que este algoritmo seja dividido em etapas de acordo com o sistema de comando do MP. Portanto, o sistema de comando é importante não apenas do ponto de vista do que o MP pode fazer, mas também de como o algoritmo é executado. A presença ou ausência de qualquer comando ou grupo de comandos pode afetar significativamente a escolha do MP para uma determinada aplicação.

A classificação dos comandos MP é apresentada na Figura 8.

Com base no número de células de memória necessárias para acomodar um comando, são diferenciados comandos de uma, duas ou três palavras. Instruções com duas ou três palavras requerem dois ou três ciclos de acesso à memória, respectivamente, para serem buscadas.

Em muitos casos, nomeadamente quando se comparam MPs com arquitecturas semelhantes, é útil classificar os comandos de acordo com as características arquitectónicas do MP.

Do ponto de vista funcional, as equipes são divididas em três grandes grupos: transmissão, gestão e processamento de dados. Consideremos detalhadamente os principais comandos utilizados no MP, utilizando a classificação de acordo com as características funcionais. Os nomes dos comandos serão indicados por palavras russas que indicam o significado das operações executadas.

Comandos de transferência de dados fornecer transferência simples de informações sem realizar quaisquer operações de processamento. Os comandos deste grupo são divididos em comandos relacionados ao acesso à memória, comandos de acesso a registradores e comandos de entrada/saída.

Os comandos relacionados ao acesso à memória incluem:

LEMBRAR(WRITE), pelo qual o conteúdo do registrador é enviado para a célula de memória.

Os comandos relativos à transferência de um byte ou palavra devem indicar o número de um registro específico, o endereço da célula de memória e, se necessário, o número do módulo de armazenamento.

Os comandos associados ao acesso aos registros devem indicar o número da fonte de informação e o número do registro de resultado.Este subgrupo de comandos de transferência de dados inclui os comandos:

BAIXE DIRETAMENTE, em que a constante especificada no código de comando é gravada no registrador;

AVANÇAR, através do qual o conteúdo de um registro é enviado para outro.

Os comandos de E/S incluem:

DIGITAR, pelo qual o conteúdo do dispositivo de entrada é enviado para o cadastro interno do MP;

CONCLUSÃO, no qual o conteúdo do registro interno do MP (geralmente um acumulador) é enviado ao dispositivo de saída.

Comandos de controle , muitas vezes chamados de comandos de transição, permitem executar diversas ações de acordo com o valor dos sinais externos ou condições geradas dentro do sistema.Todos os comandos de controle são divididos em comandos de transição incondicionais e condicionais.

Os comandos de salto incondicional incluem:

SALTO INCONDICIONAL(BP), segundo o qual o conteúdo do campo de endereço do comando BP é gravado no contador do programa, ou seja, fornece uma transição no programa para o endereço especificado no comando;

TRANSFERÊNCIA INCONDICIONAL COM REEMBOLSO(transição para uma sub-rotina), segundo a qual novos conteúdos são gravados no contador do programa (o endereço do primeiro comando da sub-rotina), mas ao contrário do comando BP, o estado do contador do programa e alguns outros registros são salvos na memória . Quando uma sub-rotina é executada no seu último comando RETURN, o conteúdo do contador do programa e todos os registros são restaurados.

Instruções de salto condicional verificam o estado de um bit de registro, flag flip-flop ou outro parâmetro. O resultado da verificação determina se a transição será realizada ou não. Normalmente, a transição é realizada se o resultado da verificação corresponder à condição especificada no comando. Este subgrupo de comandos de controle inclui:

SALTO CONDICIONAL(UP) por endereço. O código do comando UP deve indicar a condição que está sendo verificada, para a qual o MT utiliza um valor zero ou diferente de zero do resultado, um sinal positivo ou negativo do resultado, a presença ou ausência de carry sinais, overflow, etc. Quando a condição é atendida, o conteúdo do contador de endereços é gravado no contador de programa. Campos de comando do UE, ou seja, fornece uma transição no programa para o endereço especificado no comando. Se a condição não for atendida, o controle é transferido para o próximo comando do programa;

TRANSIÇÃO CONDICIONAL COM RETORNO, que difere do comando UNCONDITIONAL JUMP WITH RETURN porque a transição para a sub-rotina ocorre somente quando a condição especificada é atendida.

Normalmente, o sistema de comando MP inclui vários outros comandos auxiliares que permitem controlar o estado dos registros ou gatilhos que afetam a execução de transições condicionais, por exemplo: SET FLAG, RESET FLAG, SET BATTERY HIGH BIT, RESET BATTERY HIGH BIT, etc. .

Comandos de processamento de dados são divididos em aritméticos e lógicos. Os aritméticos incluem:

DOBRAR o conteúdo de dois registradores ou de um registrador e de uma célula de memória;

SUBTRAIR do conteúdo de uma célula ou registrador de memória; conteúdo de um registrador;

AUMENTAR EM 1(INCREMENT) conteúdo de uma célula ou registrador de memória (ponteiro de pilha, registrador de índice, acumulador);

DIMINUIR EM 1(DECREMENT) conteúdo de uma célula ou registrador de memória;

ADICIONAR COM REALIZAR, pelo qual a adição é realizada levando em consideração o estado do gatilho de transferência. Isto facilita a organização do processamento de grandes números;

SUBTRAIR CONTABILIDADE DO EMPRÉSTIMO;

MUDANÇA conteúdo de uma célula de memória ou registro (geralmente um bit).

O subgrupo de comandos lógicos inclui os seguintes comandos:

E(MULTIPLICAÇÃO LÓGICA), pela qual é realizada a operação de conjunção entre o conteúdo de dois registradores ou uma célula de memória e um registrador;

OU(ADIÇÃO LÓGICA), pela qual é realizada uma operação de disjunção entre o conteúdo de dois registradores ou uma célula de memória e um registrador;

INVALIDEZ, que realiza uma comparação bit a bit do conteúdo de dois registradores ou de uma célula de memória e de um registrador;

INVERSÃO conteúdo de uma célula de memória ou registro.

2.Tipos de endereçamento

Uma das características arquitetônicas mais importantes do MP é a lista de possíveis métodos de acesso à memória ou tipos de endereçamento. As capacidades de endereçamento do MP são significativas sob dois pontos de vista.

Primeiro, uma grande quantidade de memória requer um grande comprimento de endereço, uma vez que um endereço de n bits permite acesso à memória com capacidade de 2n palavras. Palavras MP típicas de 8 bits permitem acessar diretamente apenas 256 células de memória, o que claramente não é suficiente. Se levarmos em conta que o acesso à memória é a operação mais comum, então é óbvio que a eficiência do uso do MP é em grande parte determinada pelos métodos de endereçamento de um grande volume de memória com uma pequena capacidade de MP.

Em segundo lugar, para facilitar a programação, é desejável ter um sistema simples de geração de endereços de dados ao trabalhar com arrays, tabelas e ponteiros. Vejamos maneiras de resolver esses problemas.

Se o campo de endereço do comando for limitado e insuficiente para acessar diretamente qualquer célula de memória, então a memória nesses casos é dividida em páginas, onde 2n células de memória são consideradas uma página.

Para combinar o campo de endereço de um comando de pequeno bit com memória de grande capacidade (para resolver o problema da “página”), vários tipos de endereçamento são usados ​​no MP:

Endereçamento direto para a página atual . Com este endereçamento, o contador do programa é dividido em dois campos; os bits de ordem superior indicam o número da página e os bits de ordem inferior indicam o endereço da célula na página. O campo de endereço do comando contém o endereço da célula na página, e o endereço da página deve ser definido de alguma outra forma, por exemplo, usando um comando especial.

Endereçamento direto usando registro de página. O MP deve ter um registro de página acessível programaticamente e carregado por um comando especial. Este registrador adiciona vários bits ao campo de endereço da instrução, necessários para endereçar toda a memória.

Endereçamento direto usando palavras duplas. Para aumentar o comprimento do campo de endereço de um comando, uma palavra adicional é alocada para o endereço (e, se necessário, duas).

Endereçamento relativo ao contador do programa. O campo de endereço da instrução é tratado como um número inteiro assinado, que é adicionado ao conteúdo do contador do programa para formar o endereço de execução. Este método de endereçamento relativo cria uma página flutuante e facilita a movimentação de programas na memória.

Endereçamento relativo ao registro de índice. O endereço de execução é formado pela soma do conteúdo do registrador de índice e do campo de endereço do comando, considerado como um número inteiro assinado. O registro de índice é carregado com comandos especiais.

Endereçamento indireto . Quando o endereçamento indireto é usado, o campo de endereço do comando especifica o endereço na página atual onde o endereço executivo está armazenado. Neste caso, é necessário um bit adicional no campo de comando - um sinal de endereçamento indireto. O endereço executivo pode ser armazenado não em uma célula de memória, mas em um registrador de uso geral. Neste caso, o endereçamento indireto é chamado de endereçamento de registro.

3. Estrutura e formatos de comando do MP KR580VM80

O sistema de comando MP da série KR580VM80 contém comandos em três formatos: byte único, byte duplo e três bytes.

O conteúdo do primeiro byte indica o formato do comando, o código da operação, o tipo de endereçamento e os registradores ou pares de registradores, caso estejam envolvidos na operação, porém é impossível especificar os bits específicos que serão alocados aos três primeiros de os componentes especificados do comando, porque eles podem estar localizados em qualquer bit do comando. Mas, apesar disso, assumiremos que eles são codificados como um campo, chamado campo de código de operação. Variantes de formatos para o primeiro byte do comando são mostradas na Figura 9.

Se houver registros envolvidos na operação, um ou dois deles poderão ser especificados no primeiro byte do comando. Neste caso, bits bastante específicos são atribuídos aos números dos registradores no campo de comando: os três bits de ordem inferior (b2 – b0) codificam o número do registrador fonte que contém o operando, e os três bits do meio (b5 – b3) – o número do registro de destino para o qual é enviado o resultado da operação. Nos casos em que ambos ou um desses registros não estão envolvidos na execução da operação, os bits correspondentes são utilizados para o código da operação.

A seguinte codificação de registro é aceita:

000 – registro B, 100 – registro H,

001 – registro C, 101 – registro L,

010 – registro D, 110 – célula de memória,

011 – registro E, 111 – bateria A.

O código 100 é um sinal de endereçamento indireto de memória usando um endereço de 16 bits localizado nos registradores H e L. Dependendo da localização deste código no comando, a célula de memória correspondente é acessada para um operando ou para escrita dos resultados de a operação.

Vários comandos MP permitem o processamento ou transmissão de números de comprimento duplo. Nestes casos, os pares de registradores B e C, D e E ou H e L são combinados em registradores de 16 bits numerados 00, 01 e 10, respectivamente. Os números dos pares de registros nos comandos são atribuídos aos bits b2 e b1 (registro de origem), b5 e b4 (registro de destino), e os bits b0 e b3 são usados ​​para indicar o código de operação.

Os comandos de byte duplo no MP incluem comandos com endereçamento direto e comandos de entrada/saída. Assim, o segundo byte do comando deste grupo contém um operando de 8 bits ou um endereço de 8 bits de um dispositivo de entrada ou saída.

Nas instruções de três bytes, o segundo e o terceiro bytes contêm endereços de 16 bits (em instruções de endereçamento direto) ou operandos de 16 bits (em instruções para carregar pares de registradores e ponteiro de pilha).

Após a execução de cada operação da ALU, são gerados cinco sinais, cujos valores podem influenciar a execução de comandos subsequentes de processamento de informações e transferência de controle condicional.No entanto, deve-se ter em mente que comandos diferentes têm efeitos diferentes em sinais individuais.

Para a conveniência de salvar e restaurar o estado do MP durante interrupções e transições para sub-rotinas, todas as características especificadas são armazenadas em um registro especial - o registro de características. A localização dos sinais nos bits de registro é mostrada na tabela.

onde S é o atributo “sinal” (assume o valor do bit mais significativo

resultado);

Z – sinal de resultado zero;

AC é sinal de transferência auxiliar (se houver transferência

entre tétrades de bytes, então AC=1, caso contrário AC=0;

P – um sinal de paridade do resultado (se o número de uns no byte

o resultado for par, então P=1, caso contrário P=0);

C – sinal de transferência ou empréstimo (se, ao executar comandos,

Quando houve uma transferência de um cargo sênior ou um empréstimo para um cargo sênior

O dígito mais alto é C=1, caso contrário C=0).

Observação: Para comandos de multiplicação lógica, o sinal de transporte auxiliar AC assume o valor do quarto bit do resultado.

O sistema de comando completo da série MP KR580VM80 é fornecido no apêndice do livro “Microprocessadores e sistemas de microprocessadores”. Lá, para cada comando, é indicado como, após sua execução, o valor de cada atributo muda: é definido de acordo com o resultado da operação (+), não muda (–), é zerado (0 ) ou definido como um (1).

Em geral, o comando deve conter as seguintes informações:

–código de operação que indica a operação que o MP deve realizar;

–endereços de dois operandos (adições, subtraendos, etc.). Se algum dos operandos for uma constante, então, em vez de seu endereço, o valor do próprio operando poderá ser especificado no comando. No entanto, esta circunstância deve estar refletida no código de operação para que o MP utilize a parte adequada do comando para o fim a que se destina;

–endereço da célula de memória onde deve ser colocado o resultado da operação;

–endereço do próximo comando.

Aqueles. o comando geralmente tem quatro endereços, mas essa estrutura de comando leva a um formato de comando mais longo, que, por sua vez, está associado a um processo de processamento e estrutura de processador mais complexos. Portanto, na tecnologia MP, os comandos sem endereço e unicast são os mais difundidos, possibilitando a construção de um processador simples, porém, ao realizar operações complexas, vários formatos de comandos são utilizados.

O sistema de instruções MP da série 580 possui instruções de byte único, byte duplo e três bytes.

As informações sobre como o comando a ser endereçado estão contidas no opcode do primeiro byte do comando.

Para agilizar os cálculos, alguns operandos são armazenados no bloco RON. As instruções que operam nesses operandos utilizam códigos de endereço abreviados (endereçamento de registro).

Esses comandos permitem eliminar o ciclo relativamente longo de acesso à RAM e, assim, aumentar significativamente a velocidade das operações. Devido à capacidade limitada do RON e quando se trabalha com um grande conjunto de dados, são utilizados outros métodos de endereçamento que permitem o acesso a operandos localizados na memória externa ao MP. O mais comum é o endereçamento indireto de registradores, que utiliza um par de registradores HL.

No grupo de comandos de transferência de controle, existem quatro tipos de comandos: ramificações incondicionais, ramificações condicionais, loops e interrupções .

Comandos de salto incondicionais. Inclui três códigos mnemônicos: JMP (salto incondicional), CALL (chamada de sub-rotina) e RET (retorno da sub-rotina).

O comando JMP permite saltar para qualquer ponto do programa, localizado tanto no segmento atual do programa quanto em outro segmento. Ao saltar dentro do segmento de programa atual, os três primeiros formatos de instrução JMP são usados.

O primeiro formato fornece uma transição para um ponto arbitrário no programa dentro do segmento de programa atual, para o qual um deslocamento de 16 bits é adicionado ao conteúdo IP no código complemento de dois, cujo bit mais significativo é assinado. O segundo formato abreviado permite que você pule para um ponto no programa que não ultrapasse os endereços -128-f-127 da instrução JMP. Por fim, o terceiro formato carrega o ponteiro de instrução com um número de 16 bits, que está localizado no endereço executivo EA, determinado pelo pós-byte. Essa transição é chamada de indireta porque é usado endereçamento indireto.

Para implementar um salto incondicional para um ponto de programa localizado fora do segmento de programa atual quando é necessária uma recarga do registrador de segmento CS, são usados ​​o quarto e o quinto formatos de instrução JMP.

O quarto formato define uma transição direta entre segmentos, em que o segundo e o terceiro bytes do formato indicam o endereço relativo do ponto de transição, e o quarto e o quinto bytes indicam o novo valor CS. O quinto formato, usando um postbyte, permite determinar o endereço executivo EA, no qual está localizado o endereço relativo do ponto de transição (em bytes de memória com endereços EA, EA+1), e o novo valor CS (em bytes de memória EA+2, EA+3).

O comando CALL permite chamar uma sub-rotina localizada no segmento atual do programa ou em outra área da memória. Possui os mesmos formatos do comando JMP, exceto que é mais curto. Ao contrário do comando JMP de formato semelhante, o comando CALL, antes de alterar os valores IP ou IP e CS, grava automaticamente os valores atuais desses registradores na pilha, o que garante que o ponto de retorno da sub-rotina seja lembrado.

Para retornar de uma sub-rotina, use o comando RET, que transfere o controle para o endereço de retorno colocado na pilha ao executar o comando CALL anterior. Ao retornar de sub-rotinas localizadas no segmento de programa atual, são utilizados os dois primeiros formatos da instrução RET, e o segundo formato difere do primeiro porque uma constante escrita no 2º e 3º bytes da instrução é adicionada ao conteúdo de o ponteiro da pilha. Isto permite, simultaneamente ao retorno da sub-rotina, zerar os parâmetros escritos na pilha durante a execução desta sub-rotina e não utilizados no futuro.

Para retorno intersegmento, são utilizados o terceiro e quarto formatos RET, que proporcionam a recuperação do conteúdo tanto do ponteiro de instrução quanto do segmento do programa.

Comandos de salto condicional. Controle de transferência dependendo dos resultados de operações anteriores. Existem três tipos de saltos condicionais usados ​​para estabelecer relações entre números assinados, números não assinados e números arbitrários. Nas duas primeiras variedades, diferentes códigos mnemônicos de comando são selecionados para as mesmas relações entre números, uma vez que diferentes valores de sinalizadores correspondem às mesmas relações entre números assinados e não assinados.

Nos códigos mnemônicos dos comandos de salto condicional, ao comparar números com sinal, a letra é usada para indicar a condição “maior que” G (maior- mais), e para designar - letra “menos” L (menos- menos). Para condições semelhantes, ao comparar números sem sinal, letras são usadas respectivamente A (acima- acima) e Abaixo- sob). A condição de igualdade é denotada pela letra E (igual- é igual), e o não cumprimento de alguma condição - ao pé da letra N (não- Não). Ressalta-se que é permitida a utilização de dois códigos mnemônicos diferentes para cada comando; por exemplo, os códigos mnemônicos JL e JNGF são equivalentes, pois as condições “menor que” e “não maior ou igual a” são idênticas.

Uma lista completa de códigos mnemônicos de comando, condições verificadas, bem como as combinações booleanas correspondentes de sinalizadores e seus valores são fornecidos na Tabela. 1.4.

Tabela 1.4

Código mnemônico de comando Doença Significado das bandeiras
Para números assinados
JL/JNGE Menor/não mais que ou igual a SF + OF = eu
JNL/JGE Não menor que/maior que ou igual a SF + OF = 0
JG/JNLE Mais que/não menos que ou igual a (SF + OF) V ZF = 0
JNG/JLE Não maior que/menor ou igual a Para números sem sinal (SF + OF) V ZF = l
JB/JNAE Menor/não mais que ou igual a CF=1
JNB/JAE Não menor que/maior que ou igual a CF=0
JA/JNBE Mais CF V ZF = 0
JNA/JBE Não mais Para outros dados CF V ZF = 1
JE/JZ Igual/zero ZF = 1
JNE/JNZ Diferente/zero ZF = 0
JS Por menos SF = 1
JNS Do lado positivo SF = 0
JO Transbordar DE = eu
JNO Por ausência de transbordamento DE = 0
JP/JPE Por paridade par PF = 1
JNP/JPO Por paridade ímpar PF = 0

Todas as instruções de salto condicional têm o mesmo formato de dois bytes, sendo o primeiro byte o código de operação (OPC) e o segundo um deslocamento de 8 bits, que é tratado como um número assinado e, portanto, permite alterações de endereço no intervalo de -128 a +127. Se uma transição mais distante (“distante”) for necessária quando uma condição for atendida, um comando de transição incondicional adicional será usado.

O tempo de execução de cada uma das instruções de salto condicional é indicado para dois casos: 1) a condição é satisfeita e o controle é efetivamente transferido de acordo com o deslocamento, 2) a condição não é satisfeita, então o controle é transferido para a próxima instrução.

Equipes para organização de ciclos. Introduzido na CPU para a comodidade de realizar ciclos computacionais. Estes incluem os seguintes códigos mnemônicos: LOOP (loop até (CX) não ser igual a 0), LOOPNZ/LOOPNE (loop até zero/diferente de), LOOPZ/LOOPE (loop até zero/igual a) e JCXZ (pular em zero em SH). Cada um desses comandos possui um formato de dois bytes, cujo segundo byte especifica o deslocamento de 8 bits usado para organizar o salto. Esse deslocamento é tratado como um número assinado e estendido com sinal para 16 bits antes que o endereço de salto seja calculado.

Usando comandos de loop junto com comandos para manipular elementos de string, você pode criar programas de conversão de string bastante complexos. Vamos considerar um exemplo de composição de um programa para converter uma string de dados escrita no sistema numérico hexadecimal em algum código para o qual a tabela de conversão está localizada na memória a partir do endereço inicial especificado em BX, conforme necessário para usar o comando de conversão de tabela para XLAT códigos. Vamos supor ainda que a string de origem contém 80 elementos e está localizada na memória a partir do endereço inicial relativo 100, e a string de resultado deve ser colocada no endereço relativo 200. O programa que converte a string de origem na string de resultado, com o valor da bandeira de direção DF=0, terá a forma:

MOVSI ,100
DI MOV, 200
MOV CX, 80

O comando de conversão de tabela XLAT descrito em 1.2 é usado aqui.

Interromper comandos. Inclui três mnemônicos: INT (interrupção), INTO (interrupção em caso de estouro) e IRET (interrupção de retorno).

Interrompa o comando INT em v = 1 tem um formato de dois bytes, o segundo byte contém um número de 8 bits que define o tipo (tipo) ou nível de interrupção. Por comando INT tipo O processador executa o programa de serviço de interrupção do nível especificado e as ações necessárias para garantir o retorno ao ponto de interrupção são executadas automaticamente. Essas ações são as seguintes: o conteúdo do registrador de flags F é gravado na pilha (PUSHF), os flags IF e TF são redefinidos, os valores atuais do registrador CS e o ponteiro de instrução IP são gravados na pilha.

Para determinar o endereço inicial do programa de serviço de acordo com o valor tipo A tabela de nível de interrupção é usada. Para cada um dos 256 níveis de interrupção nesta tabela, quatro bytes são alocados: os dois primeiros bytes determinam o valor do ponteiro da instrução IP, o segundo - o valor do registro do segmento CS. Esses quatro bytes determinam os endereços iniciais dos programas de serviço (pares de valores CS, IP), que devem primeiro ser gravados nas células de memória nos endereços absolutos 0-3FFH. Endereço da tabela correspondente ao especificado no comando INT tipo o nível de interrupção é determinado na CPU da seguinte maneira. Após armazenar os valores atuais de CS e GR na pilha, o carregamento é realizado: CS = tipo x 4 + 2 e IP = tipo x 4. Novos valores CS e IP retirados das células de endereço, respectivamente tipo x 4 + 2 E tipo x 4, determinar o endereço inicial do programa de manutenção necessário.

O comando de interrupção INT discutido acima quando o valor do campo é v=0 tem formato de byte único, ou seja, não requer indicação especial do nível de interrupção. Este comando é automaticamente percebido pelo processador como uma interrupção de nível 3. (tipo=3) e é comumente usado em programas como ponto de verificação.

O comando de interrupção de overflow INTO causa uma transição para atender a interrupção de quarto nível (tipo = 4) no caso em que o valor do sinalizador de overflow DE = 1. O comando INTO é normalmente usado após comandos aritméticos assinados. Normalmente, os primeiros níveis de interrupção (até 32) são reservados para processar uma série de situações específicas, como tentativa de divisão por zero, estouro e similares.

Uma peculiaridade do processamento de interrupções de níveis reservados é que o processador prossegue para atendê-los independentemente do valor do sinalizador de habilitação de interrupção IF.

A instrução IRET de um byte é colocada no final de cada rotina de serviço de interrupção e fornece retorno de interrupção. Com este comando, o processador recupera o valor do ponteiro de instrução IP e o segmento do programa CS da pilha e também restaura o conteúdo anterior do registro de flags F (como acontece com o comando POPF). Se necessário, o conteúdo dos registros restantes da CPU correspondentes ao programa interrompido pode ser armazenado na pilha ao passar para o programa de serviço e depois restaurado ao retornar dele usando instruções de acesso à pilha.

Por endereço indireto

PCHL – o endereço de salto é armazenado no par de registradores HL. Quando é executado (HL) → PC.

Comandos de salto condicional

Jcon @, onde con é um mnemônico de condição da palavra inglesa condição.

Foi observado anteriormente que o estado dos bits (flags) do RgP (F) é utilizado como condição de transição. Os mnemônicos correspondentes a esses estados são apresentados na Fig. 6.18.

Por exemplo: JC 8BFE – quando C=1 vai para o endereço 8BFE, quando C=0 o próximo comando no endereço é executado.

Comandos para chamar PP e retornar

Foi observado anteriormente que o endereço de retorno é armazenado automaticamente na pilha, ou seja, (PC)® pilha.

Comandos incondicionais

CALL @ – chamada de sub-rotina;

RET – retorno da sub-rotina.

Comandos condicionais

Ccon@ – chamada de sub-rotina;

Rcon – retorno da sub-rotina.

A ação dos comandos é semelhante à ação dos comandos de salto condicional, ou seja, se a condição for verdadeira, ligue ou retorne. Caso contrário, os seguintes comandos serão executados.

Outros comandos de controle

RST n, onde n = 0,1,...,7 – reinicia de acordo com o vetor de interrupção n.

Quando este comando é executado, o controle é transferido para a sub-rotina que atende esta interrupção. Durante a execução da instrução RST, o conteúdo do contador do programa do PC é armazenado na pilha e o endereço do vetor de interrupção correspondente é gravado no PC.

Este endereço é definido da seguinte forma. O comando RST possui a estrutura 11NN N111, ou seja, um byte. A combinação NNN de três bits é especificada pelo valor n (n = 0...7). O valor 0000 0000 00NN N000 é inserido no contador de comandos do PC, que serve como endereço do vetor de interrupção correspondente.

Assim, definindo um determinado valor de n, você pode gerar o endereço de um dos 8 vetores de interrupção. Esses endereços estão localizados na zona de 0000H a 0038H do espaço de endereço e passam por 8 bytes, ou seja, As primeiras 64 células de memória são reservadas para eles (cada um dos 8 vetores recebe 8 bytes). Nestas zonas (8 bytes cada) são escritos apenas comandos para saltar para as sub-rotinas (handlers) correspondentes, que estão localizadas em outras áreas da memória.

A interrupção das sub-rotinas (como as sub-rotinas normais) deve terminar com o comando RET. Durante a execução deste comando, o endereço do comando do programa principal antes do qual ocorreu a interrupção é selecionado da pilha e transferido para o registro de endereço PA, e o valor aumentado em 1 é inserido no contador do programa.

EI – habilitação de interrupção. Este comando é colocado no início da seção do programa onde a interrupção está habilitada. Com este comando, o gatilho de habilitação de interrupção na unidade de controle MP é colocado no estado 1.

DI – interrupção desabilitada. Este comando é colocado no final da seção do programa onde a interrupção foi habilitada e redefine o gatilho para o estado 0.

NOP é um comando "vazio". Pula 4 compassos. Apenas o PC muda.

HLT – pare. Faz com que a execução do programa pare e entre no estado parado. O MP é desconectado do endereço externo e dos barramentos de dados (ou seja, seus buffers vão para o estado Z). A saída WAIT (espera) é definida para o nível 1. Este estado pode ser interrompido por sinais de início do MP ou colocando-o no estado de interrupção.

PERGUNTAS DE AUTOTESTE

1. Quais dispositivos são necessários para criar um microcomputador simples?

2. Liste 5 opções de estruturas de microcomputadores.

3. Usando uma interface intermediária.

4. O que inclui o conceito de “controlador PU”?

5. Liste as características do processador I8080.

6. Registros de dados. Seu propósito.

7. Assinar registros. Quais atributos são armazenados nesses registros?

8. Descreva o princípio da troca bidirecional de dados entre SD interno e externo.

9. Quais registros um programador pode usar?

10. Forneça um diagrama de blocos de um microcomputador baseado em MP KR580VM80.

11. Em que ciclos consiste um ciclo de máquina?

12. Liste os formatos de dados do MP KR580VM80.

13. Liste os formatos de comando do MP KR580VM80.

14. Quais métodos de endereçamento são utilizados no MP KR580VM80?

15. Em quais grupos as equipes MP KR580VM80 podem ser divididas?

16. Transferências de byte único. Dê exemplos de comandos deste grupo.

17. Transferências de byte duplo. Dê exemplos de comandos deste grupo.

18. Quais operações de bateria você conhece?

19. Operações em RON e memória. Que operações eles incluem?

20. Liste os comandos de controle.

TAREFAS DE CONTROLE

1. As folhas de respostas devem indicar o número do grupo, o apelido do aluno e o número da sua opção.

2. Os números das questões são seleccionados pelo aluno de acordo com os seus dois últimos dígitos do livro de notas. Na Tabela 6.1, n-1 é o penúltimo dígito do número e n é o último dígito. As células da tabela contêm o número de perguntas às quais deve ser dada uma resposta por escrito.

Números das perguntas Tabela 6.1

um n um n-1
1,5,9, 13,16 2,6,10,14,17 3,7,11,15,18 4,8,12,13,19 1,9,11,14,20 2,10,12,15,18 3,5,8, 13,17 4,6,7, 14,19 1,8,10,13,17 2,5,7, 14,18
3,6,8, 15,19 4,7,9, 13,16 1,5,12,14,20 2,6,11,15,16 3,7,10,13,17 4,8,9, 14,18 1,7,12,13,18 2,8,10,14,19 3,5,11,15,20 4,6,9, 13,17
2,7,9, 13,20 1,8,11,15,19 4,5,10,15,17 3,6,12,14,16 1,5,9, 13,16 2,6,10,14,17 3,7,11,15,18 4,8,12,13,19 1,9,11,14,20 2,10,12,15,18
3,5,8, 13,17 4,6,7, 14,19 1,8,10,13,17 2,5,7, 14,18 3,6,8, 15,19 4,7,9, 13,16 1,5,12,14,20 2,6,11,15,16 3,7,10,13,17 4,8,9, 14,18
1,7,12,13,18 2,8,10,14,19 3,5,11,15,20 4,6,9, 13,17 2,7,9, 13,20 1,8,11,15,19 4,5,10,15,17 3,6,12,14,16 1,5,9, 13,16 2,6,10,14,17
3,7,11,15,18 4,8,12,13,19 1,9,11,14,20 2,10,12,15,18 3,5,8, 13,17 4,6,7, 14,19 1,8,10,13,17 2,5,7, 14,18 3,6,8, 15,19 4,7,9, 13,16
1,5,12,14,20 2,6,11,15,16 3,7,10,13,17 4,8,9, 14,18 1,7,12,13,18 2,8,10,14,19 3,5,11,15,20 4,6,9, 13,17 2,7,9, 13,20 1,8,11,15,19
4,5,10,15,17 3,6,12,14,16 1,5,9, 13,16 2,6,10,14,17 3,7,11,15,18 4,8,12,13,19 1,9,11,14,20 2,10,12,15,18 3,5,8, 13,17 4,6,7, 14,19
1,8,10,13,17 2,5,7, 14,18 3,6,8, 15,19 4,7,9, 13,16 1,5,12,14,20 2,6,11,15,16 3,7,10,13,17 4,8,9, 14,18 1,7,12,13,18 2,8,10,14,19
3,5,11,15,20 4,6,9, 13,17 2,7,9, 13,20 1,8,11,15,19 4,5,10,15,17 3,6,12,14,16 1,5,9, 13,16 2,6,10,14,17 3,7,11,15,18 4,8,12,13,19

A operação de transição incondicional (BP) refere-se às operações de transferência incondicional de controle e consiste no seguinte. No início da operação, o conteúdo do CC, indicando o comando que segue o BP (endereço de retorno), é enviado para P1 AU caso o programa preveja retorno; isso permite salvar o endereço de retorno transferindo posteriormente o conteúdo de P1 (por exemplo, pela operação 3G) para a memória. Para isso, os primeiros comandos da seção do programa para a qual é feita a transição devem conter uma operação correspondente. No próximo estágio da operação, o conteúdo de 1 a 14 bits, que é o endereço de transição, é lido da célula RAM ou ROM com o endereço especificado no comando BP no SchK. Neste endereço, é então feita uma solicitação à ROM para o comando para o qual a transição é feita.

Operação de turno

No formato de deslocamento (FSD), as operações “Deslocamento aritmético para a direita (esquerda)” e “Deslocamento lógico para a direita (esquerda)” são codificadas. Quando executados, as ações são executadas no número localizado no AC. Os atributos no comando são especificados: a direção do deslocamento (5 r), os tipos de deslocamentos (8,9 r) e seu número (1-4 r). Durante a operação, os bits do registro P2 são deslocados, o resultado é registrado nos registros P2 e РСм, e o deslocamento para a direita é realizado em 3 bits ao mesmo tempo, o deslocamento para a esquerda é de 1 bit. O valor do 5º bit igual a “1” determina o deslocamento para a esquerda, igual a “0” - para a direita.

As operações são cíclicas. O número de ciclos de mudança é contado pelo contador de ciclos (CC). Antes de executar a parte cíclica da operação, o conteúdo de 1 a 5 bits do comando contendo uma constante e um sinal de deslocamento é enviado para o centro. A seguir, o conteúdo de P2 é enviado ao RSM. A mudança em si é realizada devido à cópia “oblíqua” do conteúdo dos registradores P2 e Pcm para P2’ e Pcm’, respectivamente. Então o resultado da mudança de PCm' e P2' através de SM1 e SM2 é reescrito em P2 e PSM. A conclusão da operação é indicada pelo valor de SchT =0.

Dependendo do tipo de deslocamento (L ou A), todos os 16 bits (L) ou apenas 15 bits (mantissa) sem sinal (A) são deslocados. Quando A se desloca para a direita, os bits vagos de ordem superior são preenchidos com um sinal, e quando se desloca para a esquerda, os bits vagos de ordem inferior são preenchidos com zeros. Durante um deslocamento lógico para a direita ou para a esquerda, os bits vagos são preenchidos com zeros.

Você também pode alterar programaticamente a constante de deslocamento.

32 Interação de nós e elementos do diagrama de blocos do processador CB ao realizar operações de salto condicional.

Operações de salto condicional



A execução da operação começa verificando a viabilidade da condição de transição comparando o valor do atributo resultado da operação anterior com o código “máscara” do comando. Se a condição for atendida, ocorre a transição para a execução do comando, cujo endereço está na parte endereço-operando do formato PFU. Se a condição de transição não for atendida, o comando seguinte ao comando “Salto condicional” do programa será executado.

O comando “Salto Condicional” (JJ) ocupa duas células ROM adjacentes. A primeira célula contém o comando, a segunda célula contém o endereço de salto. Um salto condicional é determinado por uma combinação de 7 a 9 bits do comando, a condição para colocar o endereço de retorno é determinada pelo 6º bit.

Quando a condição for atendida, o endereço de transição é inserido no contador do programa, portanto o código do próximo comando será lido na célula com este endereço. O endereço de retorno é inserido em P1 se o 6º bit for igual a 0 e em Pcm se o valor deste bit for igual a um.

Se a condição de transição não for atendida, a próxima instrução é selecionada na célula com código de endereço i+2. Neste caso, o código especificado (endereço de retorno) é inserido em P1 independente do valor do 6º bit do comando. Este último é determinado pelo algoritmo operacional do processador SV ao decifrar o código de operação do UE.

A inserção do endereço de retorno no PCM se deve ao fato de que a saída para o barramento de código do AC possui apenas o registro especificado.

Uma peculiaridade da execução da operação NC é que se houver o código 111 ou 000 nos bits “máscara” do comando, a transição condicional degenera em incondicional ou em operação de envio aos registradores base, respectivamente. Nestes casos, os endereços de salto ou o endereço de envio para os registradores base são o conteúdo da parte endereço-operando da instrução (AOC).

Ao realizar a operação de envio para o BR, o conteúdo do AOC é enviado para um ou vários BRs de uma só vez, dependendo do conteúdo dos 15-17 bits do comando. O endereço de retorno neste caso não é enviado para P1 e RSM.



A execução de uma operação NC como uma operação TCU pode ser usada em interrupções para saltar para programas interrompidos. Para isso, no 5º bit do comando é definido o atributo de transição programada (PNT). Neste caso, o comando é lido no processador a partir da ROM através de um sinal de interrupção (ISR). Neste caso, o endereço de acesso à ROM (endereço de interrupção) é gerado pelo circuito de interrupção do processador.

Uma peculiaridade da operação neste caso é que o endereço de retorno das interrupções não é o endereço do comando seguinte ao comando no formato FUP, mas o endereço do comando antes do qual ocorreu a interrupção. O sinal NPP é processado da seguinte forma. Com base neste sinal, o circuito de interrupção do processador gera um endereço de interrupção (APr), igual ao endereço da primeira célula da instrução de salto no formato FUP(i). Este endereço é transferido para a memória através do switch e do registrador de endereços ROM. Os endereços de interrupção são selecionados de forma que o endereço da primeira célula do comando (i) seja par e o endereço da segunda célula (i+1) seja ímpar. O segundo endereço é obtido alterando (em hardware) o dígito menos significativo sem a participação do CC de zero para um. No processo de leitura de um comando da ROM e execução do mesmo, o conteúdo do SchK (K+1) é armazenado no registrador P1 do AC, e o conteúdo da segunda célula do comando (i+1), que é o endereço de transição para o comando com endereço j, são inseridos no SchK. É feita uma solicitação ao ROM sobre o novo conteúdo do CC. Assim, o endereço da próxima instrução no momento da interrupção (K+1) é armazenado no registrador P1. Após o processamento da interrupção, este endereço é usado para retornar ao programa interrompido.

33 Interação de nós e elementos do diagrama de blocos do processador SV ao realizar operações de controle do processador e do sistema.