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 rcx
est é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 0x20
est 0 pour identique ou 0x20 pour différer. a ^= mask; b ^= mask
caseflip 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.lst
pour 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' loop
instruction lente est également 2 octets, identique à un court jcc
. scasb
reste le meilleur moyen d’incrémenter rdi
avec 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 loop
cas (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++i
avec 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?