Newsgroup: it.comp.lang.c
Titolo: programma oscuro

Ciao a tutti
Mi e' stato proposto il seguente programma :
----------------------------------------------------------------
#include <stdio.h>
void main(void)
{
 printf(&__MSDOS__["\021%sao\012\0"],(__MSDOS__)["tanti"]+"baci"-0x5F);
}
----------------------------------------------------------------
Si tratta di un codice che dovrebbe avere vinto alcuni anna fa un qualche premio
per la sua scarsa chiarezza  *:)
Scrive semplicemente "ciao" sullo schermo.
Dall'help del BC3.1 ho trovato che __MSDOS__ coincide con il numero 1.
Sostituendo le due scritte la printf diventa :
 printf(&1["\021%sao\012\0"],(1)["tanti"]+"baci"-0x5F);
ed il tutto continua a funzionare correttamente.
C'e' qualcuno in grado di spiegare come funziona ?
Ciao
-----------------------------------------------------------------------------------
Email: sostituire "nospam" con "netsis"

C'e' qualcuno in grado di spiegare come funziona ?
A naso dovrebbe chiamre l'INT 21 del dos, che e' la system call per
effettuare dell'I/O
___
Fabio Forno
  "Vi aspetta l'esplorazione delle ignote 
  possibilita' dell'esistenza" 
  - Q in "All Good Things..."
=============================================
scia...@inorbit.com
http://rampage.ml.org/sector1/~sciasbat/
=============================================

 
Ordunque:
Primo fatto "Strano ma Vero": se V e' un array V[1] e identico a 1[V].
Secondo fatto "Strano ma Vero": dato che una stringa e' in effetti un
array 1["stringa"] e' identico a 't' (secondo carattere della stringa).
Terzo  fatto "Strano ma Vero": &1["stringa"] => "tringa" cioe' la stringa
che parte dal secondo elemento.
Quindi 1["\021%sao\012\0"] e' identico a "%sao\012\0". '\012' e' Line Feed
e '\0' puo' essere ignorato quindi il tutto e' uguale a "%sao\n". Questo e'
piu' familiare? %s (stampa una variabile stringa) seguita da "ao" e poi a
capo. 
A questo punto quale e' la variabile (deve essere un puntatore dato che si
stampa con %s)?    (1)["tanti"]+"baci"-0x5F
Per quanto sopra detto (1)["tanti"] => 'a' => 0x61.
Quindi abbiamo 0x61+"baci"-0x5F. Cioe' "baci" + 2 ovvero l'indirizzo della
stringa "baci" aumentato di 2 => puntatore a "ci".
risultato finale:   printf("%sao\n","ci");
Stampa "ci" seguito da "ao". QED
Ciao, 
       GianPiero
-- 
*  Istituto Nazionale di Ottica                        GianPiero Puccioni  *
*  Largo E.Fermi 6                               E-Mail :  
g...@fox.ino.it
  *
*  I-50125  Firenze - ITALY    =>this space intentionally left non-blank<= *

risultato finale:   printf("%sao\n","ci");
Grande !   :-)


 Email: sostituire "nospam" con "netsis"
Credo di aver capito qualcosa di piu' riguardo questo codice.
Secondo il prototipo della printf() la parte che viene dopo la virgola deve essere una
stringa da sostituire al posto di %s che compare nella prima parte. Togliendo dal codice
la parte dopo la virgola viene stampato
ao
quindi (1)["tanti"]+"baci"+0x5F deve sicuramente stare per "ci".
Ho provato a cambiare la parola "baci" con altre parole e mi sono accorto che non vengono
stampate le prime due lettere. Ad esempio se a "baci" si sostituisce "attrici" viene 
stampato a video 
triciao
Si tratta di un gioco di puntatori. Praticamente all'indirizzo di "baci" viene sommato il 
valore (1)["tanti"] e poi viene sottratto 0x5F. Ho provato a stampare il valore esadecimale 
di (1)["tanti"] ed effettivamente e' 0x61, cosi' non si fa altro che sommare 2 all'indirizzo
di "baci" in modo tale che la printf() inizi a stampare la stringa da due posizioni piu' a
destra.
Perche' il valore di (1)["tanti"] e' 0x61 ?
Anche qui ho cambiato qualche lettera notando che il valore dipende solo dal secondo
carattere della stringa, in questo caso 'a'. Guarda caso il valore esadecimale della 'a'
e' proprio 0x61.
Se si prova a sostituire (2) al posto di (1) viene ritornato il valore del carattere 'n'
quindi questo mi ricorda l'accesso a memoria base+spiazzamento di certe istruzioni
assembly (non crediate che conosca l'assembler, ho visto solo qualche listato) tuttavia
su nessun libro del linguaggio C ho trovato indicazioni su questo tipo di accesso a
memoria e sarei grato se qualcuno potessi dirmi qualcosa di piu'.
Comunque ora il codice diventa
printf(&1["\021%sao\012\0"],"ci");
Per la parte che precede la virgola mi e' stato piu' chiaro capirne il significato:
la stringa tra virgolette viene considerata tutta a partire dal secondo carattere, cioe' '%',
infatti \021 e' una sequenza di escape e viene considerata un unico carattere (per la 
precisione corrisponde a DC1 Device Control 1, tuttavia non ha importanza in quanto non
viene considerato). Si tratta sempre di qualcosa di simile all'assembler e anche su questo
avrei bisogno di chiarimenti. Siamo giunti a
printf("%sao\012\0","ci");
A questo punto \012 corrisponde alla sequenza di escape per LF Line Feed e puo' essere quindi
sostituita dal carattere \n.
Infine \0 e' il caarattere nullo che in questo caso non ha alcun effetto e si puo' eliminare.
Alla fine il codice diventa
printf("%sao\n","ci");
oppure, come scriverebbero tutte le persone senza disturbi mentali
printf("ciao\n");
Spero di essere stato chiaro.
Ciao
                                   Andrea
----------------------------------------------------------------------------------------------
         Andrea Cadei                
ac52...@silab.dsi.unimi.it
 
c...@cybergal.com
----------------------------------------------------------------------------------------------

 Perche' il valore di (1)["tanti"] e' 0x61 ?
Basta notare che l'espressione p[n] viene valutata come *(p+n).
Considera ad esempio questo caso:
char *p;
int n;
Allora p[n] equivale a *(p+n) che equivale a *(n+p) cioe' n[p].
Nota che questo e' vero solo perche` sizeof(char)==1, in quanto nel secondo passaggio si sta
incrementando n volte un puntatore, mentre nel secondo caso il puntatore viene convertito ad un
intero e ci viene sommato n.
?manu*

 Grande !   :-)
certo che si deve essere impegrato a scrivere una cosa del genere ;)
---
Ranger, email 
ran...@queen.it
http://members.tripod.com/%7Eranger_rg/

certo che si deve essere impegrato a scrivere una cosa del genere ;)
Questo e' sicuro  :-)
Ciao


 
Credo che quel commento si riferisse originariamente all'autore del
"programma oscuro" sorgente del thread. Ma mi sembra che poi sia stato
interpretato in varie maniere. O e' solo una mia impressione?


interpretato in varie maniere. O e' solo una mia impressione?
Io l'ho interpretato come un riferimento al tipo che ha scritto il programma
originale  ;-)
