машинный код x86-64, 14 байт
Вызывается из C (соглашение о вызовах SysV x86-64) с этим прототипом:
void casexchg(char *rdi, char *rsi); // modify both strings in place
Версия с явной длиной с длиной в rcx
имеет тот же размер. void casexchg(char *rdi, char *rsi, int dummy, size_t len);
При этом используется тот же алгоритм обмена битами, что и в ответах C и Java: если обе буквы имеют одинаковый регистр, их не нужно менять. Если они противоположны, они оба должны измениться.
Используйте XOR, чтобы отличить бит регистра двух строк. mask = (a XOR b) AND 0x20
0 для одинаковых или 0x20 для разных. a ^= mask; b ^= mask
caseflip обе буквы, если они противоположны (Потому что буквенные коды ASCII для верхнего и нижнего отличаются только в бите 5.)
Листинг NASM (с nasm -felf64 -l/dev/stdout
). Используйте, cut -b 26- <casexchg.lst >casexchg.lst
чтобы превратить это в то, что вы можете собрать.
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
Медленная loop
инструкция также 2 байта, так же, как короткая jcc
. scasb
все еще лучший способ увеличить rdi
с помощью однобайтовой инструкции. Я думаю , мы могли бы xor al, [rdi]
/ stosb
. Это будет тот же размер, но, вероятно, быстрее для loop
случая (память src + store дешевле, чем память dst + reload). И все равно установил бы ZF соответственно для случая неявной длины!
Попробуйте онлайн! с _start, который вызывает его на argv [1], argv [2] и использует sys_write для результата
array[i++%n]+=...;
?array[t=i++%n]=array[t]+...;
работает отлично; иarray[i%n]+=...;i++;
прекрасно работает, но использованиеi++
или++i
с модулем и+=
добавление к строке в массиве не работает .. Вот Java 10 TIO в качестве примера, чтобы увидеть проблему. Это ошибка (или особенность: S) в Java 10 JDK или в компиляторе Java 10 TIO?