Aldeia Numaboa
Um portal diferente em Português do Brasil
Informática da Aldeia

Tutoriais
Home Informática Tutoriais e Programação Art of Assembly AoA - Cap.2 - Funções booleanas genéricas

Na Aldeia

Há 96 visitantes online

3630 registros
0 hoje
14 nesta semana
4 neste mês

Boas vindas: flor

Estatística

Membros: 3639
Artigos: 1045
Links: 90
Leituras: 6680970

Login



Kanji da hora




Faça contato






Sex

23

Fev

2007


10:40

AoA - Cap.2 - Funções booleanas genéricas PDF Imprimir Indique esta página
(3 votos, média 3.7 de 5)


Nível intermediário Para uma aplicação específica pode-se criar uma função lógica que dê um determinado resultado. Suponha, entretanto, que você queira escrever um programa para simular qualquer função booleana possível.

Por exemplo, imagine um programa que permita a entrada de uma função booleana arbitrária com quatro variáveis diferentes. Este programa lerá as entradas e produzirá necessariamente os resultados das funções. Uma vez que o número de funções de quatro variáveis únicas é grande (65536, para ser exato), não é prático incluir uma solução específica para cada uma no programa. O que se precisa é de uma função lógica genérica, uma que calcule os resultados para qualquer função arbitrária. Esta seção descreve como escrever tal função.

Uma função booleana genérica de quatro variáveis requer cinco parâmetros - os quatro parâmetros de entrada e um quinto parâmetro que especifica a função que deve ser calculada. Apesar de haver muitas formas de se especificar uma função, optamos por passar o número da função booleana como quinto parâmetro.

À primeira vista você poderia perguntar como é possível calcular uma função utilizando o seu número. Contudo, lembre-se de que os bits que formam o número da função vêm diretamente da tabela verdade da própria função. Então, se extrairmos os bits do número da função, poderemos construir a tabela verdade para a mesma. Além disto, se selecionarmos somente o iésimo bit do número da função, onde i = D*8 + C*4 + B*2 + A, obteremos o resultado da função para os valores especificados para A, B, C e D. O exemplo a seguir, em C e Pascal, mostra como escrever tais funções:

 
/************************************************************************/
/*                                                                      */
/* Este programa C demonstra como escrever uma função booleana genérica */
/* que pode calcular qualquer função lógica de quatro variáveis. Com os */
/* operadores de manipulação de bits e com a E/S hexadecimal, esta é    */
/* uma tarefa fácil de ser efetuada com a linguagem C.                  */
/*                                                                      */
/************************************************************************/
 
#include <stdlib.h>
#include <stdio.h>
 
/* função lógica genérica.  O parâmetro "Func" contém o número 16       */
/* da função lógica. Na verdade, isto é a função lógica de uma tabela   */
/* verdade codificada. Os parâmetros a, b, c e d são as entradas para   */
/* a função lógica. Se tratarmos "func" como um array 2x2x2x2 de bits,  */
/* esta função particular seleciona o bit "func[d,c,b,a]" da função.    */
 
int generic(int func, int a, int b, int c, int d)
{
        /* Retorna o bit especificado por a, b, c e d */
 
        return (func >> (a + b*2 + c*4 + d*8)) & 1;
}
 
/* Programa principal para comandar a função lógica genérica escrita em C. */
 
main()
{
        int func, a, b, c, d;
 
        /* Repete o seguinte até o usuário entrar zero.                 */
 
        do
        {
                /* Obtém o número da função (tabela verdade)            */
 
                printf("Entre o valor da função (hex): ");
                scanf("%x", &func);
 
                /* Se o usuário especificar zero como nro da função     */
 
                if (func != 0)
                {
                        printf("Entre os valores para d, c, b & a: ");
                        scanf("%d%d%d%d",
                                &d, &c, &b, &a);
 
                        printf("O resultado é %d\n", generic(func,a,b,c,d));
                        printf("Func = %x, A=%d, B=%d, C=%d, D=%d\n",
                                func, a, b, c, d);
                }
 
        } while (func !=0);
 
}
 

O programa a seguir, em Pascal, foi escrito para Standard Pascal. O Standard Pascal não fornece quaisquer operações para manipulação de bits, então este programa ficou grande porque ele precisa manipular os bits utilizando um array de inteiros. Muitos Pascals modernos (especialmente o Turbo Pascal) fornecem operações de bits embutidas ou rotinas em bibliotecas que operam bits. Este programa seria muito mais fácil de escrever utilizando tais características não padronizadas.

 
program GenericFunc(input,output);
 
(* Já que o Pascal Padrão não fornece uma forma fácil para manipular    *)
(* diretamente bits em um inteiro, simularemos o número da função       *)
(* utilizando um array de 16 inteiros. "GFTYPE" é o tipo desse array.   *)
 
type
    gftype = array [0..15] of integer;
 
var
   a, b, c, d:integer;
   fresult:integer;
   func: gftype;
 
(* Pascal Padrão não tem a capacidade de deslocar um dado inteiro para  *)
(* a esquerda ou a direita. Então, simularemos um valor de 16 bits      *)
(* utilizando um array de 16 inteiros. Podemos simular o deslocamento   *)
(* movendo o dado através do array.                                     *)
(*                                                                      *)
(* Note que o Turbo Pascal *fornece* os operadores shl e shr.           *)
(* Contudo, este código é escrito para funcionar com o Pascal Padrão,   *)
(* e não apenas em Turbo Pascal.                                        *)
(*                                                                      *)
(* ShiftLeft desloca os valores em func para a esquerda e insere o      *)
(* valor deslocado no bit de posição zero                               *)
 
procedure ShiftLeft(shiftin:integer);
var i:integer;
begin
     for i := 15 downto 1 do func[i] := func[i-1];
     func[0] := shiftin;
end;
 
(* ShiftNibble desloca o dado em func para a esquerda quatro posições e *)
(* insere os quatro bits a , b, c & d nas posições vagas                *)
 
procedure ShiftNibble(d,c,b,a:integer);
begin
     ShiftLeft(d);
     ShiftLeft(c);
     ShiftLeft(b);
     ShiftLeft(a);
end;
 
(* ShiftRight desloca o dado em func uma posição à direita. Desloca     *)
(* um zero para dentro do bit de mais alta ordem do array.              *)
 
procedure ShiftRight;
var i:integer;
begin
     for i := 0 to 14 do func[i] := func[i+1];
     func[15] := 0;
end;
 
(* ToUpper converte um caracter minúsculo para maiúsculo.               *)
 
procedure toupper(var ch:char);
begin
     if (ch in ['a'..'z']) then ch := chr(ord(ch) - 32);
end;
 
(* ReadFunc lê um número de função hexadecimal fornecido pelo usuário   *)
(* e põe este valor no array func (bit a bit)                           *)
 
function ReadFunc:integer;
var ch:char;
    i, val:integer;
begin
     write('Entre o número da função (hexadecimal): ');
     for i := 0 to 15 do func[i] := 0;
     repeat
           read(ch);
           if not eoln then begin
                      toupper(ch);
                      case ch of
                           '0': ShiftNibble(0,0,0,0);
                           '1': ShiftNibble(0,0,0,1);
                           '2': ShiftNibble(0,0,1,0);
                           '3': ShiftNibble(0,0,1,1);
                           '4': ShiftNibble(0,1,0,0);
                           '5': ShiftNibble(0,1,0,1);
                           '6': ShiftNibble(0,1,1,0);
                           '7': ShiftNibble(0,1,1,1);
                           '8': ShiftNibble(1,0,0,0);
                           '9': ShiftNibble(1,0,0,1);
                           'A': ShiftNibble(1,0,1,0);
                           'B': ShiftNibble(1,0,1,1);
                           'C': ShiftNibble(1,1,0,0);
                           'D': ShiftNibble(1,1,0,1);
                           'E': ShiftNibble(1,1,1,0);
                           'F': ShiftNibble(1,1,1,1);
                           else write(chr(7),chr(8));
                      end;
           end;
     until eoln;
     val := 0;
     for i := 0 to 15 do val := val + func[i];
     ReadFunc := val;
end;
 
(* Generic - Calcula a função lógica genérica especificada pelo *)
(*           número da função "func" nas quatro variáveis       *)
(*           a, b, c & d.  Faz isto retornando o bit            *)
(*           d*8 + c*4 + b*2 + a da função.                     *)
 
function Generic(var func:gftype; a,b,c,d:integer):integer;
begin
          Generic := func[a + b*2 + c*4 + d*8];
end;
 
begin (* main *)
      repeat
            fresult := ReadFunc;
            if (fresult <> 0) then begin
               write('Entre os valores para D, C, B, & A (0/1):');
               readln(d, c, b, a);
               writeln('O resultado é ',Generic(func,a,b,c,d));
            end;
      until fresult = 0;
end.
 

O código a seguir demonstra o poder das operações de manipulação de bits. Esta nova versão do código acima utiliza características especiais presentes na linguagem de programação do Turbo Pascal que permitem deslocar bits para a direita ou para a esquerda e fazer um AND lógico bit a bit em variáveis inteiras:

 
program GenericFunc(input,output);
const
     hex = ['a'..'f', 'A'..'F'];
     decimal = ['0'..'9'];
var
   a, b, c, d:integer;
   fresult:integer;
   func: integer;
 
(* Aqui está uma segunda versão da função genérica do Pascal que     *)
(* utiliza as características do Turbo Pascal para simplificar o     *)
(* programa.                                                         *)
 
function ReadFunc:integer;
var ch:char;
    i, val:integer;
begin
     write('Entre o número da função (hexadecimal): ');
     repeat
           read(ch);
           func := 0;
           if not eoln then begin
              if (ch in Hex) then 
                func := (func shl 4) + (ord(ch) and 15) + 9
              else if (ch in Decimal) then 
                func := (func shl 4) + (ord(ch) and 15)
              else write(chr(7));
           end;
     until eoln;
     ReadFunc := func;
end;
 
(* Generic - Calcula a função lógica genérica especificada pelo *)
(*           número da função "func" nas quatro variáveis       *)
(*           a, b, c e d.  Faz isto retornando o bit            *)
(*           d*8 + c*4 + b*2 + a de func. Esta versão deixa o   *)
(*           trabalho para o operador de deslocamento do Turbo  *)
(*           Pascal e sua habilidade para fazer operações em    *)
(*           bits de inteiros.                                  *)
function Generic(func,a,b,c,d:integer):integer;
begin
          Generic := (func shr (a + b*2 + c*4 + d*8)) and 1;
end;
 
begin (* main *)
      repeat
            fresult := ReadFunc;
            if (fresult <> 0) then begin
               write('Entre os valores para D, C, B, & A (0/1):');
               readln(d, c, b, a);
               writeln('O resultado é ',Generic(func,a,b,c,d));
            end;
      until fresult = 0;
end.
 

Fonte

  • Art of Assembly de Randall Hyde.
  • Tradução meio que livre da vovó Vicki.
Última atualização ( Dom, 19.04.2009 20:26 )
 

Topo

Topo

Exceto onde especificamente citado, todo material deste site está sob Licença Creative Commons