Ir ao conteúdo
  • Cadastre-se

Do fluxograma para o Programa


MOR_AL

Posts recomendados

Olá pessoal.

 

Em meus projetos com PIC16F628A, aprendi a usar a linguagem Assembly muito bem e costumo obter uma grande redução da memória de programa se comparado a linguagens de mais alto nível. Com 2k de memória de programa se consegue fazer muita coisa com essa linguagem.

 

Mas a evolução para programas maiores está sendo mais complicada, justamente pelo fato de eu sempre partir de um fluxograma. 

 

Aí é que vem o MEU problema.

Escuto que não se deve usar a instrução GOTO, porque ela cria confusão no entendimento do programa. Eu concordo em parte. Mas se houver um fluxograma disponível, o programa fica bem mais inteligível.

Minha dúvida é a seguinte.

Na figura abaixo há uma opção melhor que usar o GOTO?

Informo que já apresentei o problema em outro fórum e que os colegas apresentaram uma brilhante solução. Criaram uma tabela verdade e simplificaram o programa. Mas eu também gostaria de saber, se haveria uma opção ao GOTO X no programa da figura. Onde "X" é o endereço (Label) depois do bloco "A", no While (1).

Grato.

MOR_AL

 

FluxoProgr.thumb.jpg.9dbe48616b45a0590396a0e8d4e675e5.jpg

 

Link para o comentário
Compartilhar em outros sites

  • Membro VIP

Sim Moris. Vejamos com comentários...

while (1)
{
//x:
while(!B); //! inverte. Então algo como... aguarde enquanto B=0
if (C || E) //|=OR ... || algo como OR de bit = se C ou E
	{
	if (C) D; //se C faça D
	if (E) F; //se E faça F
	}
//goto x:
}

Perceba o comentado goto x: implícito

Sei lá... pra mim foi só exercício mental...Talvez desastrado mas... tentei né... Se não me der nota zero, pra mim é lucro...😁

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

  • Membro VIP

Perdão velho amigo... Esqueci de dizer que quando se coloca duas barras...

//goto x: //isso é apenas um comentário ... do comentário 

é apenas um comentário, ou seja, o compilador nem dá bola pra isso. Ele ignora, entende? E sim, tentei avaliar seu fluxograma e traduzir pra pseudo código quasi-c. Infelizmente, direto pra assembly vou ficar te devendo. Mas penso que nele não deve haver restrições ao uso do goto, senão te complica ou até mesmo te inviabiliza seu uso, não?

abç

Link para o comentário
Compartilhar em outros sites

@Isadora Ferraz

OK....quase. Hehe!

Sei que o que vem depois de // é comentário..

Não estou falando da linguagem Assembly e sim pseudo código para linguagem de mais alto nível que o Assembly, como o C ou o Basic.

Em seu código.....

 

12 horas atrás, Isadora Ferraz disse:

if (C) D; //se C faça D

 

Vamos supor que "C" seja verdadeiro, então faz "D". Até aí tudo bem. Repare que no fluxograma anterior, não haveria o teste ...

12 horas atrás, Isadora Ferraz disse:

if (E) F; //se E faça F

 

De "D" deveria ir para 

12 horas atrás, Isadora Ferraz disse:

while(!B);

 

Então, acho que ao invés de 

12 horas atrás, Isadora Ferraz disse:

if (C) D; //se C faça D

Poderia ser isso?

if (C){

  D;

else

  if (E) F;  

}

MOR_AL

Link para o comentário
Compartilhar em outros sites

46 minutos atrás, Isadora Ferraz disse:

10! Moris. Vai tirar a rodinha da bicicleta rapidin kk.

De fato, eu aprendi C há trezentos anos... na época em que os dados eram guardados em disquetes....Perdi todas as informações. Os disquetes eram atacados por fungos e duravam cerca de 2 anos.

MOR_AL

Link para o comentário
Compartilhar em outros sites

Programa linear puro, será? Será que um while já não tem um GOTO implícito?

 

De qualquer forma, @MOR, sem GOTO:

 

- o programa só seria executado uma única vez

- o then e o else de um if teriam que ter instruções repetidas em relação aos de um outro if

 

Aliás um if já tem um GOTO implícito, também. Um if endereça alguma posição na memória que não a posição seguinte ao próprio if.

 

Agora, que a solução com tabela-verdade poupa GOTO, isso poupa mesmo. Não fica puro linear porque implica em decisão, mas que poupa, poupa. Se puder e quiser, traz o caso verdade, @MOR...

  • Curtir 2
Link para o comentário
Compartilhar em outros sites

Como o salto de D() para A() é forçado no seu fluxograma, GOTO é o comando natural. O problema apontado em muitos comentários sobre o GOTO é que se em outra parte do programa quiser reutilizar D() vai criar bagunça.

adicionado 5 minutos depois

Me assustam muito mais fluxos com rede intrincada de CALLs condicionais. Se entrar em sequência onde o CALL superar o RET adeus pilha. Mesmo havendo a paridade de CALL e RET na escrita do programa um GOTO pode quebrar a paridade da execução.

  • Curtir 2
Link para o comentário
Compartilhar em outros sites

Tive que fazer um programa que tinha 6 entradas e duas saídas. Comecei com o fluxograma e logo vi que daria um emaranhado lógico. Aí parti para a tabela verdade, que teve 64 linhas.
Delas fiz apenas 2 mapas de Karnaugh 4x4.
A solução tornou o programa incrivelmente simples.
Portanto fazer o fluxograma nem sempre é a melhor opção.

Mudei as minhas conclusões:

1 - Fazer a tabela verdade.
2 - Fazer o mapa de karnaugh.
3 -  Partir para um programa tentando evitar o GOTO.

Para os que tiverem interesse, segue a imagem do problema e da solução. Aliás, não sei se escrevi corretamente o programa em C de uma variável barrada. (S2M barrado e S3M barrado).

Talvez a Isa possa me corrigir neste detalhe.

MOR_AL
 

Água_Marcos.jpg

  • Curtir 2
Link para o comentário
Compartilhar em outros sites

Em 10/02/2020 às 12:23, rmlazzari58 disse:

Aliás um if já tem um GOTO implícito, também. Um if endereça alguma posição na memória que não a posição seguinte ao próprio if.

GOTO, JUMPER, BRANCH, um monte de nomes para a mesma coisa, se bem que BRANCH tb pode ser um CALL. No meio de tanta salada a tabelinha tornou o programa muito mais enxuto e fácil, seja em assembler ou C.

Parabéns pela simplificação do desafio.

  • Curtir 2
Link para o comentário
Compartilhar em outros sites

  • Membro VIP
6 horas atrás, MOR disse:

possa me corrigir

O barrado está correto.

Sei que é pseudo código mas como você nos evocou, foquemos no c...

Quanto ao solitário & (and) pra condição binária funciona quase sempre. Geralmente coloca-se 2 & pro sistema saber que é condição binária e não operação lógica

if (SM2 && !SM3)... fica mais "aprazível" pro compilador

P.ex. ...  vamos aproveitar e simplificar ainda mais? Que tal...

while (1) //eu prefiro for(;;)
{
B1=S1m & S1M & !S2M;
B2=S2m & !S3M;
}

Perceba agora que há operação lógica então... & sozinho necessário

 

Ah  me lembrei... Um operador lógico de inversão é o ~. (o ! é negação)

Portanto algo como...

B1=S1m & S1M & ~S2M;
B2=S2m & ~S3M;

Tende a ficar mais logicamente coerente... e talvez também dê certo...

 

6 horas atrás, MOR disse:

1 - Fazer a tabela verdade.
2 - Fazer o mapa de karnaugh.

Puts nem lembro + nada sobre isso.

  • Curtir 2
Link para o comentário
Compartilhar em outros sites

7 horas atrás, Isadora Ferraz disse:

O barrado está correto.

Sei que é pseudo código mas como você nos evocou, foquemos no c...

Quanto ao solitário & (and) pra condição binária funciona quase sempre. Geralmente coloca-se 2 & pro sistema saber que é condição binária e não operação lógica

 

Na verdade todas as variáveis do programinha são bits de um byte. Algo como S1m equivale ao bit Byte.x (x de 0 a 7). Então acho que apenas um & estaria certo, né?

 

if (SM2 && !SM3)... fica mais "aprazível" pro compilador

P.ex. ...  vamos aproveitar e simplificar ainda mais? Que tal...


while (1) //eu prefiro for(;;)
{
B1=S1m & S1M & !S2M;
B2=S2m & !S3M;
}

Perceba agora que há operação lógica então... & sozinho necessário

 

Ah  me lembrei... Um operador lógico de inversão é o ~. (o ! é negação)

 

Os bits S2M e S3M barrados possuem o prefixo !, não é?

 

Portanto algo como...

B1=S1m & S1M & ~S2M;

 

B1 = S1m & S1M & !S2M // Eu quis dizer que se os bits valerem S1m = 1 & S1M = 1 & S2M = 0, então o bit B1 = 1 lógico. Está certo?


B2=S2m & ~S3M;

Tende a ficar mais logicamente coerente... e talvez também dê certo...

 

Puts nem lembro + nada sobre isso.

 

MOR_AL

Link para o comentário
Compartilhar em outros sites

  • Membro VIP
12 minutos atrás, MOR disse:

Os bits S2M e S3M barrados possuem o prefixo !, não é?

Sim. Eu uso o ! mais pra avaliar se o bit é zero. Ele á algo como "não 1". .. o que no mundo binário só pode ser...?? ???.... zero. Pra inverter efetivamente e fazer operações uso e ouso usar ~

 

 

15 minutos atrás, MOR disse:

B1 = S1m & S1M & !S2M // Eu quis dizer que se os bits valerem S1m = 1 & S1M = 1 & S2M = 0, então o bit B1 = 1 lógico. Está certo?

Também sim. Ou seja B1 é o resultado das operações supramencionadas. Perceba que são operações e não condições lógicas do if. No fundo é a lesma lerda mas me deu vontade registrar aquela taquigrafia... Já que tá escovando bits, se achar que deve, compare os assemblys gerados de ambos.

Link para o comentário
Compartilhar em outros sites

7 horas atrás, Isadora Ferraz disse:

Sei que é pseudo código mas como você nos evocou, foquemos no c...

Quanto ao solitário & (and) pra condição binária funciona quase sempre. Geralmente coloca-se 2 & pro sistema saber que é condição binária e não operação lógica

Como tem detalhes... nos obriga a retornar ao básico.

Extraido da Microsoft:

 

Operador AND lógico &

O operador & computa o AND lógico de seus operandos. O resultado de x & y será true se ambos x e y forem avaliados como true. Caso contrário, o resultado será false.

O operador & avalia os dois operandos mesmo que o operando esquerdo seja avaliado como false, de modo que o resultado da operação seja false, independentemente do valor do operando à direita.

No exemplo a seguir, o operando à direita do operador & é uma chamada de método, que é executada independentemente do valor do operando à esquerda:

 

C#

bool SecondOperand()
{
    Console.WriteLine("Second operand is evaluated.");
    return true;
}

bool a = false & SecondOperand();
Console.WriteLine(a);
// Output:
// Second operand is evaluated.
// False

bool b = true & SecondOperand();
Console.WriteLine(b);
// Output:
// Second operand is evaluated.
// True

 

O operador AND lógico condicional && também computa o AND lógico e seus operandos, mas não avalia o operando à direita se o operando à esquerda for avaliado como false.

Para os operandos dos tipos numéricos inteiros, o operador de & computa a lógica de bit e de seus operandos. O operador & unário é o operador address-of.

adicionado 3 minutos depois

https://docs.microsoft.com/pt-br/dotnet/csharp/language-reference/operators/boolean-logical-operators#logical-and-operator-

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

  • Membro VIP

entendi nada kk

Só sei que tem compilador que chia se eu fizer

if (a&b)

Dá um warning avisando que usei & no lugar de &&. Mas como disse, funciona quase sempre...Acho que ele se sente melhor se fizer if ((a&b)==0) .. sei lá.

aqui tem neguinho chutando mais sobre...

https://www.guj.com.br/t/diferenca-entre-os-operadores-logico-e/38032/4

Link para o comentário
Compartilhar em outros sites

O que entendi sobre & e &&

 

No && o programa escapa para para a execução FALSE na primeira ausência do TRUE.

 

No & as condições são verificadas independente do primeiro resultado. Dessa forma, se o segundo operador vier a ser uma função (ou método ou sub-rotina, etc) esta será executada independente da condição do primeiro operador, o que não ocorrerá no && se o primeiro operador for falso.

 

Caso minha interpretação esteja errada serei grato pela correção.

Link para o comentário
Compartilhar em outros sites

  • Membro VIP

Puts... vacilei ... o compilador chia se fizer

if (a=b)...

ele pede gentilmente pra trocar pra if (a==b)...

Coisa de eternamente 'principiante' kk... herrar é umano (vulgo to nem aí com a mrd)

Mas é melhor fazer os testes na prática... algo como Moris acabou de perguntar enquanto eu digitava...

 

Sim Moris

4 minutos atrás, MOR disse:

if (PINB.0 | PINB.1)  PORTB.2 = 0;

isso tem tudo pra dar certo...  Mas de novo, prefira ||. Faça o teste com ambos e confira os assembly... e claro, o resultado...

Link para o comentário
Compartilhar em outros sites

17 minutos atrás, MOR disse:

Pessoal!

Na linguagem C para AVR, tem como fazer um "OU", ou um "E" entre bits de um mesmo registrador?

Exemplo:

if (PINB.0 | PINB.1)  PORTB.2 = 0;

Ou tenho que fazer...


if (PINB.0 & 0b00000001) PORTB.2 = 0;
if (PINB.1 & 0b00000010) PORTB.2 = 0;

Valeu!

MOR_AL

 

Morris, boa noite

Vamos por partes. A operação (que afeta o registrador de STATUS da CPU) é sempre feita entre 2 variáveis. No caso específico da consulta é usada variável interna zero. Comparar 1 bit com 1 byte me parece demais para a CPU. Estou raciocinando em assembler.

A primeira alternativa faz sentido.

A segunda me parece insana. A consulta ao bit retorna apenas alteração do registrador de STATUS, não retorna valor da memória ou registro, não altera nenhum registrador de uso geral para a ALU fazer operação AND ou OR com um byte.

Link para o comentário
Compartilhar em outros sites

3 horas atrás, Sérgio Lembo disse:

Comparar 1 bit com 1 byte me parece demais para a CPU.

Puxa é mesmo. Nem percebi.

Seria isso?

if (PINB & 0b00000001) PORTB.2 = 0;

if (PINB & 0b00000010) PORTB.2 = 0;

 

3 horas atrás, Sérgio Lembo disse:

A primeira alternativa faz sentido.

Faz sentido, mas o compilador compreenderia essa instrução?

if (PINB.0 | PINB.1)  PORTB.2 = 0;

MOR_AL

Link para o comentário
Compartilhar em outros sites

Se é para comparar com byte, vamos comparar 2 bytes.

if (PORTB & 0b00000011) PORTB.2 = 0;

Força a leitura da portaB, faz AND com os bits 0 e 1 isolando os demais. Basta que 1 deles seja 1 para que o resultado seja diferente de zero (true).

adicionado 12 minutos depois

Esta última opção deve resultar num código assembler mais enxuto. Na opção com leitura dos pinos, uma leitura para cada pino, 1 interpretação de status para cada pino e finalmente operação OR entre os status para resultado. Nessa apenas uma leitura e uma comparação com 1 valor fixo. Creio que o assembler resultante dê no máximo 4 códigos.

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...