Ripensandoci adesso, quell'odioso errore incontrato qualche anno fa, ora mi sembra nulla di più che un semplice bug, ma con le poche conoscenze che avevo allora (e che ho ancora oggi, se penso all'intero sapere informatico) persi parecchio tempo per trovare una soluzione decente.
Avevo cominciato a programmare da poco più di un anno in Pascal, e i miei programmi si limitavano a qualche giochino (tipo MasterMind) o qualche grafico colorato. Usavo Turbo Pascal 7.0, e mi ero imbattuto nel noto errore: «Error 200: division by zero»; inizialmente non capii cosa ci fosse nel mio programma di sbagliato, così cominciai a «commentare» pezzi di codice per vedere se riuscivo a isolare l'errore: niente da fare. Alla fine rimaneva scritto solo questo:
Provai a togliere la prima riga e l'errore scomparve. Al che, divenne chiaro che il problema non era nel mio programma, ma nella unit Crt. Per me significava un punto morto, non sapendo come fare a risolverlo, soprattutto perché l'errore non si manifestava sempre, solo certe volte, anzi, solo su certi computer: scoprii che sui 386 e 486 funzionava, mentre sul mio AMD-K6 400MHz no. Doveva essere legato alla velocità dei computer, ma, non sapendo cosa fare, programmai per qualche tempo senza ricorrere alla unit Crt.
Non era certo semplice, dato che avevo bisogno di funzioni come Readkey o Keypressed; per non parlare dei colori: non riuscivo a scrivere testo colorato, dato che non avevo la funzione Textcolor.
Dopo qualche mese, mi accorsi che non riuscivo ad andare avanti, dovevo trovare una soluzione!
Le soluzioni erano 2: aggirare l'ostacolo (non usare la unit Crt), o non rispettare le regole, correggendo i miei programmi (patchare il codice). Certo, non avevo idea che in internet ci fossero così tante soluzioni al mio stesso problema, come scoprii in seguito.
Fortunatamente la mia conoscenza dell'assembly mi venne in aiuto; sapevo qualcosa, avendo anche scritto semplici programmini (usando il Debug del DOS, sigh), così mi procurai una buona lista degli interrupts e cercai... Ciò che scoprii mi illuminò: molte delle funzioni della Crt, non erano altro che servizi dell'int 21h, come Readkey (servizio 08h) o Keypressed (servizio 0Bh). Scrissi così la Crt2, una nuova unit, con le stesse (o quasi) funzioni della Crt, scritte da me; per esempio:
Function ReadKey: Char; Assembler;
Asm
MOV AH, 008h
INT 021h
End;
Procedure HighVideo; Assembler;
Asm
MOV AX, 01003h
MOV BX, 00000h
INT 010h
End;
Riuscii così a programmare per parecchi mesi, ma non ero ancora contento dato che il problema non era stato risolto.
Così un pomeriggio, armato di molta pazienza, tentai di correggere i miei programmi.
Utilizzando un buon disassembler, esaminai l'entry point degli eseguibili compilati con la unit Crt; erano più o meno così:
00000060: 9A00006400 call 00064:00000
00000065: 9A0D000200 call 00002:0000D
0000006A: 55 push bp
0000006B: 89E5 mov bp,sp
0000006D: 31C0 xor ax,ax
Mentre quelli compilati senza Crt erano:
00000050: 9A00000200 call 00002:00000
00000055: 55 push bp
00000056: 89E5 mov bp,sp
00000058: 31C0 xor ax,ax
Da ciò ho capito che la call che creava problemi era quella che puntava all'offset 000Dh, e andando ad esaminare il codice ho scoperto che l'unica operazione che potesse causare un errore di divisione per 0 era la seguente DIV:
0000010A: F7D0 not ax
0000010C: F7D2 not dx
0000010E: B93700 mov cx,00037
00000111: F7F1 div cx
00000113: A35C00 mov [0005C],ax
In questo caso, se il dividendo (DX:AX) è troppo grande (come accade con pc troppo veloci), la divisione genera un errore.
Così, sostituii 037h con 0137h, in tal modo, pur sapendo che non sarebbe stata una soluzione del tutto corretta, il mio programma funzionava (senza visibili cambiamenti nell'esecuzione dopo la modifica)! Fu semplice scrivere un programmino che cercasse quella sequenza di istruzioni nei programmi, e sostituisse il byte funesto.
Poi estesi la modifica anche alla Crt originale, cercando quelle istruzioni nella libreria di Turbo Pascal e correggendole. Ora potevo anche fare a meno di correggere i programmi che scrivevo, visto che la Crt non produceva più quel fastidioso errore.
Potevo ritenermi soddisfatto, avevo risolto un fastidioso problema (sebbene non eccessivamente complesso) tutto da solo e, per un ragazzo di 16 anni qual ero io, tutto ciò dà veramente una grande soddisfazione.