-
Ci si capisce, vero?Scritto daaltgutente che non utieneil 2014-10-29 19:40:05.0 alle 2014-10-29 19:40:05.0Trollate totali: 11540Ci si capisce un casino!
E` tutto molto espressivo e ovvio.
include rc include text nameset text to From ByteString r "binaural fn to From ByteString "monaural fn creates a text object from a byte-aligned null-terminated string, such as those built by the compiler e.g. when you type @8:{ Hello! }, or generally read from ASCII files (does not support UTF-8; another function will probably be developed for that, once someone provides means to render the characters outside the historical ASCII range...) --> m = firstByte (byte select mask) --> n = R (first unit in source buffer) --> p = r (start address in source buffer) --> q (future start address in target buffer) --> r = 0 (source bytes counter, starts at zero) repeat if n has m (as long as no null terminator found) r + 1 (increment bytes counter) m ] 8 (rotate mask, e.g. FF000000 -> 00FF0000) if m eq firstByte p + 1 (access next unit in source buffer) n = P (load new source buffer unit) <-- p (p = entry r, i.e. initial source address) q <- rc::Pick r Units (q = target buffer) r <- rc::Size Of q (r = back to abovely determined byte-size) --> q (will be returned to caller) --> v = firstByte (free register v, use as byte select mask) m = 0 (rotation magnitude, starts at zero) r times (each byte in source) m + 8 (increase rotation: make that 8 for first byte) n = P (read current source unit) n & v (mask off all bytes except the relevant one) n [ m (rotate the relevant byte to its place, i.e...) Q = n (left-most of the target unit, hereby written) if m eq bitsPerUnit p + 1 (full circle? ok, access next unit in source) m = 0 (and reset rotation magnitude) q + 1 (access next unit in target buffer) v ] 8 (rotate mask, e.g. FF000000 -> 00FF0000) <-- v (restore v - it's callers' vicinity pointer) <-- r (we had stacked target buffer before v) <-- q (callee-saved) <-- p (callee-saved) <-- n (callee-saved) <-- m (callee-saved) return r (we return the target buffer address)
Oh ma comunque una cosa del genere (conversione di una stringa ASCII da un allineamento a 8 bit a uno a 32 bit per carattere), penso sarebbe piuttosto oscura anche se la scrivessi in javascript. Comunque ho commentato tutto, il che spiega molte cose e non sto affatto prendendo per il culo, no, cosa andate mai a pensare?
Vabbe' ragazzi, ovviamente poi uno 'ste cose se le trova pronte e le chiama e basta. Cioe` in un esempio da tutorial, 'sta roba e` solo usata, non scritta, il che viene fuori piu` comprensibilmente cosi`:startup displayStatus engage include text fromByteString include text say include util pause to Begin text::From ByteString @8:{ Hello } -> Say each P inside \ [ @8:{ _Mercury }, @8:{ _Venus }, @8:{ _Earth }, @8:{ _Mars }, @8:{ _Jupiter }, @8:{ _Saturn }, @8:{ _Uranus }, @8:{ _Neptune }, @8:{ _and_maybe_Pluto } ] text::From ByteString P -> Say util::Pause leave
E qui dai si capisce.
Testo::daStringaDiBytes @8:{ questa } -> Dillo
Dove @8 imposta la wordsize, cioe` gli dice fai 8 bit per carattere.
Per default la fa lunga un'unita`, cioe` una parola della CPU, cioe` 32 bit qui.
E poi "per ogni P in un array di stringhe di bytes", fai la stessa cosa con P.
Pausa e poi chiudi il programma.
L'output e` ovviamente "Hello Mercury Venus Earth Mars Jupiter Saturn Uranus Neptune and maybe Pluto".
Ah, gli underscore nelle stringhe marcano gli spazi.
Dai che si capisce, dai, non mi puoi dire... no? come no?
-
Re: Ci si capisce, vero?Scritto daNon Autenticatoil 2014-10-29 20:05:42.0 alle 2014-10-29 20:05:42.0Scritto da: altg
> Ci si capisce un casino!
> E` tutto molto espressivo e ovvio.
>
>> include rc > include text > nameset text > > > to From ByteString r "binaural fn > to From ByteString "monaural fn > > creates a text object from a byte-aligned null-terminated string, > such as those built by the compiler e.g. when you type @8:{ Hello! }, > or generally read from ASCII files (does not support UTF-8; another > function will probably be developed for that, once someone provides > means to render the characters outside the historical ASCII range...) > > --> m = firstByte (byte select mask) > --> n = R (first unit in source buffer) > --> p = r (start address in source buffer) > --> q (future start address in target buffer) > --> r = 0 (source bytes counter, starts at zero) > > repeat if n has m (as long as no null terminator found) > > r + 1 (increment bytes counter) > m ] 8 (rotate mask, e.g. FF000000 -> 00FF0000) > > if m eq firstByte > > p + 1 (access next unit in source buffer) > n = P (load new source buffer unit) > > <-- p (p = entry r, i.e. initial source address) > > q <- rc::Pick r Units (q = target buffer) > r <- rc::Size Of q (r = back to abovely determined byte-size) > > --> q (will be returned to caller) > --> v = firstByte (free register v, use as byte select mask) > > m = 0 (rotation magnitude, starts at zero) > > r times (each byte in source) > > m + 8 (increase rotation: make that 8 for first byte) > n = P (read current source unit) > n & v (mask off all bytes except the relevant one) > n [ m (rotate the relevant byte to its place, i.e...) > Q = n (left-most of the target unit, hereby written) > > if m eq bitsPerUnit > > p + 1 (full circle? ok, access next unit in source) > m = 0 (and reset rotation magnitude) > > q + 1 (access next unit in target buffer) > v ] 8 (rotate mask, e.g. FF000000 -> 00FF0000) > > <-- v (restore v - it's callers' vicinity pointer) > <-- r (we had stacked target buffer before v) > <-- q (callee-saved) > <-- p (callee-saved) > <-- n (callee-saved) > <-- m (callee-saved) > > return r (we return the target buffer address) >
>
> Oh ma comunque una cosa del genere (conversione di una stringa ASCII da un allineamento a 8 bit a uno a 32 bit per carattere), penso sarebbe piuttosto oscura anche se la scrivessi in javascript. Comunque ho commentato tutto, il che spiega molte cose e non sto affatto prendendo per il culo, no, cosa andate mai a pensare?
>
> Vabbe' ragazzi, ovviamente poi uno 'ste cose se le trova pronte e le chiama e basta. Cioe` in un esempio da tutorial, 'sta roba e` solo usata, non scritta, il che viene fuori piu` comprensibilmente cosi`:
>
>> startup displayStatus engage > include text fromByteString > include text say > include util pause > > > to Begin > > text::From ByteString @8:{ Hello } -> Say > > each P inside \ > > [ > > @8:{ _Mercury }, > @8:{ _Venus }, > @8:{ _Earth }, > @8:{ _Mars }, > @8:{ _Jupiter }, > @8:{ _Saturn }, > @8:{ _Uranus }, > @8:{ _Neptune }, > @8:{ _and_maybe_Pluto } > > ] > > text::From ByteString P -> Say > > util::Pause > leave >
>
> E qui dai si capisce.
> Testo::daStringaDiBytes @8:{ questa } -> Dillo
> Dove @8 imposta la wordsize, cioe` gli dice fai 8 bit per carattere.
> Per default la fa lunga un'unita`, cioe` una parola della CPU, cioe` 32 bit qui.
> E poi "per ogni P in un array di stringhe di bytes", fai la stessa cosa con P.
> Pausa e poi chiudi il programma.
> L'output e` ovviamente "Hello Mercury Venus Earth Mars Jupiter Saturn Uranus Neptune and maybe Pluto".
> Ah, gli underscore nelle stringhe marcano gli spazi.
> Dai che si capisce, dai, non mi puoi dire... no? come no?
Che ne pensano quelli di ANOwhere?-
Re: Ci si capisce, vero?Scritto daaltgutente che non utieneil 2014-10-29 21:29:06.0 alle 2014-10-29 21:29:06.0Trollate totali: 11540> Che ne pensano quelli di ANOwhere?
Niente, a loro lo presento quando ho qualcosa di vagamente piu` completo e con un tutorial che abbraccia argomenti piu` interessanti della conversione di stringhe da 8 a 32 bit. A proposito, l'output del compilatore per quella routine:
dovrebbe evidenziare come il rapporto fra le istruzioni nel sorgente e quelle nell'output sia vicino a 1:1, insomma il fatto che fin qui non tradisce la sua natura di "assembly sotto un'altra forma". Poi c'e` a chi piacera` e a chi dira` che era meglio un CIL a stack machine invece di fare register naming a mano, ma a me mi piace cosi`.
-
-
Re: Ci si capisce, vero?Scritto daavvelentaniCubicolarioil 2014-10-30 08:29:50.0 alle 2014-10-30 08:29:50.0Trollate totali: 18184non si capisce un cazzo.I think happiness is love
- Vladimir Putin-
Re: Ci si capisce, vero?Scritto da: avvelentani
> non si capisce un cazzo.
altg -> ... -> ... -> ... -> yoda`"la realta' non e' cosi' terrificante come vogliono farti credere" - Giambo ` - Wakko che cita Giambo-
Re: Ci si capisce, vero?Scritto daaltgutente che non utieneil 2014-10-30 10:44:57.0 alle 2014-10-30 10:44:57.0Trollate totali: 11540> > non si capisce un cazzo.
>
> altg -> ... -> ... -> ... -> yoda
Fra gli omissis chi c'e`?
-
Re: Ci si capisce, vero?Scritto da: altg
> > > non si capisce un cazzo.
> >
> > altg -> ... -> ... -> ... -> yoda
>
> Fra gli omissis chi c'e`?
Diverse forme di vita: Microbi, protovirus, ...`"la realta' non e' cosi' terrificante come vogliono farti credere" - Giambo ` - Wakko che cita Giambo
-
-
Re: Ci si capisce, vero?Scritto daNon Autenticatoil 2014-10-31 17:41:07.0 alle 2014-10-31 17:41:07.0Scritto da: Giambo
> Scritto da: avvelentani
> > non si capisce un cazzo.
>
> altg -> ... -> ... -> ... -> yoda
sei noioso Giambo e pure vile a tirarmi in ballo in ogni thread dove non c'entro nulla
-
-
Re: Ci si capisce, vero?Scritto daaltgutente che non utieneil 2014-10-30 10:41:52.0 alle 2014-10-30 10:41:52.0Trollate totali: 11540> non si capisce un cazzo.

Um...
Ottimo!
E` quello che volevo, cosi` nessuno potra` fare casino col mio linguaggio.
-
Re: Ci si capisce, vero?Scritto daNon Autenticatoil 2014-10-30 10:56:43.0 alle 2014-10-30 10:56:43.0
-
Re: Ci si capisce, vero?Scritto daNon Autenticatoil 2014-10-30 14:15:39.0 alle 2014-10-30 14:15:39.0Scritto da: altg
> > non si capisce un cazzo.
>
>
>
>
>
> Um...
>
> Ottimo!
> E` quello che volevo, cosi` nessuno potra` fare casino col mio linguaggio.
Stai creando l'equivalente informatico di un dialetto parlato solo su alcune creste dell'Himalaya cinese, non collegato ad alcuna lingua esistente.
-
Re: Ci si capisce, vero?Scritto daavvelentaniCubicolarioil 2014-10-30 15:02:50.0 alle 2014-10-30 15:02:50.0Trollate totali: 18184Scritto da: altg
> > non si capisce un cazzo.
>
>
>
>
>
> Um...
>
> Ottimo!
> E` quello che volevo, cosi` nessuno potra` fare casino col mio linguaggio.
1. per capire (vagamente) cosa cazzo stai facendo ho dovuto leggere l'output del disassembler che hai postato
2. firstByte e` terminologia ambigua, si chiama most significant byte
3. mi pare di capire che se usi il nome di un registro con la lettera maiuscola lo dereferenzi -->
il (tra l'altro chi e` che setta EDI/w?)
4. se la stringa di input non fosse 4-allineata (e non vedo per quale motivo una stringa di byte dovrebbe esserlo) non solo ti fai una marea di accessi disallineati (che ammazzerebbero, ad esempio, un ARM) ma potrebbe anche causare un segfault alla fine
5. non capisco perche' il codice sia scritto in modo da essere non-efficiente e non-leggibile, se fosse leggibile l'accesso sarebbe fatto byte per byte, se fosse efficiente il loop con gli shift sulla maschera sarebbe parzialmente srotolato (e a naso mi sa che ci sono modi piu` efficienti di manipolare stringhe su x86)
6. per quale motivo i caratteri delle tue stringhe sono di 32bit quando non supporti unicode? Anche se in un futuro dovessi supportare unicode, per quale motivo scegliere l'encoding massimamente inefficiente come default?
I think happiness is love
- Vladimir Putin-
Re: Ci si capisce, vero?Scritto daNon Autenticatoil 2014-10-30 16:06:47.0 alle 2014-10-30 16:06:47.0Scritto da: avvelentani
>
> 6. per quale motivo i caratteri delle tue stringhe sono di 32bit quando non supporti unicode? Anche se in un futuro dovessi supportare unicode, per quale motivo scegliere l'encoding massimamente inefficiente come default?
>
Sono curioso di vedere come si barcamena su questa.-
Re: Ci si capisce, vero?Scritto daaltgutente che non utieneil 2014-10-31 17:14:41.0 alle 2014-10-31 17:14:41.0Trollate totali: 11540> > 6. per quale motivo i caratteri delle tue stringhe sono di 32bit quando non supporti unicode? Anche se in un futuro dovessi supportare unicode, per quale motivo scegliere l'encoding massimamente inefficiente come default?
> >
>
> Sono curioso di vedere come si barcamena su questa.
Figliolo, io su questi argomenti non mi barcameno.
Vi meno e basta.
-
-
Re: Ci si capisce, vero?Scritto daaltgutente che non utieneil 2014-10-31 17:14:06.0 alle 2014-10-31 17:14:06.0Trollate totali: 11540> 1. per capire (vagamente) cosa cazzo stai facendo ho dovuto leggere l'output del disassembler che hai postato
Ci contavo: almeno quello aiutera` a familiarizzarsi.
> 2. firstByte e` terminologia ambigua, si chiama most significant byte
Qui si chiama first perche` non c'e` ambiguita` dovuta all'endianness. L'endianness della memoria di lavoro e` sempre big: quello piu` a sinistra e` il primo, poi c'e` il secondo, il terzo, il quarto e, sui processori a 64 bit, quinto sesto settimo e ottavo. Quindi non e` ambiguo definirlo in termini posizionali.
> 3. mi pare di capire che se usi il nome di un registro con la lettera maiuscola lo dereferenzi -->
il (tra l'altro chi e` che setta EDI/w?)
Esatto, anche se io la chiamo piu` tradizionalmente indirezione. Dereferenziare e` un termine connesso al C. L'indirezione con spiazzamento zero e` marcata sinteticamente dalla lettera maiuscola.
> 4. se la stringa di input non fosse 4-allineata (e non vedo per quale motivo una stringa di byte dovrebbe esserlo) non solo ti fai una marea di accessi disallineati (che ammazzerebbero, ad esempio, un ARM) ma potrebbe anche causare un segfault alla fine
La stringa di input e` per forza allineata a una boundary di 4 byte, ovvero di un'unita` per come la definisce L.in.oleum (per distinguerla dal significato tradizionalmente confuso di "word"). L'allineamento e` dovuto al fatto che L.in.oleum in nessun punto permette accessi disallineati (in effetti andrebbe a nozze con gli ARM). Semplicemente non conosce i byte: i byte sono parti interne delle unita`.
> 5. non capisco perche' il codice sia scritto in modo da essere non-efficiente e non-leggibile, se fosse leggibile l'accesso sarebbe fatto byte per byte,
Non puoi, altrimenti hai i disallineamenti e problemi di endianness di cui sopra. L.in.oleum sacrifica l'accesso byte per byte per evitare questo genere di problemi, che lo renderebbero irrimediabilmente non portabile (se cambiasse la endianness il sorgente sarebbe da buttare). E poi gli accessi disallineati non ammazzano solo gli ARM, ammazzano anche gli Intel superscalari dal Pentium in poi, che ormai sono CISC di nome, ma di fatto funzionano meglio se li si usa in modo molto simile a un RISC.
> se fosse efficiente il loop con gli shift sulla maschera sarebbe parzialmente srotolato (e a naso mi sa che ci sono modi piu` efficienti di manipolare stringhe su x86)
Intrinsecamente piu` efficienti, penso di no. Se stai pensando a cazzate come rep scasb stai pensando a roba dei tempi del 386, gia` il 486 avrebbe arrancato meno con cicli estesi. Per lo srotolamento, rendo atto che sarebbe un po' piu` efficiente, ma considera che le librerie di quel gruppo sono ottimizzate piu` per compattezza che per velocita`.
> 6. per quale motivo i caratteri delle tue stringhe sono di 32bit quando non supporti unicode? Anche se in un futuro dovessi supportare unicode, per quale motivo scegliere l'encoding massimamente inefficiente come default?
Perche` i processori sono piu` veloci nel manipolare dati di dimensione pari alla loro word, perche` essendo che L.in.oleum manipola bytes solo come parti di una word mantenerle in memoria a una unita` per carattere e` infinitamente piu` comodo ed efficiente, e perche` se le volessi codificare scriverei una routine apposita prima di scaricarle da qualche parte.
Figurati che se fosse compilato su un processore a 64 bit, ogni carattere prenderebbe 64 bit, una specie di inesistente UCS-8. Ma non e` appunto un fatto di avere piu` code points, e` proprio un fatto di allineamento puro e semplice. Non esistono bytes in L.in.oleum, dai tempi della prima versione, ne` possono esistere.-
Re: Ci si capisce, vero?Scritto daNon Autenticatoil 2014-10-31 17:21:21.0 alle 2014-10-31 17:21:21.0Scritto da: altg
> > 1. per capire (vagamente) cosa cazzo stai facendo ho dovuto leggere l'output del disassembler che hai postato
>
> Ci contavo: almeno quello aiutera` a familiarizzarsi.
>
> > 2. firstByte e` terminologia ambigua, si chiama most significant byte
>
> Qui si chiama first perche` non c'e` ambiguita` dovuta all'endianness. L'endianness della memoria di lavoro e` sempre big: quello piu` a sinistra e` il primo, poi c'e` il secondo, il terzo, il quarto e, sui processori a 64 bit, quinto sesto settimo e ottavo. Quindi non e` ambiguo definirlo in termini posizionali.
>
> > 3. mi pare di capire che se usi il nome di un registro con la lettera maiuscola lo dereferenzi -->
il (tra l'altro chi e` che setta EDI/w?)
>
> Esatto, anche se io la chiamo piu` tradizionalmente indirezione. Dereferenziare e` un termine connesso al C. L'indirezione con spiazzamento zero e` marcata sinteticamente dalla lettera maiuscola.
>
> > 4. se la stringa di input non fosse 4-allineata (e non vedo per quale motivo una stringa di byte dovrebbe esserlo) non solo ti fai una marea di accessi disallineati (che ammazzerebbero, ad esempio, un ARM) ma potrebbe anche causare un segfault alla fine
>
> La stringa di input e` per forza allineata a una boundary di 4 byte, ovvero di un'unita` per come la definisce L.in.oleum (per distinguerla dal significato tradizionalmente confuso di "word"). L'allineamento e` dovuto al fatto che L.in.oleum in nessun punto permette accessi disallineati (in effetti andrebbe a nozze con gli ARM). Semplicemente non conosce i byte: i byte sono parti interne delle unita`.
>
> > 5. non capisco perche' il codice sia scritto in modo da essere non-efficiente e non-leggibile, se fosse leggibile l'accesso sarebbe fatto byte per byte,
>
> Non puoi, altrimenti hai i disallineamenti e problemi di endianness di cui sopra. L.in.oleum sacrifica l'accesso byte per byte per evitare questo genere di problemi, che lo renderebbero irrimediabilmente non portabile (se cambiasse la endianness il sorgente sarebbe da buttare). E poi gli accessi disallineati non ammazzano solo gli ARM, ammazzano anche gli Intel superscalari dal Pentium in poi, che ormai sono CISC di nome, ma di fatto funzionano meglio se li si usa in modo molto simile a un RISC.
>
> > se fosse efficiente il loop con gli shift sulla maschera sarebbe parzialmente srotolato (e a naso mi sa che ci sono modi piu` efficienti di manipolare stringhe su x86)
>
> Intrinsecamente piu` efficienti, penso di no. Se stai pensando a cazzate come rep scasb stai pensando a roba dei tempi del 386, gia` il 486 avrebbe arrancato meno con cicli estesi. Per lo srotolamento, rendo atto che sarebbe un po' piu` efficiente, ma considera che le librerie di quel gruppo sono ottimizzate piu` per compattezza che per velocita`.
>
> > 6. per quale motivo i caratteri delle tue stringhe sono di 32bit quando non supporti unicode? Anche se in un futuro dovessi supportare unicode, per quale motivo scegliere l'encoding massimamente inefficiente come default?
>
> Perche` i processori sono piu` veloci nel manipolare dati di dimensione pari alla loro word, perche` essendo che L.in.oleum manipola bytes solo come parti di una word mantenerle in memoria a una unita` per carattere e` infinitamente piu` comodo ed efficiente, e perche` se le volessi codificare scriverei una routine apposita prima di scaricarle da qualche parte.
>
> Figurati che se fosse compilato su un processore a 64 bit, ogni carattere prenderebbe 64 bit, una specie di inesistente UCS-8. Ma non e` appunto un fatto di avere piu` code points, e` proprio un fatto di allineamento puro e semplice. Non esistono bytes in L.in.oleum, dai tempi della prima versione, ne` possono esistere.
un utilizzo efficientissimo della memoria fisica
-
Re: Ci si capisce, vero?Scritto daaltgutente che non utieneil 2014-10-31 17:28:19.0 alle 2014-10-31 17:28:19.0Trollate totali: 11540> > > 1. per capire (vagamente) cosa cazzo stai facendo ho dovuto leggere l'output del disassembler che hai postato
> >
> > Ci contavo: almeno quello aiutera` a familiarizzarsi.
> >
> > > 2. firstByte e` terminologia ambigua, si chiama most significant byte
> >
> > Qui si chiama first perche` non c'e` ambiguita` dovuta all'endianness. L'endianness della memoria di lavoro e` sempre big: quello piu` a sinistra e` il primo, poi c'e` il secondo, il terzo, il quarto e, sui processori a 64 bit, quinto sesto settimo e ottavo. Quindi non e` ambiguo definirlo in termini posizionali.
> >
> > > 3. mi pare di capire che se usi il nome di un registro con la lettera maiuscola lo dereferenzi -->
il (tra l'altro chi e` che setta EDI/w?)
> >
> > Esatto, anche se io la chiamo piu` tradizionalmente indirezione. Dereferenziare e` un termine connesso al C. L'indirezione con spiazzamento zero e` marcata sinteticamente dalla lettera maiuscola.
> >
> > > 4. se la stringa di input non fosse 4-allineata (e non vedo per quale motivo una stringa di byte dovrebbe esserlo) non solo ti fai una marea di accessi disallineati (che ammazzerebbero, ad esempio, un ARM) ma potrebbe anche causare un segfault alla fine
> >
> > La stringa di input e` per forza allineata a una boundary di 4 byte, ovvero di un'unita` per come la definisce L.in.oleum (per distinguerla dal significato tradizionalmente confuso di "word"). L'allineamento e` dovuto al fatto che L.in.oleum in nessun punto permette accessi disallineati (in effetti andrebbe a nozze con gli ARM). Semplicemente non conosce i byte: i byte sono parti interne delle unita`.
> >
> > > 5. non capisco perche' il codice sia scritto in modo da essere non-efficiente e non-leggibile, se fosse leggibile l'accesso sarebbe fatto byte per byte,
> >
> > Non puoi, altrimenti hai i disallineamenti e problemi di endianness di cui sopra. L.in.oleum sacrifica l'accesso byte per byte per evitare questo genere di problemi, che lo renderebbero irrimediabilmente non portabile (se cambiasse la endianness il sorgente sarebbe da buttare). E poi gli accessi disallineati non ammazzano solo gli ARM, ammazzano anche gli Intel superscalari dal Pentium in poi, che ormai sono CISC di nome, ma di fatto funzionano meglio se li si usa in modo molto simile a un RISC.
> >
> > > se fosse efficiente il loop con gli shift sulla maschera sarebbe parzialmente srotolato (e a naso mi sa che ci sono modi piu` efficienti di manipolare stringhe su x86)
> >
> > Intrinsecamente piu` efficienti, penso di no. Se stai pensando a cazzate come rep scasb stai pensando a roba dei tempi del 386, gia` il 486 avrebbe arrancato meno con cicli estesi. Per lo srotolamento, rendo atto che sarebbe un po' piu` efficiente, ma considera che le librerie di quel gruppo sono ottimizzate piu` per compattezza che per velocita`.
> >
> > > 6. per quale motivo i caratteri delle tue stringhe sono di 32bit quando non supporti unicode? Anche se in un futuro dovessi supportare unicode, per quale motivo scegliere l'encoding massimamente inefficiente come default?
> >
> > Perche` i processori sono piu` veloci nel manipolare dati di dimensione pari alla loro word, perche` essendo che L.in.oleum manipola bytes solo come parti di una word mantenerle in memoria a una unita` per carattere e` infinitamente piu` comodo ed efficiente, e perche` se le volessi codificare scriverei una routine apposita prima di scaricarle da qualche parte.
> >
> > Figurati che se fosse compilato su un processore a 64 bit, ogni carattere prenderebbe 64 bit, una specie di inesistente UCS-8. Ma non e` appunto un fatto di avere piu` code points, e` proprio un fatto di allineamento puro e semplice. Non esistono bytes in L.in.oleum, dai tempi della prima versione, ne` possono esistere.
>
> un utilizzo efficientissimo della memoria fisica
Filiolo, che pensi di doverci mantenere, in termini di testo non compresso o non codificato (cioe` su cui devi lavorare prontamente) nella memoria di lavoro? Il database di Wikipedia?
-
Re: Ci si capisce, vero?Scritto daNon Autenticatoil 2014-10-31 17:44:20.0 alle 2014-10-31 17:44:20.0Scritto da: altg
> > > > 1. per capire (vagamente) cosa cazzo stai facendo ho dovuto leggere l'output del disassembler che hai postato
> > >
> > > Ci contavo: almeno quello aiutera` a familiarizzarsi.
> > >
> > > > 2. firstByte e` terminologia ambigua, si chiama most significant byte
> > >
> > > Qui si chiama first perche` non c'e` ambiguita` dovuta all'endianness. L'endianness della memoria di lavoro e` sempre big: quello piu` a sinistra e` il primo, poi c'e` il secondo, il terzo, il quarto e, sui processori a 64 bit, quinto sesto settimo e ottavo. Quindi non e` ambiguo definirlo in termini posizionali.
> > >
> > > > 3. mi pare di capire che se usi il nome di un registro con la lettera maiuscola lo dereferenzi -->
il (tra l'altro chi e` che setta EDI/w?)
> > >
> > > Esatto, anche se io la chiamo piu` tradizionalmente indirezione. Dereferenziare e` un termine connesso al C. L'indirezione con spiazzamento zero e` marcata sinteticamente dalla lettera maiuscola.
> > >
> > > > 4. se la stringa di input non fosse 4-allineata (e non vedo per quale motivo una stringa di byte dovrebbe esserlo) non solo ti fai una marea di accessi disallineati (che ammazzerebbero, ad esempio, un ARM) ma potrebbe anche causare un segfault alla fine
> > >
> > > La stringa di input e` per forza allineata a una boundary di 4 byte, ovvero di un'unita` per come la definisce L.in.oleum (per distinguerla dal significato tradizionalmente confuso di "word"). L'allineamento e` dovuto al fatto che L.in.oleum in nessun punto permette accessi disallineati (in effetti andrebbe a nozze con gli ARM). Semplicemente non conosce i byte: i byte sono parti interne delle unita`.
> > >
> > > > 5. non capisco perche' il codice sia scritto in modo da essere non-efficiente e non-leggibile, se fosse leggibile l'accesso sarebbe fatto byte per byte,
> > >
> > > Non puoi, altrimenti hai i disallineamenti e problemi di endianness di cui sopra. L.in.oleum sacrifica l'accesso byte per byte per evitare questo genere di problemi, che lo renderebbero irrimediabilmente non portabile (se cambiasse la endianness il sorgente sarebbe da buttare). E poi gli accessi disallineati non ammazzano solo gli ARM, ammazzano anche gli Intel superscalari dal Pentium in poi, che ormai sono CISC di nome, ma di fatto funzionano meglio se li si usa in modo molto simile a un RISC.
> > >
> > > > se fosse efficiente il loop con gli shift sulla maschera sarebbe parzialmente srotolato (e a naso mi sa che ci sono modi piu` efficienti di manipolare stringhe su x86)
> > >
> > > Intrinsecamente piu` efficienti, penso di no. Se stai pensando a cazzate come rep scasb stai pensando a roba dei tempi del 386, gia` il 486 avrebbe arrancato meno con cicli estesi. Per lo srotolamento, rendo atto che sarebbe un po' piu` efficiente, ma considera che le librerie di quel gruppo sono ottimizzate piu` per compattezza che per velocita`.
> > >
> > > > 6. per quale motivo i caratteri delle tue stringhe sono di 32bit quando non supporti unicode? Anche se in un futuro dovessi supportare unicode, per quale motivo scegliere l'encoding massimamente inefficiente come default?
> > >
> > > Perche` i processori sono piu` veloci nel manipolare dati di dimensione pari alla loro word, perche` essendo che L.in.oleum manipola bytes solo come parti di una word mantenerle in memoria a una unita` per carattere e` infinitamente piu` comodo ed efficiente, e perche` se le volessi codificare scriverei una routine apposita prima di scaricarle da qualche parte.
> > >
> > > Figurati che se fosse compilato su un processore a 64 bit, ogni carattere prenderebbe 64 bit, una specie di inesistente UCS-8. Ma non e` appunto un fatto di avere piu` code points, e` proprio un fatto di allineamento puro e semplice. Non esistono bytes in L.in.oleum, dai tempi della prima versione, ne` possono esistere.
> >
> > un utilizzo efficientissimo della memoria fisica
>
> Filiolo, che pensi di doverci mantenere, in termini di testo non compresso o non codificato (cioe` su cui devi lavorare prontamente) nella memoria di lavoro? Il database di Wikipedia?
boh-
Re: Ci si capisce, vero?Scritto daaltgutente che non utieneil 2014-10-31 17:50:49.0 alle 2014-10-31 17:50:49.0Trollate totali: 11540> > > > > 1. per capire (vagamente) cosa cazzo stai facendo ho dovuto leggere l'output del disassembler che hai postato
> > > >
> > > > Ci contavo: almeno quello aiutera` a familiarizzarsi.
> > > >
> > > > > 2. firstByte e` terminologia ambigua, si chiama most significant byte
> > > >
> > > > Qui si chiama first perche` non c'e` ambiguita` dovuta all'endianness. L'endianness della memoria di lavoro e` sempre big: quello piu` a sinistra e` il primo, poi c'e` il secondo, il terzo, il quarto e, sui processori a 64 bit, quinto sesto settimo e ottavo. Quindi non e` ambiguo definirlo in termini posizionali.
> > > >
> > > > > 3. mi pare di capire che se usi il nome di un registro con la lettera maiuscola lo dereferenzi -->
il (tra l'altro chi e` che setta EDI/w?)
> > > >
> > > > Esatto, anche se io la chiamo piu` tradizionalmente indirezione. Dereferenziare e` un termine connesso al C. L'indirezione con spiazzamento zero e` marcata sinteticamente dalla lettera maiuscola.
> > > >
> > > > > 4. se la stringa di input non fosse 4-allineata (e non vedo per quale motivo una stringa di byte dovrebbe esserlo) non solo ti fai una marea di accessi disallineati (che ammazzerebbero, ad esempio, un ARM) ma potrebbe anche causare un segfault alla fine
> > > >
> > > > La stringa di input e` per forza allineata a una boundary di 4 byte, ovvero di un'unita` per come la definisce L.in.oleum (per distinguerla dal significato tradizionalmente confuso di "word"). L'allineamento e` dovuto al fatto che L.in.oleum in nessun punto permette accessi disallineati (in effetti andrebbe a nozze con gli ARM). Semplicemente non conosce i byte: i byte sono parti interne delle unita`.
> > > >
> > > > > 5. non capisco perche' il codice sia scritto in modo da essere non-efficiente e non-leggibile, se fosse leggibile l'accesso sarebbe fatto byte per byte,
> > > >
> > > > Non puoi, altrimenti hai i disallineamenti e problemi di endianness di cui sopra. L.in.oleum sacrifica l'accesso byte per byte per evitare questo genere di problemi, che lo renderebbero irrimediabilmente non portabile (se cambiasse la endianness il sorgente sarebbe da buttare). E poi gli accessi disallineati non ammazzano solo gli ARM, ammazzano anche gli Intel superscalari dal Pentium in poi, che ormai sono CISC di nome, ma di fatto funzionano meglio se li si usa in modo molto simile a un RISC.
> > > >
> > > > > se fosse efficiente il loop con gli shift sulla maschera sarebbe parzialmente srotolato (e a naso mi sa che ci sono modi piu` efficienti di manipolare stringhe su x86)
> > > >
> > > > Intrinsecamente piu` efficienti, penso di no. Se stai pensando a cazzate come rep scasb stai pensando a roba dei tempi del 386, gia` il 486 avrebbe arrancato meno con cicli estesi. Per lo srotolamento, rendo atto che sarebbe un po' piu` efficiente, ma considera che le librerie di quel gruppo sono ottimizzate piu` per compattezza che per velocita`.
> > > >
> > > > > 6. per quale motivo i caratteri delle tue stringhe sono di 32bit quando non supporti unicode? Anche se in un futuro dovessi supportare unicode, per quale motivo scegliere l'encoding massimamente inefficiente come default?
> > > >
> > > > Perche` i processori sono piu` veloci nel manipolare dati di dimensione pari alla loro word, perche` essendo che L.in.oleum manipola bytes solo come parti di una word mantenerle in memoria a una unita` per carattere e` infinitamente piu` comodo ed efficiente, e perche` se le volessi codificare scriverei una routine apposita prima di scaricarle da qualche parte.
> > > >
> > > > Figurati che se fosse compilato su un processore a 64 bit, ogni carattere prenderebbe 64 bit, una specie di inesistente UCS-8. Ma non e` appunto un fatto di avere piu` code points, e` proprio un fatto di allineamento puro e semplice. Non esistono bytes in L.in.oleum, dai tempi della prima versione, ne` possono esistere.
> > >
> > > un utilizzo efficientissimo della memoria fisica
> >
> > Filiolo, che pensi di doverci mantenere, in termini di testo non compresso o non codificato (cioe` su cui devi lavorare prontamente) nella memoria di lavoro? Il database di Wikipedia?
>
> boh
Allora ricapitolo gentilmente io: quando fai lavorare il processore su del testo in memoria di lavoro in un compito che dev'essere efficiente, di solito non e` su una serie di 50 copie della divina commedia, ma su relativamente poche stringhe. Nel 99% dei casi non ha molta importanza come sono rappresentate in memoria, perche` se le stringhe sono massiccie vengono lasciate altrove, in memoria di massa o chi per lei, dove si puo` comunque scegliere la codifica piu` opportuna, inclusi vari algoritmi di compressione dal deflate in su. Dove conta il volume, il testo puo` tranquillamente prendere molto meno di 8 bit per carattere. In memoria, poco importa se ne prende 32 o 64.
-
-
-
-
Re: Ci si capisce, vero?Scritto daavvelentaniCubicolarioil 2014-10-31 20:30:06.0 alle 2014-10-31 20:30:06.0Trollate totali: 18184Scritto da: altg
> > 1. per capire (vagamente) cosa cazzo stai facendo ho dovuto leggere l'output del disassembler che hai postato
>
> Ci contavo: almeno quello aiutera` a familiarizzarsi.
>
> > 2. firstByte e` terminologia ambigua, si chiama most significant byte
>
> Qui si chiama first perche` non c'e` ambiguita` dovuta all'endianness. L'endianness della memoria di lavoro e` sempre big: quello piu` a sinistra e` il primo, poi c'e` il secondo, il terzo, il quarto e, sui processori a 64 bit, quinto sesto settimo e ottavo. Quindi non e` ambiguo definirlo in termini posizionali.
IMHO "first" e` comunque ambiguo, msb no.
>
> > 3. mi pare di capire che se usi il nome di un registro con la lettera maiuscola lo dereferenzi -->
il (tra l'altro chi e` che setta EDI/w?)
>
> Esatto, anche se io la chiamo piu` tradizionalmente indirezione. Dereferenziare e` un termine connesso al C. L'indirezione con spiazzamento zero e` marcata sinteticamente dalla lettera maiuscola.
Ma usare una cosa normale tipo * o [] o ?
> > 4. se la stringa di input non fosse 4-allineata (e non vedo per quale motivo una stringa di byte dovrebbe esserlo) non solo ti fai una marea di accessi disallineati (che ammazzerebbero, ad esempio, un ARM) ma potrebbe anche causare un segfault alla fine
>
> La stringa di input e` per forza allineata a una boundary di 4 byte, ovvero di un'unita` per come la definisce L.in.oleum (per distinguerla dal significato tradizionalmente confuso di "word"). L'allineamento e` dovuto al fatto che L.in.oleum in nessun punto permette accessi disallineati (in effetti andrebbe a nozze con gli ARM). Semplicemente non conosce i byte: i byte sono parti interne delle unita`.
Quindi se uno volesse accedere ad un file mmappato ti ci devi contorcere attorno?
>
> > 5. non capisco perche' il codice sia scritto in modo da essere non-efficiente e non-leggibile, se fosse leggibile l'accesso sarebbe fatto byte per byte,
>
> Non puoi, altrimenti hai i disallineamenti e problemi di endianness di cui sopra. L.in.oleum sacrifica l'accesso byte per byte per evitare questo genere di problemi, che lo renderebbero irrimediabilmente non portabile (se cambiasse la endianness il sorgente sarebbe da buttare). E poi gli accessi disallineati non ammazzano solo gli ARM, ammazzano anche gli Intel superscalari dal Pentium in poi, che ormai sono CISC di nome, ma di fatto funzionano meglio se li si usa in modo molto simile a un RISC.
Con "ammazzano" intendevo che se lo fai ti becchi un SIGBUS, AFAIK in amd64 ottieni un degradamento delle prestazioni e basta. BTW in ARM esistono anche LDRB/LDRH/STRB/STRH.
>
> > se fosse efficiente il loop con gli shift sulla maschera sarebbe parzialmente srotolato (e a naso mi sa che ci sono modi piu` efficienti di manipolare stringhe su x86)
>
> Intrinsecamente piu` efficienti, penso di no. Se stai pensando a cazzate come rep scasb stai pensando a roba dei tempi del 386, gia` il 486 avrebbe arrancato meno con cicli estesi. Per lo srotolamento, rendo atto che sarebbe un po' piu` efficiente, ma considera che le librerie di quel gruppo sono ottimizzate piu` per compattezza che per velocita`.
Questo e` il modo in cui viene implemento da gcc:0x000000000040054b <+43>: mov rdx,rsp 0x000000000040054e <+46>: mov ecx,DWORD PTR [rdx] 0x0000000000400550 <+48>: add rdx,0x4 0x0000000000400554 <+52>: lea eax,[rcx-0x1010101] 0x000000000040055a <+58>: not ecx 0x000000000040055c <+60>: and eax,ecx 0x000000000040055e <+62>: and eax,0x80808080 0x0000000000400563 <+67>: je 0x40054e <main+46> 0x0000000000400565 <+69>: mov ecx,eax 0x0000000000400567 <+71>: mov esi,0x400734 0x000000000040056c <+76>: mov edi,0x1 0x0000000000400571 <+81>: shr ecx,0x10 0x0000000000400574 <+84>: test eax,0x8080 0x0000000000400579 <+89>: cmove eax,ecx 0x000000000040057c <+92>: lea rcx,[rdx+0x2] 0x0000000000400580 <+96>: cmove rdx,rcx 0x0000000000400584 <+100>: add al,al 0x0000000000400586 <+102>: sbb rdx,0x3 0x000000000040058a <+106>: xor eax,eax 0x000000000040058c <+108>: sub rdx,rbx
a occhio mi sembra parecchio piu` efficiente.
>
> > 6. per quale motivo i caratteri delle tue stringhe sono di 32bit quando non supporti unicode? Anche se in un futuro dovessi supportare unicode, per quale motivo scegliere l'encoding massimamente inefficiente come default?
>
> Perche` i processori sono piu` veloci nel manipolare dati di dimensione pari alla loro word,
I processori sono anche piu` veloci a manipolare cose che stanno nella cache e moltiplicare per 4 la dimensione di tutte le stringhe non aiuta.
> perche` essendo che L.in.oleum manipola bytes solo come parti di una word mantenerle in memoria a una unita` per carattere e` infinitamente piu` comodo ed efficiente, e perche` se le volessi codificare scriverei una routine apposita prima di scaricarle da qualche parte.
>
> Figurati che se fosse compilato su un processore a 64 bit, ogni carattere prenderebbe 64 bit, una specie di inesistente UCS-8. Ma non e` appunto un fatto di avere piu` code points, e` proprio un fatto di allineamento puro e semplice. Non esistono bytes in L.in.oleum, dai tempi della prima versione, ne` possono esistere.
Mi sembra una follia.I think happiness is love
- Vladimir Putin-
Re: Ci si capisce, vero?Scritto daNon Autenticatoil 2014-10-31 20:39:12.0 alle 2014-10-31 20:39:12.0Scritto da: avvelentani
> Scritto da: altg
> > > 1. per capire (vagamente) cosa cazzo stai facendo ho dovuto leggere l'output del disassembler che hai postato
> >
> > Ci contavo: almeno quello aiutera` a familiarizzarsi.
> >
> > > 2. firstByte e` terminologia ambigua, si chiama most significant byte
> >
> > Qui si chiama first perche` non c'e` ambiguita` dovuta all'endianness. L'endianness della memoria di lavoro e` sempre big: quello piu` a sinistra e` il primo, poi c'e` il secondo, il terzo, il quarto e, sui processori a 64 bit, quinto sesto settimo e ottavo. Quindi non e` ambiguo definirlo in termini posizionali.
>
> IMHO "first" e` comunque ambiguo, msb no.
Propongo MSByte
> > > 3. mi pare di capire che se usi il nome di un registro con la lettera maiuscola lo dereferenzi -->
il (tra l'altro chi e` che setta EDI/w?)
> >
> > Esatto, anche se io la chiamo piu` tradizionalmente indirezione. Dereferenziare e` un termine connesso al C. L'indirezione con spiazzamento zero e` marcata sinteticamente dalla lettera maiuscola.
>
> Ma usare una cosa normale tipo * o [] o ?
Facciamo * O [] o così mi ricorda i loghi di gengiva.
> > > 4. se la stringa di input non fosse 4-allineata (e non vedo per quale motivo una stringa di byte dovrebbe esserlo) non solo ti fai una marea di accessi disallineati (che ammazzerebbero, ad esempio, un ARM) ma potrebbe anche causare un segfault alla fine
> >
> > La stringa di input e` per forza allineata a una boundary di 4 byte, ovvero di un'unita` per come la definisce L.in.oleum (per distinguerla dal significato tradizionalmente confuso di "word"). L'allineamento e` dovuto al fatto che L.in.oleum in nessun punto permette accessi disallineati (in effetti andrebbe a nozze con gli ARM). Semplicemente non conosce i byte: i byte sono parti interne delle unita`.
>
> Quindi se uno volesse accedere ad un file mmappato ti ci devi contorcere attorno?
>
> >
> > > 5. non capisco perche' il codice sia scritto in modo da essere non-efficiente e non-leggibile, se fosse leggibile l'accesso sarebbe fatto byte per byte,
> >
> > Non puoi, altrimenti hai i disallineamenti e problemi di endianness di cui sopra. L.in.oleum sacrifica l'accesso byte per byte per evitare questo genere di problemi, che lo renderebbero irrimediabilmente non portabile (se cambiasse la endianness il sorgente sarebbe da buttare). E poi gli accessi disallineati non ammazzano solo gli ARM, ammazzano anche gli Intel superscalari dal Pentium in poi, che ormai sono CISC di nome, ma di fatto funzionano meglio se li si usa in modo molto simile a un RISC.
>
> Con "ammazzano" intendevo che se lo fai ti becchi un SIGBUS, AFAIK in amd64 ottieni un degradamento delle prestazioni e basta. BTW in ARM esistono anche LDRB/LDRH/STRB/STRH.
>
> >
> > > se fosse efficiente il loop con gli shift sulla maschera sarebbe parzialmente srotolato (e a naso mi sa che ci sono modi piu` efficienti di manipolare stringhe su x86)
> >
> > Intrinsecamente piu` efficienti, penso di no. Se stai pensando a cazzate come rep scasb stai pensando a roba dei tempi del 386, gia` il 486 avrebbe arrancato meno con cicli estesi. Per lo srotolamento, rendo atto che sarebbe un po' piu` efficiente, ma considera che le librerie di quel gruppo sono ottimizzate piu` per compattezza che per velocita`.
>
> Questo e` il modo in cui viene implemento da gcc:
>
>> 0x000000000040054b <+43>: mov rdx,rsp > 0x000000000040054e <+46>: mov ecx,DWORD PTR [rdx] > 0x0000000000400550 <+48>: add rdx,0x4 > 0x0000000000400554 <+52>: lea eax,[rcx-0x1010101] > 0x000000000040055a <+58>: not ecx > 0x000000000040055c <+60>: and eax,ecx > 0x000000000040055e <+62>: and eax,0x80808080 > 0x0000000000400563 <+67>: je 0x40054e <main+46> > 0x0000000000400565 <+69>: mov ecx,eax > 0x0000000000400567 <+71>: mov esi,0x400734 > 0x000000000040056c <+76>: mov edi,0x1 > 0x0000000000400571 <+81>: shr ecx,0x10 > 0x0000000000400574 <+84>: test eax,0x8080 > 0x0000000000400579 <+89>: cmove eax,ecx > 0x000000000040057c <+92>: lea rcx,[rdx+0x2] > 0x0000000000400580 <+96>: cmove rdx,rcx > 0x0000000000400584 <+100>: add al,al > 0x0000000000400586 <+102>: sbb rdx,0x3 > 0x000000000040058a <+106>: xor eax,eax > 0x000000000040058c <+108>: sub rdx,rbx >
>
> a occhio mi sembra parecchio piu` efficiente.
>
> >
> > > 6. per quale motivo i caratteri delle tue stringhe sono di 32bit quando non supporti unicode? Anche se in un futuro dovessi supportare unicode, per quale motivo scegliere l'encoding massimamente inefficiente come default?
> >
> > Perche` i processori sono piu` veloci nel manipolare dati di dimensione pari alla loro word,
>
> I processori sono anche piu` veloci a manipolare cose che stanno nella cache e moltiplicare per 4 la dimensione di tutte le stringhe non aiuta.
>
> > perche` essendo che L.in.oleum manipola bytes solo come parti di una word mantenerle in memoria a una unita` per carattere e` infinitamente piu` comodo ed efficiente, e perche` se le volessi codificare scriverei una routine apposita prima di scaricarle da qualche parte.
> >
> > Figurati che se fosse compilato su un processore a 64 bit, ogni carattere prenderebbe 64 bit, una specie di inesistente UCS-8. Ma non e` appunto un fatto di avere piu` code points, e` proprio un fatto di allineamento puro e semplice. Non esistono bytes in L.in.oleum, dai tempi della prima versione, ne` possono esistere.
>
> Mi sembra una follia.
-
Re: Ci si capisce, vero?Scritto daaltgutente che non utieneil 2014-10-31 21:54:17.0 alle 2014-10-31 21:54:17.0Trollate totali: 11540> > > 1. per capire (vagamente) cosa cazzo stai facendo ho dovuto leggere l'output del disassembler che hai postato
> >
> > Ci contavo: almeno quello aiutera` a familiarizzarsi.
> >
> > > 2. firstByte e` terminologia ambigua, si chiama most significant byte
> >
> > Qui si chiama first perche` non c'e` ambiguita` dovuta all'endianness. L'endianness della memoria di lavoro e` sempre big: quello piu` a sinistra e` il primo, poi c'e` il secondo, il terzo, il quarto e, sui processori a 64 bit, quinto sesto settimo e ottavo. Quindi non e` ambiguo definirlo in termini posizionali.
>
> IMHO "first" e` comunque ambiguo, msb no.
IMHO pero` msb e` meno comprensibile. Poi per carita`, mi va bene anche MSB e probabilmente nelle istruzioni avro` l'occasione di precisare che e` quello. Tanto piu` che non avremo neanche ambiguita` come l'LSD (Least Significant Doubleword).
> > > 3. mi pare di capire che se usi il nome di un registro con la lettera maiuscola lo dereferenzi -->
il (tra l'altro chi e` che setta EDI/w?)
> >
> > Esatto, anche se io la chiamo piu` tradizionalmente indirezione. Dereferenziare e` un termine connesso al C. L'indirezione con spiazzamento zero e` marcata sinteticamente dalla lettera maiuscola.
>
> Ma usare una cosa normale tipo * o [] o ?
Lo facevo, lo feci, lo facetti, ne feci le veci. In L.in.oleum 1, si scriveva b per intendere il registro b, e [b] per intendere il contenuto della locazione puntata da b. Ma la gente si confondeva lo stesso, in compenso tutte quelle quadre mi davano sui nervi perche` non potevo scrivere [b] in un carattere solo e mi si disallineavano le istruzioni. Io ho la paturnia degli allineamenti.
Comunque mi piace il nuovo schema:
- p significa il registro p
- P significa [p], indiretto con base p e spiazzamento zero
- p.1 significa [p+1]
- p.-1 significa [p-1]
- p.1.1 significa [p+1+1] cioe` [p+2]
- eccetera...
> > > 4. se la stringa di input non fosse 4-allineata (e non vedo per quale motivo una stringa di byte dovrebbe esserlo) non solo ti fai una marea di accessi disallineati (che ammazzerebbero, ad esempio, un ARM) ma potrebbe anche causare un segfault alla fine
> >
> > La stringa di input e` per forza allineata a una boundary di 4 byte, ovvero di un'unita` per come la definisce L.in.oleum (per distinguerla dal significato tradizionalmente confuso di "word"). L'allineamento e` dovuto al fatto che L.in.oleum in nessun punto permette accessi disallineati (in effetti andrebbe a nozze con gli ARM). Semplicemente non conosce i byte: i byte sono parti interne delle unita`.
>
> Quindi se uno volesse accedere ad un file mmappato ti ci devi contorcere attorno?
Be', se ci sono sequenze non allineate e vengono lette una volta sola, non ci sarebbe altro modo che contorcersi un po'. Riconosco che e` uno svantaggio, ma del resto indirizzare la memoria in unita` piuttosto che in bytes ha molti altri vantaggi.
> > > 5. non capisco perche' il codice sia scritto in modo da essere non-efficiente e non-leggibile, se fosse leggibile l'accesso sarebbe fatto byte per byte,
> >
> > Non puoi, altrimenti hai i disallineamenti e problemi di endianness di cui sopra. L.in.oleum sacrifica l'accesso byte per byte per evitare questo genere di problemi, che lo renderebbero irrimediabilmente non portabile (se cambiasse la endianness il sorgente sarebbe da buttare). E poi gli accessi disallineati non ammazzano solo gli ARM, ammazzano anche gli Intel superscalari dal Pentium in poi, che ormai sono CISC di nome, ma di fatto funzionano meglio se li si usa in modo molto simile a un RISC.
>
> Con "ammazzano" intendevo che se lo fai ti becchi un SIGBUS, AFAIK in amd64 ottieni un degradamento delle prestazioni e basta. BTW in ARM esistono anche LDRB/LDRH/STRB/STRH.
Poi dici che non t'interessa l'assembly.
> > > se fosse efficiente il loop con gli shift sulla maschera sarebbe parzialmente srotolato (e a naso mi sa che ci sono modi piu` efficienti di manipolare stringhe su x86)
> >
> > Intrinsecamente piu` efficienti, penso di no. Se stai pensando a cazzate come rep scasb stai pensando a roba dei tempi del 386, gia` il 486 avrebbe arrancato meno con cicli estesi. Per lo srotolamento, rendo atto che sarebbe un po' piu` efficiente, ma considera che le librerie di quel gruppo sono ottimizzate piu` per compattezza che per velocita`.
>
> Questo e` il modo in cui viene implemento da gcc:
>
>> 0x000000000040054b <+43>: mov rdx,rsp > 0x000000000040054e <+46>: mov ecx,DWORD PTR [rdx] > 0x0000000000400550 <+48>: add rdx,0x4 > 0x0000000000400554 <+52>: lea eax,[rcx-0x1010101] > 0x000000000040055a <+58>: not ecx > 0x000000000040055c <+60>: and eax,ecx > 0x000000000040055e <+62>: and eax,0x80808080 > 0x0000000000400563 <+67>: je 0x40054e <main+46> > 0x0000000000400565 <+69>: mov ecx,eax > 0x0000000000400567 <+71>: mov esi,0x400734 > 0x000000000040056c <+76>: mov edi,0x1 > 0x0000000000400571 <+81>: shr ecx,0x10 > 0x0000000000400574 <+84>: test eax,0x8080 > 0x0000000000400579 <+89>: cmove eax,ecx > 0x000000000040057c <+92>: lea rcx,[rdx+0x2] > 0x0000000000400580 <+96>: cmove rdx,rcx > 0x0000000000400584 <+100>: add al,al > 0x0000000000400586 <+102>: sbb rdx,0x3 > 0x000000000040058a <+106>: xor eax,eax > 0x000000000040058c <+108>: sub rdx,rbx >
>
> a occhio mi sembra parecchio piu` efficiente.
A occhio non ci ho capito una minchia.
La prima sequenza fino al "je", esclusa la prima istruzione, e` un ciclo che rileva byte posti a zero in un buffer che comincia a rsp (suppongo sia qualcosa di locale sullo stack), poi c'e` qualcos'altro che include delle mov predicate ma che mi sembra incompleto: da nessuna parte si direbbero presenti delle istruzioni di write-back. Legge soltanto? Si puo` avere il sorgente che ha prodotto quel frammento?
> > > 6. per quale motivo i caratteri delle tue stringhe sono di 32bit quando non supporti unicode? Anche se in un futuro dovessi supportare unicode, per quale motivo scegliere l'encoding massimamente inefficiente come default?
> >
> > Perche` i processori sono piu` veloci nel manipolare dati di dimensione pari alla loro word,
>
> I processori sono anche piu` veloci a manipolare cose che stanno nella cache e moltiplicare per 4 la dimensione di tutte le stringhe non aiuta.
Vero. A dirla tutta, per ora il fatto che il compilatore funzioni a passo singolo e non usi salti corti espande anche il codice riducendone la localita`, cosa che mi secca parecchio di piu` dei dati. Certo, sono svantaggi che posso tenere presenti, ma se non voglio inserire istruzioni che accedano ai singoli bytes, non ho alternative. Per il compilatore, prima o poi magari gli faro` fare un passo aggiuntivo per scorciare i salti.
> > perche` essendo che L.in.oleum manipola bytes solo come parti di una word mantenerle in memoria a una unita` per carattere e` infinitamente piu` comodo ed efficiente, e perche` se le volessi codificare scriverei una routine apposita prima di scaricarle da qualche parte.
> >
> > Figurati che se fosse compilato su un processore a 64 bit, ogni carattere prenderebbe 64 bit, una specie di inesistente UCS-8. Ma non e` appunto un fatto di avere piu` code points, e` proprio un fatto di allineamento puro e semplice. Non esistono bytes in L.in.oleum, dai tempi della prima versione, ne` possono esistere.
>
> Mi sembra una follia.
Per come la vedo io, e` l'idealizzare una macchina semplificata che indirizza, legge e scrive unita` discrete di dimensione piu` utile del singolo byte, ECCETTO nel caso di stringhe di testo grandi e di accesso frequente e casuale. Nel qual caso, pazienza: come diceva Ford Prefect, "si fottano le oche, non ci si puo` occupare di ogni dannata cosa".
-
Re: Ci si capisce, vero?Scritto daavvelentaniCubicolarioil 2014-11-01 08:02:55.0 alle 2014-11-01 08:02:55.0Trollate totali: 18184Scritto da: altg
> Comunque mi piace il nuovo schema:
> - p significa il registro p
> - P significa [p], indiretto con base p e spiazzamento zero
> - p.1 significa [p+1]
> - p.-1 significa [p-1]
> - p.1.1 significa [p+1+1] cioe` [p+2]
> - eccetera...
Un capolavoro di inconsistenza.
> > Quindi se uno volesse accedere ad un file mmappato ti ci devi contorcere attorno?
>
> Be', se ci sono sequenze non allineate e vengono lette una volta sola, non ci sarebbe altro modo che contorcersi un po'. Riconosco che e` uno svantaggio, ma del resto indirizzare la memoria in unita` piuttosto che in bytes ha molti altri vantaggi.
usi "allineato" in modo non-standard, una stringa di byte e` allineata a qualunque indirizzo, un in16 e` allineato a qualunque indirizzo divisibile per 2, &c. Tutti questi vantaggi dell'indirizzare la memoria solo a multipli di 4 io non ce li vedo, il fatto che non io non conosca un assembly che ti obbliga a farlo e che il C allinei le strutture come le allinea mi suggerisce che questi supposti vantaggi non esistano.
> > Con "ammazzano" intendevo che se lo fai ti becchi un SIGBUS, AFAIK in amd64 ottieni un degradamento delle prestazioni e basta. BTW in ARM esistono anche LDRB/LDRH/STRB/STRH.
>
> Poi dici che non t'interessa l'assembly.
Le architetture rilevanti saranno si e no una decina, non c'e` bisogno di essere interessati per avere una vaga familiarita`.
> >> > 0x000000000040054b <+43>: mov rdx,rsp > > 0x000000000040054e <+46>: mov ecx,DWORD PTR [rdx] > > 0x0000000000400550 <+48>: add rdx,0x4 > > 0x0000000000400554 <+52>: lea eax,[rcx-0x1010101] > > 0x000000000040055a <+58>: not ecx > > 0x000000000040055c <+60>: and eax,ecx > > 0x000000000040055e <+62>: and eax,0x80808080 > > 0x0000000000400563 <+67>: je 0x40054e <main+46> > > 0x0000000000400565 <+69>: mov ecx,eax > > 0x0000000000400567 <+71>: mov esi,0x400734 > > 0x000000000040056c <+76>: mov edi,0x1 > > 0x0000000000400571 <+81>: shr ecx,0x10 > > 0x0000000000400574 <+84>: test eax,0x8080 > > 0x0000000000400579 <+89>: cmove eax,ecx > > 0x000000000040057c <+92>: lea rcx,[rdx+0x2] > > 0x0000000000400580 <+96>: cmove rdx,rcx > > 0x0000000000400584 <+100>: add al,al > > 0x0000000000400586 <+102>: sbb rdx,0x3 > > 0x000000000040058a <+106>: xor eax,eax > > 0x000000000040058c <+108>: sub rdx,rbx > >
> >
> > a occhio mi sembra parecchio piu` efficiente.
>
> A occhio non ci ho capito una minchia.
>
> La prima sequenza fino al "je", esclusa la prima istruzione, e` un ciclo che rileva byte posti a zero in un buffer che comincia a rsp (suppongo sia qualcosa di locale sullo stack), poi c'e` qualcos'altro che include delle mov predicate ma che mi sembra incompleto: da nessuna parte si direbbero presenti delle istruzioni di write-back. Legge soltanto? Si puo` avere il sorgente che ha prodotto quel frammento?
Certo:#include <stdio.h> #include <string.h> int main(int argc, char *argv[]) { int i; char blah[256]; gets(blah); i = strlen(blah); printf("%d\n", i); return 0; }
Il codice di strlen e` questo: http://www.eglibc.org/cgi-bin/viewvc.cgi/trunk/lib...
Il loop e` una ricerca per il primo int32 contenente un byte a 0.
La seconda parte e` un po' intricata ma con un po' di pazienza si capisce:
- edx e` l'indirizzo del primo int32 dopo il primo int32 contenente un byte a 0 nella stringa
- ebx contiene l'indirizzo della stringa (come anche rsp)
- le istruzioni main+71, main+76 e main+116 sono irrilevanti, servono per configurare printf
- il test a main+84 e le due successive cmove serve a decidere se il primo byte a 0 sta nei primi 2 byte o negli ultimi 2 byte
- l'istruzione main+102 e` dove edx viene aggiustato per puntare esattamente all'ultimo byte
- l'istruzione main+108 e` dove edx diventa la lunghezza della stringa.
>
> Vero. A dirla tutta, per ora il fatto che il compilatore funzioni a passo singolo e non usi salti corti espande anche il codice riducendone la localita`, cosa che mi secca parecchio di piu` dei dati. Certo, sono svantaggi che posso tenere presenti, ma se non voglio inserire istruzioni che accedano ai singoli bytes, non ho alternative. Per il compilatore, prima o poi magari gli faro` fare un passo aggiuntivo per scorciare i salti.
Quindi secondo te il fatto che le istruzioni di jump siano piu` lunghe di qualche byte rispetto a quanto potrebbero essere e` piu` importante del fatto che tutte le stringhe siano 4 volte piu` lunghe di quanto potrebbero essere?
I think happiness is love
- Vladimir Putin-
Re: Ci si capisce, vero?Scritto daaltgutente che non utieneil 2014-11-01 13:06:53.0 alle 2014-11-01 13:06:53.0Trollate totali: 11540> > Comunque mi piace il nuovo schema:
> > - p significa il registro p
> > - P significa [p], indiretto con base p e spiazzamento zero
> > - p.1 significa [p+1]
> > - p.-1 significa [p-1]
> > - p.1.1 significa [p+1+1] cioe` [p+2]
> > - eccetera...
>
> Un capolavoro di inconsistenza.
Perche` la vedi come un'espressione in generale: e` un'indirezione ed e` composta da un registro e un'espressione il cui valore e` lo spiazzamento. In altre parole, non avrebbe senso scrivere:
p/5+1
Il punto serve a separare due cose diverse e secondo me rende piu` chiaro cosa si puo` scrivere dall'una e dall'altra parte, cosi` come la darebbe un registro fuori dalle quadre nella sintassi intel:
edx [1+1]
Comunque potrebbe non essere una cattiva idea quella di ricondurla a un'espressione normale, per poi emettere un errore se l'operatore che segue un registro non e` compatibile con un'indirezione, cioe` permettere p+1 ma lamentarsi per p/5. Che ne dici?
> > > Quindi se uno volesse accedere ad un file mmappato ti ci devi contorcere attorno?
> >
> > Be', se ci sono sequenze non allineate e vengono lette una volta sola, non ci sarebbe altro modo che contorcersi un po'. Riconosco che e` uno svantaggio, ma del resto indirizzare la memoria in unita` piuttosto che in bytes ha molti altri vantaggi.
>
> usi "allineato" in modo non-standard, una stringa di byte e` allineata a qualunque indirizzo, un in16 e` allineato a qualunque indirizzo divisibile per 2, &c.
Parlando di come funziona L.in.oleum, presuppongo che "allineato" significhi a una parola del processore.
> Tutti questi vantaggi dell'indirizzare la memoria solo a multipli di 4 io non ce li vedo, il fatto che non io non conosca un assembly che ti obbliga a farlo e che il C allinei le strutture come le allinea mi suggerisce che questi supposti vantaggi non esistano.
Intanto il codice che hai postato legge 4 bytes (una "unita`") per volta e "si contorce" per estrarre dal valore composto di 4 byte il primo byte a zero? Se come dicevi "dovesse essere leggibile", leggerebbe byte per byte. ARM era stata pensata per avere tutte istruzioni di una word (32 bit) per semplificare la decodifica e il fetching. IA-32 mantiene le istruzioni storiche come lodsb/scasb/stosb solo per retrocompatibilita`, ma non le definirebbe mai efficienti. Il C preferisce essere comodo e non introdurre una scelta radicale come fa L.in.oleum, ma un vettore di dati non allineati a words del processore e` comunque piu` complicato e inefficiente da gestire, e lo obbliga a contorcersi.
> > > Con "ammazzano" intendevo che se lo fai ti becchi un SIGBUS, AFAIK in amd64 ottieni un degradamento delle prestazioni e basta. BTW in ARM esistono anche LDRB/LDRH/STRB/STRH.
> >
> > Poi dici che non t'interessa l'assembly.
>
> Le architetture rilevanti saranno si e no una decina, non c'e` bisogno di essere interessati per avere una vaga familiarita`.
Ti vergogni, sei un timidone!
> > La prima sequenza fino al "je", esclusa la prima istruzione, e` un ciclo che rileva byte posti a zero in un buffer che comincia a rsp (suppongo sia qualcosa di locale sullo stack), poi c'e` qualcos'altro che include delle mov predicate ma che mi sembra incompleto: da nessuna parte si direbbero presenti delle istruzioni di write-back. Legge soltanto? Si puo` avere il sorgente che ha prodotto quel frammento?
>
> Certo:
>
>> #include <stdio.h> > #include <string.h> > > int main(int argc, char *argv[]) { > int i; > char blah[256]; > gets(blah); > i = strlen(blah); > printf("%d\n", i); > return 0; > } >
>
>
Pff... pensavo tu avessi voluto postare un equivalente dell'intera routine di conversione da 8 a 32 bit per carattere. Ok, il ciclo che cercava la lunghezza della stringa l'avevo identificato e immagino fosse a quello che ti riferivi, ma e` l'unica parte in comune col codice L.in.oleum di cui si parlava.
> Il codice di strlen e` questo: http://www.eglibc.org/cgi-bin/viewvc.cgi/trunk/lib...
>
> Il loop e` una ricerca per il primo int32 contenente un byte a 0.
> La seconda parte e` un po' intricata ma con un po' di pazienza si capisce:
> - edx e` l'indirizzo del primo int32 dopo il primo int32 contenente un byte a 0 nella stringa
> - ebx contiene l'indirizzo della stringa (come anche rsp)
> - le istruzioni main+71, main+76 e main+116 sono irrilevanti, servono per configurare printf
> - il test a main+84 e le due successive cmove serve a decidere se il primo byte a 0 sta nei primi 2 byte o negli ultimi 2 byte
> - l'istruzione main+102 e` dove edx viene aggiustato per puntare esattamente all'ultimo byte
> - l'istruzione main+108 e` dove edx diventa la lunghezza della stringa.
Come vedi, si "contorce", legge words di 4 byte intere, e non byte per byte, e in effetti replica letture di 4 byte per volta. Ora posso farti vedere la ricerca della lunghezza di una stringa di 32 bit per carattere in L.in.oleum?00000273 89F2 MOV.rm,r EDX(p), ESI(r) 00000275 833CB700 CMP.rm,i [EDI(w)+4*ESI(r)], 00 00000279 0F840E000000 JE 0000000E ; 0000028D 0000027F 837CB70400 CMP.rm,i [EDI(w)+4*ESI(r)+04], 00 00000284 8D7601 LEA.r,m ESI(r), [ESI(r)+1] 00000287 0F85F2FFFFFF JNE FFFFFFF2 ; 0000027F 0000028D 29D6 SUB.rm,r ESI(r), EDX(p)
Le istruzioni nel sorgente sono:p = r each R r - p
In pratica, copia l'indirizzo della stringa (r) in p.
Poi fa un ciclo "each" vuoto, che va avanti per ogni R non zero.
Infine, sottrae p ad r per trovare la differenza, che e` la lunghezza.
Il ciclo vero e proprio, tolto il caso della stringa vuota, e`:0000027F 837CB70400 CMP.rm,i [EDI(w)+4*ESI(r)+04], 00 00000284 8D7601 LEA.r,m ESI(r), [ESI(r)+1] 00000287 0F85F2FFFFFF JNE FFFFFFF2 ; 0000027F
tre istruzioni in croce. Ok, ci saranno i ritardi di cache 4 volte piu` spesso che se la stringa fosse fatta di bytes, ma immagina come sarebbe piu` facile trattare i caratteri di una stringa in questo modo, manipolarli e trasformarli. A partire dal cercarne la lunghezza senza contorsioni.
> Quindi secondo te il fatto che le istruzioni di jump siano piu` lunghe di qualche byte rispetto a quanto potrebbero essere e` piu` importante del fatto che tutte le stringhe siano 4 volte piu` lunghe di quanto potrebbero essere?
La localita` del codice e` almeno altrettanto importante, ma probabilmente di piu`: quella si applica a tutto il codice, le stringhe di testo a 8 bit sono casi particolari. E` un difetto del compilatore abbozzato attuale, ma mi prometto di risolverlo in seguito.-
Re: Ci si capisce, vero?Scritto daavvelentaniCubicolarioil 2014-11-02 09:16:47.0 alle 2014-11-02 09:16:47.0Trollate totali: 18184Scritto da: altg
> > > Comunque mi piace il nuovo schema:
> > > - p significa il registro p
> > > - P significa [p], indiretto con base p e spiazzamento zero
> > > - p.1 significa [p+1]
> > > - p.-1 significa [p-1]
> > > - p.1.1 significa [p+1+1] cioe` [p+2]
> > > - eccetera...
> >
> > Un capolavoro di inconsistenza.
>
> Perche` la vedi come un'espressione in generale: e` un'indirezione ed e` composta da un registro e un'espressione il cui valore e` lo spiazzamento. In altre parole, non avrebbe senso scrivere:
>
> p/5+1
>
> Il punto serve a separare due cose diverse e secondo me rende piu` chiaro cosa si puo` scrivere dall'una e dall'altra parte, cosi` come la darebbe un registro fuori dalle quadre nella sintassi intel:
>
> edx [1+1]
>
> Comunque potrebbe non essere una cattiva idea quella di ricondurla a un'espressione normale, per poi emettere un errore se l'operatore che segue un registro non e` compatibile con un'indirezione, cioe` permettere p+1 ma lamentarsi per p/5. Che ne dici?
Dico che sarebbe meglio visto che la sintassi intel funziona cosi` da sempre. Ci metterei anche delle parentesi quadre attorno.
>
> > > > Quindi se uno volesse accedere ad un file mmappato ti ci devi contorcere attorno?
> > >
> > > Be', se ci sono sequenze non allineate e vengono lette una volta sola, non ci sarebbe altro modo che contorcersi un po'. Riconosco che e` uno svantaggio, ma del resto indirizzare la memoria in unita` piuttosto che in bytes ha molti altri vantaggi.
> >
> > usi "allineato" in modo non-standard, una stringa di byte e` allineata a qualunque indirizzo, un in16 e` allineato a qualunque indirizzo divisibile per 2, &c.
>
> Parlando di come funziona L.in.oleum, presuppongo che "allineato" significhi a una parola del processore.
Allineato nel mondo normale significa che l'indirizzo e` un multiplo della dimensione.
>
> > Tutti questi vantaggi dell'indirizzare la memoria solo a multipli di 4 io non ce li vedo, il fatto che non io non conosca un assembly che ti obbliga a farlo e che il C allinei le strutture come le allinea mi suggerisce che questi supposti vantaggi non esistano.
>
> Intanto il codice che hai postato legge 4 bytes (una "unita`") per volta e "si contorce" per estrarre dal valore composto di 4 byte il primo byte a zero? Se come dicevi "dovesse essere leggibile", leggerebbe byte per byte.
Il codice che ho postato io non e` fatto per essere leggibile, e` fatto per essere veloce. E non e` solo per via dell'allineamento ma anche perche' e` bit-parallelo. Se dopo aver fatto il tuo bel load allineato ti devi andare a pescare i singoli byte a botte di shr e and e` molto piu` veloce e leggibile fare una lettura non allineata.
> ARM era stata pensata per avere tutte istruzioni di una word (32 bit) per semplificare la decodifica e il fetching.
http://infocenter.arm.com/help/index.jsp?topic=/co...
LDRB e SDRB ci sono sempre stati.
> tre istruzioni in croce. Ok, ci saranno i ritardi di cache 4 volte piu` spesso che se la stringa fosse fatta di bytes,
Hai detto niente!
> > Quindi secondo te il fatto che le istruzioni di jump siano piu` lunghe di qualche byte rispetto a quanto potrebbero essere e` piu` importante del fatto che tutte le stringhe siano 4 volte piu` lunghe di quanto potrebbero essere?
>
> La localita` del codice e` almeno altrettanto importante, ma probabilmente di piu`: quella si applica a tutto il codice, le stringhe di testo a 8 bit sono casi particolari. E` un difetto del compilatore abbozzato attuale, ma mi prometto di risolverlo in seguito.
Secondo te cosa prende piu` spazio? Il codice o i dati?
Secondo me a te piace il fatto che hai un solo tipo di dato perche' semplifica il tuo codice e lo giustifichi con l'efficienza ma e` solo una razionalizzazione a posteriori che scarti tutte le volte che non ti fa comodo per giustificare la tua semplificazione.I think happiness is love
- Vladimir Putin-
Re: Ci si capisce, vero?Scritto daaltgutente che non utieneil 2014-11-02 15:22:57.0 alle 2014-11-02 15:22:57.0Trollate totali: 11540> Dico che sarebbe meglio visto che la sintassi intel funziona cosi` da sempre.
Va be', terro` presente, puo` darsi che cambi idea. La sintassi intel e` ben affermata, lo ammetto, pero` la trovo meno descrittiva di "p.-1" perche` assume che uno spiazzamento possa essere direttamente sottratto all'indirizzo di base, mentre in realta` e` aggiunto come valore negativo in complemento a due.
> Ci metterei anche delle parentesi quadre attorno.
Non mi conviene, le sto usando per definire array inline.
Cioe`:
x = [ 1, 2, 3 ]
carica "x" con l'indirizzo di un array statica contenente le words 1, 2, 3 (e poi zero, perche` per default e` null-terminated). Poi dovrei in qualche modo distinguere i casi.
> > Parlando di come funziona L.in.oleum, presuppongo che "allineato" significhi a una parola del processore.
>
> Allineato nel mondo normale significa che l'indirizzo e` un multiplo della dimensione.
Vabbe', se lo dici te... per me "allineato" senza "a cosa" era un errore di sintassi, al massimo sfruttabile per intendere "a una granularita` di default".
> > > Tutti questi vantaggi dell'indirizzare la memoria solo a multipli di 4 io non ce li vedo, il fatto che non io non conosca un assembly che ti obbliga a farlo e che il C allinei le strutture come le allinea mi suggerisce che questi supposti vantaggi non esistano.
> >
> > Intanto il codice che hai postato legge 4 bytes (una "unita`") per volta e "si contorce" per estrarre dal valore composto di 4 byte il primo byte a zero? Se come dicevi "dovesse essere leggibile", leggerebbe byte per byte.
>
> Il codice che ho postato io non e` fatto per essere leggibile, e` fatto per essere veloce. E non e` solo per via dell'allineamento ma anche perche' e` bit-parallelo.
Bit-che?
Legge 4 byte per volta, come fa la reimplementazione L.in.oleum.
E` parallelo tanto quanto lo e` la sua reimplementazione, qualunque cosa tu intendessi per bit-parallelo.
Non legge i singoli bytes per trovare il terminatore, processa intere words.
> Se dopo aver fatto il tuo bel load allineato ti devi andare a pescare i singoli byte a botte di shr e and e` molto piu` veloce e leggibile fare una lettura non allineata.
Leggibile magari si`, veloce no. In generale, se leggi un registro di 32 bit per operare sui bytes che contiene, fai un accesso parallelo di 4 bytes invece che seriale byte per byte.mov eax, [esi] ; 1 add esi, 4 mov ebx, eax ; 1 mov ecx, eax mov edx, eax ; 1 and eax, 0xFF and ebx, 0xFF00 ; 1 and ecx, 0xFF0000 and edx, 0xFF000000 ; 1 shr ebx, 8 ; 1 shr ecx, 16 ; 1 shr edx, 24 ; 1 ; 8mov al, [esi] ; 2 mov bl, [esi + 1] ; 2 mov cl, [esi + 2] ; 2 mov dl, [esi + 3] ; 2 add esi, 4 ; 1 ; 9
Certo a meno che uno debba leggere un byte solo, ma a quel punto di solito non fai un ciclo.
> > ARM era stata pensata per avere tutte istruzioni di una word (32 bit) per semplificare la decodifica e il fetching.
>
> http://infocenter.arm.com/help/index.jsp?topic=/co...
>
> LDRB e SDRB ci sono sempre stati.
Chissa` se sono penalizzati.
Gli Intel penalizzano gli accessi non allineati alla word del processore.
> > tre istruzioni in croce. Ok, ci saranno i ritardi di cache 4 volte piu` spesso che se la stringa fosse fatta di bytes,
>
> Hai detto niente!
Ma non intendo dire che quando operi su stringhe di caratteri allineati a una word, lo fai perche` la stringa e` colossale. Le converti a stringhe del genere quando devi manipolare frequentemente la stessa stringa, tipo splittarla o concatenarne frammenti. In generale, stai immaginando casi che secondo me sono molto rari, dove la performance dovuta alla specifica capacita` di leggere singoli bytes farebbe la differenza.
> > > Quindi secondo te il fatto che le istruzioni di jump siano piu` lunghe di qualche byte rispetto a quanto potrebbero essere e` piu` importante del fatto che tutte le stringhe siano 4 volte piu` lunghe di quanto potrebbero essere?
> >
> > La localita` del codice e` almeno altrettanto importante, ma probabilmente di piu`: quella si applica a tutto il codice, le stringhe di testo a 8 bit sono casi particolari. E` un difetto del compilatore abbozzato attuale, ma mi prometto di risolverlo in seguito.
>
> Secondo te cosa prende piu` spazio? Il codice o i dati?
E secondo te cosa viene letto piu` spesso, il codice o i dati?
> Secondo me a te piace il fatto che hai un solo tipo di dato perche' semplifica il tuo codice
Non lo semplifica affatto, tant'e` che se devo gestire bytes singoli mi tocca contorcermi. Certo, l'espansione a 32 bit delle stringhe a quel punto lo semplifica, ma probabilmente non ho chiarito bene che si tratta di casi in cui si sa che le stringhe sono relativamente piccole e che vanno manipolate spesso. Una sorta di processo di "importazione" di una stringa a n bit nel "mondo a words" di L.in.oleum.
> e lo giustifichi con l'efficienza ma e` solo una razionalizzazione a posteriori che scarti tutte le volte che non ti fa comodo per giustificare la tua semplificazione.
Senz'altro mi piace l'idea di avere un solo tipo di dato, si`, ma ha dei vantaggi nelle manipolazioni frequenti di stringhe brevi, e d'altra parte secondo me tu stai ingigantendo il caso delle stringhe ASCII/UTF8 di lunghezza rilevante, che sono praticamente l'unico tipo di dato che verrebbe penalizzato dalla loro espansione e che spesso non dovrebbe essere espanso in primo luogo, a meno di processarle in maniera complessa (come in un text editor, ad esempio).
Per il resto, chiarisco che nessuno impedisce di tenerle in bytes e andarci di operazioni binarie su word intere: non mi stupirei se come per strlen di glib, probabilmente anche chi puo` leggere singoli bytes preferisca gestire words intere nei cicli. Ti faccio notare che la strlen che hai postato e` praticamente una smentita dei vantaggi dell'accesso byte per byte: accede word per word per essere efficiente, parallelizzando il trattamento di 4 byte per volta.
-
-
-
Re: Ci si capisce, vero?Scritto daaltgutente che non utieneil 2014-11-01 13:37:09.0 alle 2014-11-01 13:37:09.0Trollate totali: 11540> Il codice di strlen e` questo: http://www.eglibc.org/cgi-bin/viewvc.cgi/trunk/lib...

p.s. comunque la tattica per trovare il terminatore confrontando 4 byte per volta e` carina, non la sapevo e ora la importo in text::FromByteString. Intanto, pero`, volevo farti notare che L.in.oleum, allineando tutto a word del processore, nel fare la stessa cosa per poter sfruttare confronti su 4 byte per volta, puo` saltare questo:/* Handle the first few characters by reading one character at a time. Do this until CHAR_PTR is aligned on a longword boundary. */ for (char_ptr = str; ((unsigned long int) char_ptr & (sizeof (longword) - 1)) != 0; ++char_ptr) if (*char_ptr == '\0') return char_ptr - str;
Sei ancora convinto che tutti questi vantaggi non ci siano?-
Re: Ci si capisce, vero?Scritto daaltgutente che non utieneil 2014-11-01 15:17:58.0 alle 2014-11-01 15:17:58.0Trollate totali: 11540> > Il codice di strlen e` questo: http://www.eglibc.org/cgi-bin/viewvc.cgi/trunk/lib...

>
> p.s. comunque la tattica per trovare il terminatore confrontando 4 byte per volta e` carina, non la sapevo e ora la importo in text::FromByteString. Intanto, pero`, volevo farti notare che L.in.oleum, allineando tutto a word del processore, nel fare la stessa cosa per poter sfruttare confronti su 4 byte per volta, puo` saltare questo:
>
>> /* Handle the first few characters by reading one character at a time. > Do this until CHAR_PTR is aligned on a longword boundary. */ > for (char_ptr = str; ((unsigned long int) char_ptr > & (sizeof (longword) - 1)) != 0; > ++char_ptr) > if (*char_ptr == '\0') > return char_ptr - str; >
>
> Sei ancora convinto che tutti questi vantaggi non ci siano?
Ho reimplementato in L.in.oleum il ciclo word-per-word visto nella strlen di GCC: e` senz'altro un'ottima idea, per quanto renda il codice praticamente incomprensibile (per rendermi conto di cosa vagamente facesse, ieri sera, ci ho messo un quarto d'ora, per poi non capire come il resto dovesse convertire una stringa da 8 a 32 bit per carattere).
Ma vediamo il filmaggine sull'analisi di quanto efficiente sia il codice prodotto dal compilatore C versus quello ottimizzato a mente (seguendo regole di ottimizzazione multiscalare piuttosto generiche) da un opportuno hikikomori...ByteString Length "monaural fn PUSH.r ECX(m) --> m PUSH.r EAX(n) --> n PUSH.r EDX(p) --> p = r MOV.rm,r EDX(p), ESI(r) LOOP ENTRY do MOV.r,rm EAX(n), [EDI(w)+4*ESI(r)] n = R MOV.r,rm ECX(m), [EDI(w)+4*ESI(r)] m = R SUB.ac,i EAX, 01010101 n - 01010101h NOT.rm ECX(m) ! m AND.rm,r EAX(n), ECX(m) n & m ADD.rm,i ESI(r), 01 r + 1 TEST.ac,i EAX, 80808080 continue if n has no 80808080h JZ 00000000 ; 00000277 (TBD) AND.ac,i EAX, 80808080 n & 80808080h LOOP EXIT end do (auto) SUB.rm,i ESI(r), 01 r - 1 SUB.rm,r ESI(r), EDX(p) r - p SHL.rm,i ESI(r), 02 r < log2 bytesPerUnit TEST.ac,i EAX, FF000000 repeat if n has no firstByte JNZ 00000000 ; fwrd ROL.rm,i EAX(n), 08 n [ 8 ADD.rm,i ESI(r), 01 r + 1 TEST.ac,i EAX, FF000000 end repeat if (auto) JZ 00000000 ; 000002AC (TBD) POP.r EDX(p) <-- p POP.r EAX(n) <-- n POP.r ECX(m) <-- m RET.near return --------------------------------------------------------------------------------------------------- MOV.r,rm EAX(n), [EDI(w)+4*ESI(r)] 1 U MOV.r,rm ECX(m), [EDI(w)+4*ESI(r)] 0 V (ovviamente cached) SUB.ac,i EAX, 01010101 1 U NOT.rm ECX(m) 0 V AND.rm,r EAX(n), ECX(m) 1 U ADD.rm,i ESI(r), 01 0 V TEST.ac,i EAX, 80808080 1 U JZ 00000000 ; 00000277 (TBD) 0 V (se predicted) --- 4 cicli/word --------------------------------------------------------------------------------------------------- 0x000000000040054e <+46>: mov ecx,DWORD PTR [rdx] 1 U 0x0000000000400550 <+48>: add rdx,0x4 0 V 0x0000000000400554 <+52>: lea eax,[rcx-0x1010101] 2 U (AGI* su RCX) 0x000000000040055a <+58>: not ecx 0 V 0x000000000040055c <+60>: and eax,ecx 1 U 0x000000000040055e <+62>: and eax,0x80808080 1 V (write after write su EAX) 0x0000000000400563 <+67>: je 0x40054e <main+46> 1 U (la pipe U non ha prediction) --- 6 cicli/word *Address Generation Interlock, stallo della pipeline dovuto all'uso di LEA per fare MOV+SUB
In conclusione, il codice C compilato e` efficiente nella scelta dell'algoritmo, che sicuramente e` piu` veloce che iterare su ogni byte (quello che i commenti di strlen definiscono "tradizionale"), ed e` una bella ottimizzazione fatta A MENTE da chi ha scritto quella versione di strlen. Il compilatore, pero`, a parte un'ottima strength reduction sulle righe successive, nel ciclo si caga abbastanza addosso. Buona serata.-
Re: Ci si capisce, vero?Scritto daNon Autenticatoil 2014-11-01 18:40:17.0 alle 2014-11-01 18:40:17.0> Buona serata.
Meno male che c'è sassofono: magari fra le sue critiche salta anche fuori qualcosa di utile.-
Re: Ci si capisce, vero?Scritto daaltgutente che non utieneil 2014-11-01 20:15:17.0 alle 2014-11-01 20:15:17.0Trollate totali: 11540> > Buona serata.
>
> Meno male che c'è sassofono: magari fra le sue critiche salta anche fuori qualcosa di utile.
Sshhh... e` per quello che posto la roba ogni tanto.
Ma se glielo dici e` abbastanza dispettoso da non cacarmela piu`.
-
Re: Ci si capisce, vero?Scritto daNon Autenticatoil 2014-11-01 20:28:08.0 alle 2014-11-01 20:28:08.0Scritto da: altg
> > > Buona serata.
> >
> > Meno male che c'è sassofono: magari fra le sue critiche salta anche fuori qualcosa di utile.
>
> Sshhh... e` per quello che posto la roba ogni tanto.
> Ma se glielo dici e` abbastanza dispettoso da non cacarmela piu`.
ormai lo sa-
Re: Ci si capisce, vero?Scritto daNon Autenticatoil 2014-11-01 20:50:09.0 alle 2014-11-01 20:50:09.0Scritto da:
> Scritto da: altg
> > > > Buona serata.
> > >
> > > Meno male che c'è sassofono: magari fra le sue critiche salta anche fuori qualcosa di utile.
> >
> > Sshhh... e` per quello che posto la roba ogni tanto.
> > Ma se glielo dici e` abbastanza dispettoso da non cacarmela piu`.
>
> ormai lo sa
Azz, dovevo star zitto.
Comunque mi ammutolisce vedere quante cose sa sassofono.-
Re: Ci si capisce, vero?Scritto daaltgutente che non utieneil 2014-11-01 23:00:14.0 alle 2014-11-01 23:00:14.0Trollate totali: 11540> > > > > Buona serata.
> > > >
> > > > Meno male che c'è sassofono: magari fra le sue critiche salta anche fuori qualcosa di utile.
> > >
> > > Sshhh... e` per quello che posto la roba ogni tanto.
> > > Ma se glielo dici e` abbastanza dispettoso da non cacarmela piu`.
> >
> > ormai lo sa
>
> Azz, dovevo star zitto.
> Comunque mi ammutolisce vedere quante cose sa sassofono.
E` un tipo curioso e molto meticoloso. Mi ha un po' colpito il fatto che trovasse NECESSARIO capire perche`, qualora la famosa istruzione sbagliata fosse stata veramente una combinazione non valida di opcode e operandi, il sistema non avesse intercettato l'eccezione.
Comunque, e` un ganzo.
-
-
-
-
-
-
Re: Ci si capisce, vero?Scritto daavvelentaniCubicolarioil 2014-11-02 09:23:59.0 alle 2014-11-02 09:23:59.0Trollate totali: 18184Scritto da: altg
> > Il codice di strlen e` questo: http://www.eglibc.org/cgi-bin/viewvc.cgi/trunk/lib...
>
> p.s. comunque la tattica per trovare il terminatore confrontando 4 byte per volta e` carina, non la sapevo e ora la importo in text::FromByteString. Intanto, pero`, volevo farti notare che L.in.oleum, allineando tutto a word del processore, nel fare la stessa cosa per poter sfruttare confronti su 4 byte per volta, puo` saltare questo:
>
>> /* Handle the first few characters by reading one character at a time. > Do this until CHAR_PTR is aligned on a longword boundary. */ > for (char_ptr = str; ((unsigned long int) char_ptr > & (sizeof (longword) - 1)) != 0; > ++char_ptr) > if (*char_ptr == '\0') > return char_ptr - str; >
>
> Sei ancora convinto che tutti questi vantaggi non ci siano?
Si`, perche' se devo gestire una stringa che non e` 4-allineata non solo mi devo scrivere l'equivalente di quel codice ma lo devo fare usanto shift e bitmask.I think happiness is love
- Vladimir Putin
-
-
-
-
-
-
Re: Ci si capisce, vero?Scritto daaltgutente che non utieneil 2014-10-31 17:24:21.0 alle 2014-10-31 17:24:21.0Trollate totali: 11540> (tra l'altro chi e` che setta EDI/w?)
Ah, m'ero scordato questa: lo carica il modulo di run-time. EDI sugli Intel e` l'origine dell'area dati dell'applicazione, relativamente alla quale avviene la mappatura degli indirizzi (non solo di dati statici, ma anche di blocchi di heap). In un sorgente, EDI si chiama w (per "workbench"). In ambito multithreaded, EDI e` specifico di un thread: ogni thread ha il suo workbench, e quel che nel sorgente si potrebbe chiamare una variabile o un buffer statico globale, e` in pratica thread-local.
-
-
-
-
Re: Ci si capisce, vero?Scritto da: altg
I sorgenti del parser sono scritti in linoleum? Se sono scritti in un linguaggio umanamente comprensibile ce li puoi mostrare?Young professional woman and busy mom.-
Re: Ci si capisce, vero?Scritto daaltgutente che non utieneil 2014-11-02 16:47:40.0 alle 2014-11-02 16:47:40.0Trollate totali: 11540> I sorgenti del parser sono scritti in linoleum? Se sono scritti in un linguaggio umanamente comprensibile ce li puoi mostrare?
I sorgenti del parser del compilatore di L.in.oleum 4 sono scritti in javascript. Girano nel browser, appoggiandosi per la lettura delle librerie a un miniserver nodeJS (una versione downscaled di JS Mary Lou). Il linker e` un modulo del webserver che risponde a un POST del disassemblato (l'output testuale del compilatore) all'indirizzo "http://localhost:4048/link".
Il compilatore e` un monoblocco javascript di 13500 righe, poi c'e` l'assembler specifico per x86 che ne conta altre 3150 (ovviamente e` switchabile con altri "semi-assemblers"). Li chiamo semi-assemblers perche` sono assemblers incompleti: si limitano ad assemblare il subset di istruzioni e modalita` d'indirizzamento contemplate dalla sintassi L.in.oleum.
In cima a tutto c'e` il front-end, cioe` il javascript che anima l'interfaccia, e che include un piccolo text editor per editare i sorgenti. Per navigare tra le librerie, le righe "include" vengono evidenziate come links che porta alla corrispondente libreria.
Di parser non ce n'e` uno solo: ce n'e` uno principale che isola le linee dei sorgenti, le istruzioni e le espressioni, ma poi c'e` il parser delle espressioni, quello degli operandi, quello dei ranges (inline arrays) e delle stringhe.
Ma a che ti servono i sorgenti del/dei parser? Per curiosita`?
Fra l'altro sono ancora un po' in evoluzione, spuntano spesso degli errorini mentre scrivo le prime librerie: il compilatore e` in rodaggio, insomma...-
Re: Ci si capisce, vero?Scritto da: altg
> Ma a che ti servono i sorgenti del/dei parser? Per curiosita`?
Sto imparando a parsare come fanno i grandi, volevo vedere come facevi tu.
Niente generatore di parser quindi, né grammatiche del linguaggio.Young professional woman and busy mom.-
Re: Ci si capisce, vero?Scritto daaltgutente che non utieneil 2014-11-02 17:01:58.0 alle 2014-11-02 17:01:58.0Trollate totali: 11540> > Ma a che ti servono i sorgenti del/dei parser? Per curiosita`?

>
> Sto imparando a parsare come fanno i grandi, volevo vedere come facevi tu.
Um... io sono un tipo atipico, come ben puo` confermarti il Prof. Avvelentani. Uno che pensa parecchio lateralmente, quasi di sbieco, solo un po' piu` giu` a babordo.
> Niente generatore di parser quindi, né grammatiche del linguaggio.
No, mai provato generatori di parsers. Non saprei quanto sarebbe comodo un generatore di parsers, puo` darsi che sarebbe comodo, oppure che per fargli fare quello che vuoi tu debba pregarlo in cinese tradizionale. Boh. Comunque io mi trovo bene a scriverli per conto mio. Quello di Lino4 guarda carattere per carattere in ordine piu` o meno LTR, ma ogni tanto fa una puntatina ahead per distinguere qualche caso, tipo quelli di "-" e "-->", nel senso che si chiede "che viene dopo il trattino?".
ps. ah ecco, ho ricontrollato, e` essenzialmente un LALR(2), Look-Ahead Left-to-Right con 2 tokens "presi piu` avanti". Ma non lo scrivo seguendo qualche modello ideale, lo scrivo partendo da un'idea di comodita`, e poi ce lo modello intorno. Per esempio e` +2 perche` appunto trovo convenienti i simboli "-->" e "<--" per push e pop in/da stack, perche` sono molto visibili e questo dovrebbe aiutare a evitare errori, visto che sbagliare a manipolare lo stack a basso livello e` catastrofico.
**Modificato dall'autore il 02.11.2014 17:13**-
Re: Ci si capisce, vero?Scritto daNon Autenticatoil 2014-11-02 17:04:33.0 alle 2014-11-02 17:04:33.0> Uno che pensa parecchio lateralmente, quasi di sbieco,
-
Re: Ci si capisce, vero?Scritto da: altg
> > > Ma a che ti servono i sorgenti del/dei parser? Per curiosita`?
> >
> > Sto imparando a parsare come fanno i grandi, volevo vedere come facevi tu.
>
> Um... io sono un tipo atipico, come ben puo` confermarti il Prof. Avvelentani. Uno che pensa parecchio lateralmente, quasi di sbieco, solo un po' piu` giu` a babordo.
Non è un approccio per forza di cose sbagliato, ci sono molti che preferiscono il tuo approccio per questione di flessibilità.
> > Niente generatore di parser quindi, né grammatiche del linguaggio.
>
> No, mai provato generatori di parsers. Non saprei quanto sarebbe comodo un generatore di parsers, puo` darsi che sarebbe comodo, oppure che per fargli fare quello che vuoi tu debba pregarlo in cinese tradizionale. Boh. Comunque io mi trovo bene a scriverli per conto mio. Quello di Lino4 guarda carattere per carattere in ordine piu` o meno LTR, ma ogni tanto fa una puntatina ahead per distinguere qualche caso, tipo quelli di "-" e "-->", nel senso che si chiede "che viene dopo il trattino?".
Sì, ti tocca litigare un po' per fargli fare quello che vuoi. Un vantaggio è la portabilità, metti che un domani vuoi cambiare l'implementazione in un altro linguaggio/piattaforma, sarà molto più facile visto che la grammatica è quella. L'altro vantaggio è che l'approccio formale evita alcuni tipi di bug nell'implementazione (qualcuno ha detto parser di php?).Young professional woman and busy mom.-
Re: Ci si capisce, vero?Scritto daaltgutente che non utieneil 2014-11-02 17:20:32.0 alle 2014-11-02 17:20:32.0Trollate totali: 11540> > > > Ma a che ti servono i sorgenti del/dei parser? Per curiosita`?

> > >
> > > Sto imparando a parsare come fanno i grandi, volevo vedere come facevi tu.
> >
> > Um... io sono un tipo atipico, come ben puo` confermarti il Prof. Avvelentani. Uno che pensa parecchio lateralmente, quasi di sbieco, solo un po' piu` giu` a babordo.
>
> Non è un approccio per forza di cose sbagliato, ci sono molti che preferiscono il tuo approccio per questione di flessibilità.
>
> > > Niente generatore di parser quindi, né grammatiche del linguaggio.
> >
> > No, mai provato generatori di parsers. Non saprei quanto sarebbe comodo un generatore di parsers, puo` darsi che sarebbe comodo, oppure che per fargli fare quello che vuoi tu debba pregarlo in cinese tradizionale. Boh. Comunque io mi trovo bene a scriverli per conto mio. Quello di Lino4 guarda carattere per carattere in ordine piu` o meno LTR, ma ogni tanto fa una puntatina ahead per distinguere qualche caso, tipo quelli di "-" e "-->", nel senso che si chiede "che viene dopo il trattino?".
>
> Sì, ti tocca litigare un po' per fargli fare quello che vuoi. Un vantaggio è la portabilità, metti che un domani vuoi cambiare l'implementazione in un altro linguaggio/piattaforma, sarà molto più facile visto che la grammatica è quella. L'altro vantaggio è che l'approccio formale evita alcuni tipi di bug nell'implementazione (qualcuno ha detto parser di php?).
Boh, c'erano dei bug nel parser di php?
Vabbe' tanto non me ne sono accorto.
Qui i bug piu` che nel parser li trovo nel semi-assembler: e` difficile testarne tutte le combinazioni di opcode e operandi, e ogni tanto ne salta fuori una che fa ka-boom.
-
-
-
-
-
-