Ir para conteúdo
Fórum Script Brasil
  • 0

Esquentando A Moringa


kmkg

Pergunta

Para as horas vagas

var b1,b2:Boolean; Baiti:Byte;
begin
  Baiti := 8;
  b1    := true;
  Move(Baiti, b2, 1);
  if b1 and b2 then
    ShowMessage('b2 é true')
  else
  if b1 and not b2 then
    ShowMessage('b2 não é true')
  else
  if b1 then
    ShowMessage('O compilador ficou meio maluco')
  else
    ShowMessage('O compilador ficou maluco');
end;

Link para o comentário
Compartilhar em outros sites

14 respostass a esta questão

Posts Recomendados

  • 0

kmkg, sabendo que no Delphi, TRUE = $01 e FALSE = $00, como poderia o processador testar $01 and $08 e dar certo (serem iguais), ou qualquer das outras operações?

Já se você utilizar no teste: if Bool(b1) and Bool(b2) then, neste caso terá a resposta correta, já que utilizando o type-cast BOOL qualquer coisa diferente de $00 será interpretado como TRUE.

[]s

Link para o comentário
Compartilhar em outros sites

  • 0

Claro porque qualquer valor acima de 0 será considerado true. Mas o que acontecerá se você fizer um and lógico entre 8 e 1, veja ->

00000001
  and
00001000
  ==
00000000

ou seja, false.

Certo?

A propósito, muito bom o título do seu tópico. Só de ler já da pra saber do que se trata.

Link para o comentário
Compartilhar em outros sites

  • 0

Acho que é isso mesmo, ele efetua a comparação pelo valor binário do campo.

quanto ao título é porque fiquei umas 4 horas pra achar este erro(erro meu de programa), depois ví num outro fórum a mesma coisa entitulado: Variável Boolean nem true, nem false. Aconteceu com outro também a mesma coisa.

Link para o comentário
Compartilhar em outros sites

  • 0

Entendendo a diferença entre as duas formas(meu post anterior) de testar no if.

Parece-me uma questão de como o compilar otimiza o código. Vamos escovar bits?

Vejamos o código gerado pelo compilador para este fragmento de código pascal:

  b1    := true;
MOV BL,$01  // *** BL é utilizado para "apontar" para b1

  Move(Baiti, b2, 1);
LEA EDX,[EBP-$01]  // *** [EBP-$01] aponta para b2
LEA EAX,[EBP-$02]  // *** [EBP-$02] aponta para Baiti
MOV ECX,$00000001  // *** Número de bytes a ser movido - 1 
CALL Move
  if b1 and b2 then
TEST [EBP-$01],BL  // *** aqui $08 está sendo testado com $01, similar a um AND, não haverá bit setado
                   // *  de modo que o registrador de flag ZF será SETADO. 
JZ +$0C      // *** fará cair no ELSE caso ZF esteja setado (1) em função da execução da instrução anterior.
    ShowMessage('b2 é true')
  else
  if b1 then
  if Bool(b1) and Bool(b2) then
TEST BL,BL  // *** artifício para verificar se o valor de b1 é verdadeiro - se houver um bit LIGADO (qualquer)
            // *   o registrador de flag ZF ficará zerado. Isto é parte da otimização do compilador - basta
            // *   que um dos testes seja falso para pular a sentença
JZ +$12   // *** fará cair no ELSE caso ZF esteja setado (1) em função da execução da instrução anterior.
          // *  Em nosso caso, b1 = $01, logo ZF ficará ZERADO e não haverá desvio
CMP BYTE PTR [EBP-$01], $00  // *** aqui se o BYTE apontado (PTR) pelo endereço [EBP-$01] (b2) for 
                             // *   igual a $00 (zero), o registrador de flag ZF será setado (1)
JZ +$0C  // *** fará cair no ELSE caso ZF esteja setado (1) em função da execução da instrução anterior.
         // * Em nosso caso, b2 = $08, logo ZF ficará ZERADO e não haverá desvio
    ShowMessage('b2 é true')
  else
  if b1 then

Referencias: Link1, Link2 e Link3

Link para o comentário
Compartilhar em outros sites

  • 0
Haja paciência para descer tanto; eu não iria tão longe.
kmkg, não precisa muita não, basta acessar o menu View->Debug Windows->CPU. Mas, a idéia proposta por você acho que era justamente de entender o porque de tão "estranho" comportamento - não?!

Apenas completando...

Claro porque qualquer valor acima de 0 será considerado true.
Thales, isto só é verdade devido a forma simplificada pela qual o compilador faz esta validação, já que sabemos por definição da linguagem que o tipo boolean só pode ter dois valores TRUE(1) e FALSE(0) . Este o motivo de a atribuição forçada do kmkg não estar funcionando corretamente e o teste simples apenas da variável b2 funcionar.
Mas o que acontecerá se você fizer um and lógico entre 8 e 1
Foi exatamente este tipo de proposição que o compilador utilizou na situação proposta pelo kmkg, já que o esperado era que os valores fossem 0 ou 1 e um AND deste tipo resulta em zero, como você bem exemplificou.

Entendo que o compilador interpreta um terceiro valor para a variável Boolean.
kmkg, observe que foi VOCE quem atribuiu um terceiro valor - forçosamente. Como disse, para o compilador um Boolean é apenas TRUE(1) e FALSE(0) - ele não se preocupa com outra possibilidade; Se apenas com o BIT, e não o BYTE inteiro, não ocorreria tal problema.

Observar que se for feiro um type-cast para Boolean, também teremos a mesma contrução por parte do compilador. E como fica possível o bservar, na primeira situação (if b1 and b2 then) a validação (teste) desvia ser o resultado não for VERDADEIRO, enquanto na segunda (if Bool(b1) and Bool(b2) then) desvia se o resultado for FALSO. São duas formas de "dizer" a mesma coisa mas que o resultado pode mudar.

Deste modo, fica a dica para o caso de alguém utilizar algo como o proposto pelo colega kmkg, de utilizar o type-cast de modo que tudo que não for FALSO será VERDADEIRO, de modo que o "compilador não ficará meio maluco".

[]s

Link para o comentário
Compartilhar em outros sites

  • 0
Micheus, baixo nível mesmo hein ?

Haja paciência para descer tanto; eu não iria tão longe.

Acredito que se você não achasse explicação no asm, iria até os circuitos eletrônicos.

Parabéns ! ! !

muito bom Micheus

Não me digam que vocês entenderam esse assembly que o Micheus escreveu.

Link para o comentário
Compartilhar em outros sites

  • 0
Não me digam que vocês entenderam esse assembly que o Micheus escreveu.
Eu não e passo longe do Assembly.

Este foi um erro sutil que me aconteceu e fiquei algumas horas para achá-lo porque tenho que utilizar o Move no recebimento de dados de uma classe que trabalha com Sockets; então de acordo com o tipo de dado vindo pelo SendBuf, alimento os campos Double, Integer, Smallint, Boolean, etc . . .

O que aconteceu foi o envio de um tipo Byte com valor 8 que joguei para um Boolean e com isso a condição não satisfazia true e nem false.

Link para o comentário
Compartilhar em outros sites

  • 0
Não me digam que vocês entenderam esse assembly que o Micheus escreveu.
Thales, não foi eu quem escreveu não. Foi o que a janela da CPU me mostrou (View->Debug Windows->CPU) - você deverá ver algo parecido - mudando apenas os endereços.

você deve ter notado que as linhas em ASM correspondem a do Delphi logo acima, e há alguns comentários ao lado para tentar explicar o que ocorre. Se não ficou claro posso tentar melhorar a explicação (já tentei fazer isto no post anterior).

Minha inteção era apenas buscar uma explicação mais razoável para o meu primeiro post.

Algumas vezes tenho a impressão que há uma certa disputa por aqui - o que é uma pena. É justamente com a inclusão de idéias diferentes ou de afirmações que nossos horizontes se expandem. Lembrando, sempre que as discursões são acompanhadas/lidas por outros colegas que apenas aproveitam o "conhecimento" que está sendo passado.

[]s

Link para o comentário
Compartilhar em outros sites

  • 0

não foi eu quem escreveu não.

Claro que não foi você, senão não seria como o compilador faz, seria o seu jeito. Eu quis dizer que foi você quem leu o código, entendeu, e explicou seu funcionamento para nós.

Minha inteção era apenas buscar uma explicação mais razoável para o meu primeiro post.

Estaria claro se você dissesse que com variável boolean o operador and faz um and lógico no byte o que resultaria em zero, e que com variável BOOL primeiro ele converte qualquer coisa acima de 0 pra 1 e faz o and lógico, por isso funciona.

Algumas vezes tenho a impressão que há uma certa disputa por aqui - o que é uma pena.

Disputa? Mas que disputa? A que você está se referindo?

Cuidado pro tópico não virar flood.

Link para o comentário
Compartilhar em outros sites

  • 0
e que com variável BOOL primeiro ele converte qualquer coisa acima de 0 pra 1 e faz o and lógico, por isso funciona.
Não é isto que ele faz. Não com esta palavras.

Ele compara o valor a ser testado com zero (que significa FALSO), e o único jeito de isto ser verdade é se este valor for 0 (zero) - não há qualquer conversão para 1.

[]s

Link para o comentário
Compartilhar em outros sites

  • 0
Não é isto que ele faz. Não com esta palavras.

Ele compara o valor a ser testado com zero (que significa FALSO), e o único jeito de isto ser verdade é se este valor for 0 (zero) - não há qualquer conversão para 1.

Ou seja, pra funcionar com tipo boolean e imitar o que ele faz com BOOL teria que ser->

if (byte(b2) <> 0) and b1 then
begin
.
.
.
end;

Link para o comentário
Compartilhar em outros sites

Participe da discussão

Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.

Visitante
Responder esta pergunta...

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emoticons são permitidos.

×   Seu link foi incorporado automaticamente.   Exibir como um link em vez disso

×   Seu conteúdo anterior foi restaurado.   Limpar Editor

×   Você não pode colar imagens diretamente. Carregar ou inserir imagens do URL.



  • Estatísticas dos Fóruns

    • Tópicos
      152,3k
    • Posts
      652,3k
×
×
  • Criar Novo...