code machine x86-64, 14 octets
Appelable à partir de C (convention d'appel SysV x86-64) avec ce prototype:
void casexchg(char *rdi, char *rsi); // modify both strings in place
Une version de longueur explicite dont la longueur rcxest égale à la même taille. void casexchg(char *rdi, char *rsi, int dummy, size_t len);
Cela utilise le même algorithme d'échange de bits que les réponses C et Java: si les deux lettres sont identiques, aucune des deux ne doit être modifiée. S'ils sont dans le cas contraire, ils doivent tous les deux changer.
Utilisez XOR pour différencier le bit de casse des deux chaînes. mask = (a XOR b) AND 0x20est 0 pour identique ou 0x20 pour différer. a ^= mask; b ^= maskcaseflip les deux lettres ssi elles étaient des cas opposés. (Parce que les codes de lettres ASCII pour les lettres supérieure et inférieure ne diffèrent que par le bit 5.)
Liste NASM (de nasm -felf64 -l/dev/stdout). Utilisez-le cut -b 26- <casexchg.lst >casexchg.lstpour transformer cela en quelque chose que vous pouvez assembler.
addr machine
6 code global casexchg
7 bytes casexchg:
8 .loop:
9 00000000 AC lodsb ; al=[rsi] ; rsi++
10 00000001 3207 xor al, [rdi]
11 00000003 2420 and al, 0x20 ; 0 if their cases were the same: no flipping needed
12
13 00000005 3007 xor [rdi], al ; caseflip both iff their cases were opposite
14 00000007 3046FF xor [rsi-1], al
15
16 0000000A AE scasb ; cmp al,[rdi] / inc rdi
17 ; AL=0 or 0x20.
18 ; At the terminating 0 in both strings, AL will be 0 so JNE will fall through.
19 ; 0x20 is ASCII space, which isn't allowed, so AL=0x20 won't cause early exit
20 0000000B 75F3 jne .loop
21 ; loop .loop ; caller passes explict length in RCX
22
23 0000000D C3 ret
size = 0xe bytes = 14
24 0000000E 0E db $ - casexchg_bitdiff
L' loopinstruction lente est également 2 octets, identique à un court jcc. scasbreste le meilleur moyen d’incrémenter rdiavec une instruction à un octet. Je suppose que nous pourrions xor al, [rdi]/ stosb. Ce serait la même taille mais probablement plus rapide pour le loopcas (la mémoire src + store est moins chère que la mémoire dst + reload). Et définirait toujours ZF de manière appropriée pour le cas de longueur implicite!
Essayez-le en ligne! avec un _start qui l'appelle sur argv [1], argv [2] et utilise sys_write sur le résultat
array[i++%n]+=...;?array[t=i++%n]=array[t]+...;fonctionne bien; etarray[i%n]+=...;i++;fonctionne bien aussi, mais utiliseri++ou++iavec un modulo et+=ajouter une ligne à un tableau ne fonctionne pas. Voici un exemple de Java 10 TIO pour voir le problème. S'agit-il d'un bogue (ou d'une fonctionnalité: S) dans le JDK Java 10 ou dans le compilateur Java 10 TIO?