|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Senior Member
Iscritto dal: Sep 2005
Città: Torino
Messaggi: 606
|
[JAVA] reverse string un pò particolare
Volevo postare questo pezzo di codice che fa il reverse di una stringa tramite xor:
Codice:
public static String reverse(String toReverse) { char[] array = toReverse.toCharArray(); int len = str.length() - 1; for (int i = 0; i < len; i++, len--) { array[i] ^= array[len]; array[len] ^= array[i]; array[i] ^= array[len]; } return new String(array); } ![]()
__________________
"Se proprio dovete piratare un prodotto, preferiamo che sia il nostro piuttosto che quello di qualcun altro." [Jeff Raikes] "Pirating software? Choose Microsoft!" |
![]() |
![]() |
![]() |
#2 | |
Bannato
Iscritto dal: Mar 2008
Città: Villabate(PA)
Messaggi: 2515
|
Quote:
Codice:
int x = 5; int y = 8; x ^= y; y ^= x; x ^= y; Ultima modifica di Vincenzo1968 : 21-10-2008 alle 23:37. |
|
![]() |
![]() |
![]() |
#3 | |
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
E' piu' lenta della versione classica con variabile d'appoggio. Era utile (ogni tanto) una volta, in assembly, in carenza di registri. Ma oggi non e' consigliabile.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
|
![]() |
![]() |
![]() |
#4 | |
Bannato
Iscritto dal: Mar 2008
Città: Villabate(PA)
Messaggi: 2515
|
Quote:
![]() Codice:
#include <stdio.h> #include <time.h> int main() { clock_t c_start, c_end; int k; int tmp; int x = 5; int y = 8; c_start = clock(); for ( k = 0; k < 100000001; k++ ) { x ^= y; y ^= x; x ^= y; } c_end = clock(); printf("\nx -> %d\ny -> %d\n", x, y); printf("\nTempo 1 -> %5.5f secondi\n", (double)(c_end - c_start) / CLOCKS_PER_SEC); c_start = clock(); for ( k = 0; k < 100000001; k++ ) { tmp = x; x = y; y = tmp; } c_end = clock(); printf("\nx -> %d\ny -> %d\n", x, y); printf("\nTempo 2 -> %5.5f secondi\n", (double)(c_end - c_start) / CLOCKS_PER_SEC); return 0; } |
|
![]() |
![]() |
![]() |
#5 |
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Se puoi stampa il codice assembly di entrambe le soluzioni, e commentiamo.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
![]() |
![]() |
![]() |
#6 | |
Moderatore
Iscritto dal: Nov 2003
Messaggi: 16211
|
Quote:
Codice:
x ^= y ^= x ^= y; ![]() Ovviamente, funziona solo se x e y sono variabili intere: int, char, long...
__________________
Ubuntu è un'antica parola africana che significa "non so configurare Debian" ![]() Scienza e tecnica: Matematica - Fisica - Chimica - Informatica - Software scientifico - Consulti medici REGOLAMENTO DarthMaul = Asus FX505 Ryzen 7 3700U 8GB GeForce GTX 1650 Win10 + Ubuntu Ultima modifica di Ziosilvio : 22-10-2008 alle 09:57. |
|
![]() |
![]() |
![]() |
#7 | |
Member
Iscritto dal: Mar 2007
Messaggi: 298
|
Quote:
Se devi muovere solo qualche byte, vanno bene entrambi i modi, ma se le operazioni vanno fatte su quantità massicce di dati, allora meglio scegliere l'operazione più veloce, a parità di cose. |
|
![]() |
![]() |
![]() |
#8 |
Bannato
Iscritto dal: Mar 2008
Città: Villabate(PA)
Messaggi: 2515
|
Eqque qua:
![]() Codice:
#include <stdio.h> #include <time.h> int main() { clock_t c_start, c_end; int k; int tmp; int x = 5; int y = 8; c_start = clock(); for ( k = 0; k < 1000000001; k++ ) { x ^= y ^= x ^= y; } c_end = clock(); printf("\nx -> %d\ny -> %d\n", x, y); printf("\nTempo 0 -> %5.5f secondi\n", (double)(c_end - c_start) / CLOCKS_PER_SEC); c_start = clock(); for ( k = 0; k < 1000000001; k++ ) { x ^= y; y ^= x; x ^= y; } c_end = clock(); printf("\nx -> %d\ny -> %d\n", x, y); printf("\nTempo 1 -> %5.5f secondi\n", (double)(c_end - c_start) / CLOCKS_PER_SEC); c_start = clock(); for ( k = 0; k < 1000000001; k++ ) { tmp = x; x = y; y = tmp; } c_end = clock(); printf("\nx -> %d\ny -> %d\n", x, y); printf("\nTempo 2 -> %5.5f secondi\n", (double)(c_end - c_start) / CLOCKS_PER_SEC); return 0; } Codice:
; Listing generated by Microsoft (R) Optimizing Compiler Version 15.00.21022.08 TITLE c:\Progetti Visual Studio\Progetti visual Studio 2008\C++\MyProjects\HtmlIt\ArrayTree\ArrayTree\ArrayTree.c .686P .XMM include listing.inc .model flat INCLUDELIB OLDNAMES PUBLIC ??_C@_03NHELKHFK@?$CFd?7?$AA@ ; `string' PUBLIC ??_C@_00CNPNBAHC@?$AA@ ; `string' PUBLIC ??_C@_0BC@BJMPBCEC@?6x?5?9?$DO?5?$CFd?6y?5?9?$DO?5?$CFd?6?$AA@ ; `string' PUBLIC ??_C@_0BL@IABJBOLO@?6Tempo?50?5?9?$DO?5?$CF5?45f?5secondi?6?$AA@ ; `string' PUBLIC ??_C@_0BL@OFHOCFPI@?6Tempo?51?5?9?$DO?5?$CF5?45f?5secondi?6?$AA@ ; `string' PUBLIC ??_C@_0BL@EKNHGIDC@?6Tempo?52?5?9?$DO?5?$CF5?45f?5secondi?6?$AA@ ; `string' EXTRN @__security_check_cookie@4:PROC EXTRN __imp__puts:PROC EXTRN __imp__printf:PROC EXTRN __imp__clock:PROC ; COMDAT ??_C@_0BL@EKNHGIDC@?6Tempo?52?5?9?$DO?5?$CF5?45f?5secondi?6?$AA@ CONST SEGMENT ??_C@_0BL@EKNHGIDC@?6Tempo?52?5?9?$DO?5?$CF5?45f?5secondi?6?$AA@ DB 0aH, 'T' DB 'empo 2 -> %5.5f secondi', 0aH, 00H ; `string' CONST ENDS ; COMDAT ??_C@_0BL@OFHOCFPI@?6Tempo?51?5?9?$DO?5?$CF5?45f?5secondi?6?$AA@ CONST SEGMENT ??_C@_0BL@OFHOCFPI@?6Tempo?51?5?9?$DO?5?$CF5?45f?5secondi?6?$AA@ DB 0aH, 'T' DB 'empo 1 -> %5.5f secondi', 0aH, 00H ; `string' CONST ENDS ; COMDAT ??_C@_0BL@IABJBOLO@?6Tempo?50?5?9?$DO?5?$CF5?45f?5secondi?6?$AA@ CONST SEGMENT ??_C@_0BL@IABJBOLO@?6Tempo?50?5?9?$DO?5?$CF5?45f?5secondi?6?$AA@ DB 0aH, 'T' DB 'empo 0 -> %5.5f secondi', 0aH, 00H ; `string' CONST ENDS ; COMDAT ??_C@_0BC@BJMPBCEC@?6x?5?9?$DO?5?$CFd?6y?5?9?$DO?5?$CFd?6?$AA@ CONST SEGMENT ??_C@_0BC@BJMPBCEC@?6x?5?9?$DO?5?$CFd?6y?5?9?$DO?5?$CFd?6?$AA@ DB 0aH, 'x' DB ' -> %d', 0aH, 'y -> %d', 0aH, 00H ; `string' CONST ENDS ; COMDAT ??_C@_00CNPNBAHC@?$AA@ CONST SEGMENT ??_C@_00CNPNBAHC@?$AA@ DB 00H ; `string' CONST ENDS ; COMDAT ??_C@_03NHELKHFK@?$CFd?7?$AA@ CONST SEGMENT ??_C@_03NHELKHFK@?$CFd?7?$AA@ DB '%d', 09H, 00H ; `string' CONST ENDS PUBLIC __real@408f400000000000 PUBLIC _main EXTRN __fltused:DWORD ; COMDAT __real@408f400000000000 ; File c:\progetti visual studio\progetti visual studio 2008\c++\myprojects\htmlit\arraytree\arraytree\arraytree.c CONST SEGMENT __real@408f400000000000 DQ 0408f400000000000r ; 1000 ; Function compile flags: /Ogtpy CONST ENDS ; COMDAT _main _TEXT SEGMENT tv203 = -4 ; size = 4 tv197 = -4 ; size = 4 tv190 = -4 ; size = 4 _c_start$ = -4 ; size = 4 _main PROC ; COMDAT ; 38 : { push ebp mov ebp, esp and esp, -64 ; ffffffc0H sub esp, 48 ; 00000030H push ebx ; 39 : clock_t c_start, c_end; ; 40 : int k; ; 41 : int tmp; ; 42 : ; 43 : int x = 5; ; 44 : int y = 8; ; 45 : ; 46 : ; 47 : c_start = clock(); mov ebx, DWORD PTR __imp__clock push ebp push esi push edi mov esi, 5 lea edi, DWORD PTR [esi+3] call ebx mov DWORD PTR _c_start$[esp+64], eax mov eax, 1000000001 ; 3b9aca01H $LL9@main: ; 48 : for ( k = 0; k < 1000000001; k++ ) ; 49 : { ; 50 : x ^= y ^= x ^= y; xor esi, edi xor edi, esi xor esi, edi sub eax, 1 jne SHORT $LL9@main ; 51 : } ; 52 : c_end = clock(); call ebx ; 53 : ; 54 : printf("\nx -> %d\ny -> %d\n", x, y); mov ebx, DWORD PTR __imp__printf push edi push esi push OFFSET ??_C@_0BC@BJMPBCEC@?6x?5?9?$DO?5?$CFd?6y?5?9?$DO?5?$CFd?6?$AA@ mov ebp, eax call ebx ; 55 : ; 56 : printf("\nTempo 0 -> %5.5f secondi\n", (double)(c_end - c_start) / CLOCKS_PER_SEC); sub ebp, DWORD PTR _c_start$[esp+76] add esp, 4 mov DWORD PTR tv203[esp+72], ebp fild DWORD PTR tv203[esp+72] fdiv QWORD PTR __real@408f400000000000 fstp QWORD PTR [esp] push OFFSET ??_C@_0BL@IABJBOLO@?6Tempo?50?5?9?$DO?5?$CF5?45f?5secondi?6?$AA@ call ebx ; 57 : ; 58 : ; 59 : c_start = clock(); mov ebp, DWORD PTR __imp__clock add esp, 12 ; 0000000cH call ebp mov DWORD PTR _c_start$[esp+64], eax mov eax, 1000000001 ; 3b9aca01H $LL6@main: ; 60 : for ( k = 0; k < 1000000001; k++ ) ; 61 : { ; 62 : x ^= y; xor esi, edi ; 63 : y ^= x; xor edi, esi ; 64 : x ^= y; xor esi, edi sub eax, 1 jne SHORT $LL6@main ; 65 : } ; 66 : c_end = clock(); call ebp ; 67 : ; 68 : printf("\nx -> %d\ny -> %d\n", x, y); push edi push esi push OFFSET ??_C@_0BC@BJMPBCEC@?6x?5?9?$DO?5?$CFd?6y?5?9?$DO?5?$CFd?6?$AA@ mov ebp, eax call ebx ; 69 : ; 70 : printf("\nTempo 1 -> %5.5f secondi\n", (double)(c_end - c_start) / CLOCKS_PER_SEC); sub ebp, DWORD PTR _c_start$[esp+76] add esp, 4 mov DWORD PTR tv197[esp+72], ebp fild DWORD PTR tv197[esp+72] fdiv QWORD PTR __real@408f400000000000 fstp QWORD PTR [esp] push OFFSET ??_C@_0BL@OFHOCFPI@?6Tempo?51?5?9?$DO?5?$CF5?45f?5secondi?6?$AA@ call ebx add esp, 12 ; 0000000cH ; 71 : ; 72 : c_start = clock(); call DWORD PTR __imp__clock mov DWORD PTR _c_start$[esp+64], eax mov eax, 1000000001 ; 3b9aca01H $LL3@main: ; 73 : for ( k = 0; k < 1000000001; k++ ) sub eax, 1 ; 74 : { ; 75 : tmp = x; mov ebp, esi ; 76 : x = y; mov esi, edi ; 77 : y = tmp; mov edi, ebp jne SHORT $LL3@main ; 78 : } ; 79 : c_end = clock(); call DWORD PTR __imp__clock ; 80 : ; 81 : printf("\nx -> %d\ny -> %d\n", x, y); push ebp push esi push OFFSET ??_C@_0BC@BJMPBCEC@?6x?5?9?$DO?5?$CFd?6y?5?9?$DO?5?$CFd?6?$AA@ mov edi, eax call ebx ; 82 : ; 83 : printf("\nTempo 2 -> %5.5f secondi\n", (double)(c_end - c_start) / CLOCKS_PER_SEC); sub edi, DWORD PTR _c_start$[esp+76] add esp, 4 mov DWORD PTR tv190[esp+72], edi fild DWORD PTR tv190[esp+72] fdiv QWORD PTR __real@408f400000000000 fstp QWORD PTR [esp] push OFFSET ??_C@_0BL@EKNHGIDC@?6Tempo?52?5?9?$DO?5?$CF5?45f?5secondi?6?$AA@ call ebx add esp, 12 ; 0000000cH ; 84 : ; 85 : return 0; ; 86 : } pop edi xor eax, eax pop esi pop ebp pop ebx mov esp, ebp pop ebp ret 0 _main ENDP _TEXT ENDS END Domanda: un buon libro per imparare l'assembly? P.S. Questa è la mia macchina: Codice:
AMD Athlon(tm) 64 X2 Dual Core Processor 4800+ 2.50 GHz 896 MB di RAM Microsoft Windows XP Professional (32 bit) Service Pack 3 Ultima modifica di Vincenzo1968 : 22-10-2008 alle 14:36. |
![]() |
![]() |
![]() |
#9 | |
Senior Member
Iscritto dal: Jul 2005
Città: Bologna
Messaggi: 1130
|
Quote:
Che ne dici di... Codice:
new StringBuilder(toReverse).reverse().toString()
__________________
-> The Motherfucking Manifesto For Programming, Motherfuckers |
|
![]() |
![]() |
![]() |
#10 |
Member
Iscritto dal: Mar 2007
Messaggi: 298
|
Ah, l'assembler... saranno 10-15 anni che non lo uso... un po' ostico, ma che sensazione di benessere quando assemblavi il programma e vedevi un eseguibile di 1-2Kb...
Come linguaggio è facilissimo (almeno io lo trovo facile, c'è chi direbbe il contrario), ma richiede una buona conoscenza dell'architettura che c'è dietro. Ci sono diverse intro in giro per internet, uno può essere questo, che ha il vantaggio di essere in italiano. Ma dal mio punto di vista il punto di riferimento resta l'Intel Software Developer's Manual per le piattaforme ia32 ed ia64, non so se anche AMD abbia documentazione sul proprio set di istruzioni, ma suppongo di si. Ma non è esattamente introduttivo... Purtroppo, di questi tempi l'assembler è quasi un hobby, difficilmente si trova spazio per utilizzarlo su progetti "reali", eccetto se ti occupi di elettronica o programmazione di basso livello. |
![]() |
![]() |
![]() |
#11 | |
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
Codice:
string ToPrint = "PippoPlutoPaperino"; StreamWriter output = new StreamWriter("output.txt"); output.Write(ToPrint); output.Write(ToPrint.Reverse()); output.Close();
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
|
![]() |
![]() |
![]() |
#12 | |
Bannato
Iscritto dal: Mar 2008
Città: Villabate(PA)
Messaggi: 2515
|
Quote:
grazie per la risposta e per il link. Non voglio imparare l'assembly per realizzare applicazioni complesse ma vorrei, almeno, capire il codice generato dal compilatore. ![]() |
|
![]() |
![]() |
![]() |
#13 | |
Bannato
Iscritto dal: Mar 2008
Città: Villabate(PA)
Messaggi: 2515
|
Quote:
a proposito di imparare l'assembly, un commento sul codice che ho postato? Ultima modifica di Vincenzo1968 : 22-10-2008 alle 17:09. |
|
![]() |
![]() |
![]() |
#14 | |
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
Si', purtroppo e' troppo ottimizzato, nel senso che il C ha pensato bene di tenere le variabili su registri. Normalmente quando si scambiano i valori delle due variabili si fa qualcosa, e quindi non possono essere tenute su registri, ma occorre passare in memoria. Invece qui non si e' fatto nulla, il C l'ha capito ed ha tagliato. L'effetto del rallentare e' solo dovuto al fatto che le XOR si accoppiano meno bene che le MOV (e comunque un po' si vede) Se all'interno del ciclo (in entrambi i casi), provi a chiamare una funzione che usa X e Y, allora forse riusciamo a vedere meglio il problema. non so, una funzione che sperabilmente non possa essere messa come __inline automaticamente, quindi decorosamente complessa. Oppure puoi provare a chiedere indirettamente al C di non considerare le variabili come ottimizzabili in registri. Se non sbaglio c'e' anche in C la keyword volatile [code] volatile int x=5; volatile int y=8; [code] Purtroppo non ho un compilatore C sottomano per provare io direttamente.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
|
![]() |
![]() |
![]() |
#15 | ||
Bannato
Iscritto dal: Mar 2008
Città: Villabate(PA)
Messaggi: 2515
|
Quote:
![]() Quote:
![]() ![]() |
||
![]() |
![]() |
![]() |
#16 | ||
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
Comunque prova anche solo a dichiarare le due variaibli con il volatile davanti (che non e' l'uccello padulo) Quote:
E comunque era a casa e non al lavoro come adesso ![]() (Poi in realta' ce l'avrei anche qui, ma sai...)
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
||
![]() |
![]() |
![]() |
#17 | |
Bannato
Iscritto dal: Mar 2008
Città: Villabate(PA)
Messaggi: 2515
|
Quote:
![]() |
|
![]() |
![]() |
![]() |
#18 | |
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
Ora ci provo quindi.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
|
![]() |
![]() |
![]() |
#19 |
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Codice:
int x; int y; int u; int v; int main(array<System::String ^> ^args) { x = 5; y = 8; /// XOR x ^= y; y ^= x; x ^= y; printf("%d %d",x,y); u = 5; v = 8; // TMP int tmp = u; u = v; v = tmp; printf("%d %d",u,v); return 0; } Codice:
x = 5; mov dword ptr ds:[0040A16Ch],5 y = 8; mov dword ptr ds:[0040A168h],8 /// XOR x ^= y; mov eax,dword ptr ds:[0040A168h] xor dword ptr ds:[0040A16Ch],eax y ^= x; mov eax,dword ptr ds:[0040A16Ch] xor dword ptr ds:[0040A168h],eax x ^= y; mov eax,dword ptr ds:[0040A168h] xor dword ptr ds:[0040A16Ch],eax printf("%d %d",x,y); push 40311Ch push dword ptr ds:[0040A16Ch] push dword ptr ds:[0040A168h] push 1C6B68h call FF9E43C8 add esp,10h nop nop u = 5; mov dword ptr ds:[0040A164h],5 v = 8; mov dword ptr ds:[0040A160h],8 // TMP int tmp = u; mov eax,dword ptr ds:[0040A164h] mov edi,eax u = v; mov eax,dword ptr ds:[0040A160h] mov dword ptr ds:[0040A164h],eax v = tmp; mov dword ptr ds:[0040A160h],edi printf("%d %d",u,v); push 403124h push dword ptr ds:[0040A164h] push dword ptr ds:[0040A160h] push 1C6B68h call FF9E43C8 add esp,10h nop nop esso equivale a: Lettura da memoria: - Una lettura da memoria, con salvataggio del dato dentro il registro EAX XOR in memoria. Se avessimo voglia di andare a vedere il microcodice di quest'ultimo XOR: - una ulteriore lettura da memoria con salvataggio su un registro interno 1 - uno XOR tra EAX (quello che avevamo letto nella prima istruzione) e il registro interno 1, con salvataggio del risultato in un altro registro interno 2 - una scrittura dal registro interno 2 alla stessa cella di memoria Tralasciando l'operazione vera e propria, abbiamo in totale 2 letture e 1 scrittura su memoria per ciascuno dei 3 XOR del codice C Per un totale di 6 letture e 3 scritture per gestire lo scambio di variabile Mentre invece le operazioni con variabile d'appoggio abbiamo un totale di 2 letture da memoria e 2 scritture su memoria. C'e' una bella differenza.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
![]() |
![]() |
![]() |
#20 |
Bannato
Iscritto dal: Mar 2008
Città: Villabate(PA)
Messaggi: 2515
|
|
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 03:34.