0 = 0? Falso. O Quê??!
O dia que Zero foi diferente de Zero!!
[singlepic id=7202 w=320 h=240 float=]
Isso aconteceu de verdade!! Um dia zero não foi igual a zero!! Calma. Vou explicar. Embora pareça uma aberração matemática isso aconteceu, e me trouxe uma imensa dor de cabeça. É provável que muitos membros do ForumPCs tenham começado a usar computadores já na era Windows. Por isso vou me permitir voltar um pouco no tempo para explicar melhor o contexto que essa aparente aberração aconteceu. Talvez já saibam por ter lido em alguma de minhas colunas anteriores que tenho uma opinião severa em relação ao estágio de desenvolvimento do software em relação ao hardware : Acho que tem algo errado e A base de dados cresceu .
Houve um tempo que só um programa podia ser executado de uma só vez. Era o tempo do DOS. Qualquer versão. Nunca o DOS permitiu o que é trivial e prosaico em tempos de Windows, Unix e Linux, o ambiente multitarefa. Hoje em dia é muito comum trabalharmos com muitos programas (no meu caso dezenas) abertos ao mesmo tempo. Word, Internet Explorer, Windows Explorer, Excel, Power Point, Visual Studio, SQL Enterprise Manager, Dreamweaver, Skype, Messenger -uma lista sem fim de programas minimizados prontinhos, a espera de um clique para voltarem à ativa. Mas nessa época de DOS havia um interessante recurso que permitia ter em menores proporções este tipo de comodidade. Eram os programas tipo “TSR”-sigla que significava “Terminate and Stay Resident”. Era um tipo de programa que depois de chamado era “finalizado” instantaneamente. Na verdade usava recursos de “DOS interrupts” ou “BIOS interrupts” para associar atalhos de teclado a estes programas que permaneciam carregados na memória, mas em estado de “dormência”. Um dos programas mais famosos da época era o SIDEKICK, que continha um editor de textos, agenda, tarefas, telefones, discador etc. Era muito popular porque ele permitia alternar o uso entre um programa e o próprio SIDEKICK, ao toque de uma combinação de teclas. Aparecia por cima na tela e depois ao acionar as “teclas mágicas” (shift shift), este sumia e voltávamos a usar o programa que estava ativo antes. Era assombroso para a época! Para quem desenvolvia software como eu, era uma mão na roda. SHIFT SHIFT abria o editor de textos (o notepad da época). Fazia as alterações no sistema sendo desenvolvido e SHIFT SHIFT voltava para o ambiente usado (dBASE III) e já podia testar o programa, sem precisar sair e entrar de novo no dBASE.
Uma base de assembler era necessária na época para fazer programas deste tipo. Essencialmente se “capturava” uma das interrupções de software do DOS ou BIOS, substituindo parte dessa rotina com o programa tipo TSR, desviando no final para o código original daquela interrupção capturada. Vale mencionar que havia uma “Bíblia” na época que eu usava para esta finalidade, um verdadeiro clássico : “Peter Norton Programmer?s Guide to IBM PC”. Usei este livro até o início da era Pentium e ainda hoje é uma referência muito interessante.
Explicado todo o contexto vamos descobrir porque ZERO foi diferente de ZERO em certo momento. Eu trabalhava na época em um projeto de software muito interessante. O ano era 1986. Eu desenvolvia um software para fazer a comunicação entre os PCs e os Mainframes. O módulo mais “simples” fazia transferência de arquivos (análogo a um FTP). O mais complexo era uma plataforma que permitia que outros desenvolvedores usassem funções de Mainframe em seus programas, sem que eu precisasse entregar para eles a minha solução. Era um programa TSR (residente) que era acionado por diversas linguagens possíveis (dBASE, Clipper, TurboPascal, C, etc.). Para quem desenvolve software, era como uma API publicada para acessar funções disponíveis. Quando se usa este tipo de serviço, um tipo de dado é fundamental. O código de retorno. Esta informação serve para que o programa tome uma decisão após ter chamado um destes serviços, como por exemplo, invocar uma transação no Mainframe. Se tudo deu certo o tal código de retorno era ZERO e no caso de algo ter dado errado obtínhamos um número com o código do erro para que o programa decidisse o que fazer.
A plataforma mais fácil para testar era o dBASE III porque era um ambiente interativo. Uma linha de comando permitia executar as instruções da API que eu desenvolvi para todas as funções. Nos testes, cada comando acionado na seqüência exibia o tal código de retorno. Aparecia na tela o número ZERO-“0”. Não era a letra “O”, era o algarismo zero mesmo. Como tudo estava certo passei a desenvolver sistemas mais elaborados usando esta API (na forma de programa TSR). O resultado foi UMA CATÁSTROFE!! TODAS as chamadas à API de comunicação PC-Mainframe resultava em erro. O mesmo comando feito no modo interativo, na linha de comando do dBASE sempre resultava em “0”, ou seja, sem erro. A pressão era grande, pois o prazo para implantar aquela solução específica já estava estourado. Num ato de desespero, uma vez que não conseguia achar a razão de em modo interativo sempre dar certo e em modo programado sempre acusar erro, eu inclui no programa final aquelas famosas (e pouco elegantes) impressões de mensagens na tela com valores de variáveis de memória. ESPANTO TOTAL!! O retorno era ZERO e mesmo assim o programa assumia que houvera erro no processo.
Voltando ao ambiente interativo do dBASE, ampliei o meu teste um pouco mais. Realizava a chamada ao Mainframe e na seqüência emitia os seguintes comandos:
.PRINT Retorno
.0(era o resultado esperado-sem erro portanto zero)
. PRINT (Retorno = 0)
. FALSE (!!!!!!!!!!!!!!!!!!!!! Esse Zero não é igual a Zero !!!!!!!)
Como pode?? O mistério aumentava com outros testes desesperados.
.Teste=0
PRINT Teste
.0(só podia imprimir isso mesmo)
. PRINT (Teste = 0)
. TRUE (Claro !!)
Ou seja, o ZERO retornado pela minha API não era reconhecido como zero pelo ambiente interativo do dBASE, nem de sua versão compilada, o Clipper. Para complicar de vez a solução do problema, rodando as funções da API direto em seu ambiente nativo (Turbo Pascal e Assembler) tudo funcionava, ou seja o ZERO era reconhecido como ZERO mesmo. Eu poderia gastar aqui alguns parágrafos contando as mazelas, infortúnios e quase crucificação que sofri por conta dessa aberração. Mas vou poupá-los dessa parte chata da história. Muitos dias e noites depois depurando o código com o CODEVIEW (depurador assembler que vinha no Microsoft “C”) descobri a solução. Veja a tabela abaixo :
[singlepic id=7200 w=320 h=240 float=]
Como o programa residente tinha sido feito em Turbo Pascal + Assembler e o ambiente de uso, dBASE e Clipper, tinham sido feitos em “C”, havia uma diferença na representação interna do ZERO. No Turbo Pascal o ZERO tinha o último BIT ligado, o BIT do sinal. No “C” o ZERO tem todos os bits desligados. Falando de outra forma no Pascal o ZERO é 0 . Quando a rotina da API fazia a transferência do retorno para a variável de memória para o dBASE/Clipper (“C”), iam todos os bits, incluindo o bit de sinal. Isso provocava aquele comportamento bizarro do zero não ser reconhecido. Uma vez descoberto o problema a solução não levou 30 segundos para ser implementada, que foi filtrar o bit de sinal do zero do Pascal.
Ufa! Que sufoco, que pressão e que caso estranho. Uma lembrança disso ainda trago comigo até hoje. Alguns fios de cabelos brancos que surgiram precocemente e que hoje se somam aos que vieram depois, seja pela idade ou por outros “causos” estanhos como esse que passei…
Posto este adendo no meu artigo hoje em 19/07. Em uma conversa com o mestre Piropo estes dias ele me fez descobrir que cometi um engano no decorrer do texto. Eu citei que os ZEROs eram diferentes um positivo e outro sem sinal. Na verdade um dos zeros era NEGATIVO e o outro sem sinal. Isso porque na representação de números inteiros nas linguagens de computador existem os SIGNED INTEGERS e os UNSIGNED INTEGERS. Os inteiros com sinal tem um bit reservado exatamente para o sinal e se este bit está ligado o número é negativo. Desculpo-me com meus leitores pelo engano. Sei que vocês me perdoarão pois isso já faz quase 19 anos…