x86-64 machine code, 14 bytes
Callable from C (x86-64 SysV calling convention) with this prototype:
void casexchg(char *rdi, char *rsi); // modify both strings in place
An explicit-length version with length in
rcx is the same size.
void casexchg(char *rdi, char *rsi, int dummy, size_t len);
This uses the same bit-exchange algo as the C and Java answers: If both letters are the same case, neither needs to change. If they're opposite case, they both need to change.
Use XOR to diff the case bit of the two strings.
mask = (a XOR b) AND 0x20 is 0 for same or 0x20 for differing.
a ^= mask; b ^= mask caseflip both letters iff they were opposite case. (Because the ASCII letter codes for upper and lower differ only in bit 5.)
NASM listing (from
nasm -felf64 -l/dev/stdout). Use
cut -b 26- <casexchg.lst >casexchg.lst to turn this back into something you can assemble.
6 code global casexchg
7 bytes casexchg:
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
13 00000005 3007 xor [rdi], al ; caseflip both iff their cases were opposite
14 00000007 3046FF xor [rsi-1], al
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
23 0000000D C3 ret
size = 0xe bytes = 14
24 0000000E 0E db $ - casexchg_bitdiff
loop instruction is also 2 bytes, same as a short
scasb is still the best way to increment
rdi with a one-byte instruction. I guess we could
xor al, [rdi] /
stosb. That would be the same size but probably faster for the
loop case (memory src + store is cheaper than memory dst + reload). And would still set ZF appropriately for the implicit-length case!
Try it online! with a _start that calls it on argv, argv and uses sys_write on the result