Created
October 8, 2020 18:01
-
-
Save clausecker/e9906b5621887481e9b8bc25a6872a61 to your computer and use it in GitHub Desktop.
Caesar cipher in x86 ASM with MMX
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# MMX caeasar chiffre implementation | |
# for i686 with MMX | |
# signature: | |
# caesar(out, in, len, key) | |
# key is between 0 and 25 | |
.section .text | |
.globl caesar | |
.type caesar,@function | |
.align 16 | |
caesar: | |
push %ebp | |
mov %esp,%ebp | |
push %ebx | |
push %edi | |
push %esi | |
mov 8(%ebp),%edi # edi: destination | |
mov 12(%ebp),%esi # esi: source | |
mov 16(%ebp),%edx # edx: length | |
and $~7,%edx # only process full qwords | |
jz 1f | |
xor %ecx,%ecx # ecx: index | |
movd 20(%ebp),%mm5 | |
punpcklbw %mm5,%mm5 | |
punpcklwd %mm5,%mm5 | |
punpckldq %mm5,%mm5 # mm5: key bytes | |
movq Amask,%mm7 # for later use | |
movq %mm5,%mm4 | |
psubb twentysix,%mm4 # mm4: key - 26 | |
movq %mm7,%mm6 | |
psubb %mm4,%mm6 # mm6: 'A' - 1 - (key - 26) | |
.align 16 | |
0: movq (%esi,%ecx),%mm0 | |
movq %mm0,%mm1 | |
pand ucmask,%mm1 # mm1: xmm0 in upper case | |
movq %mm1,%mm3 | |
movq %mm1,%mm2 | |
pcmpgtb %mm7,%mm2 # mm2: 0xff where 'A' <= buf[i] | |
pcmpgtb Zmask,%mm3 # mm3: 0xff where 'Z' < buf[i] | |
pcmpgtb %mm6,%mm1 # mm1: 0xff where 'A' + key <= buf[i] | |
pandn %mm1,%mm3 | |
pand %mm4,%mm3 # mm3: key-26 where 'A' + (26 - key) <= buf[i] <= 'Z' | |
pandn %mm2,%mm1 | |
pand %mm5,%mm1 # mm1: key where 'A' <= buf[i] < 'A' + (26 - key) | |
por %mm3,%mm1 # mm1: 0/key/key-26 | |
paddb %mm1,%mm0 | |
movq %mm0,(%edi,%ecx) | |
add $8,%ecx | |
cmp %edx,%ecx | |
jb 0b | |
emms | |
add %ecx,%edi | |
add %ecx,%esi | |
1: mov 16(%ebp),%edx # length | |
mov 20(%ebp),%ecx # key | |
and $7,%edx # loop tail | |
jz 1f # all bytes processed alread? | |
# process remaining bytes | |
add %edx,%edi # end of output buffer | |
add %edx,%esi # end of input buffer | |
neg %edx # index counts up to 0 | |
lea -26(%ecx),%ebx # bl: key - 26 | |
mov $'A'-1,%ah | |
sub %bl,%ah # ah: threshold ('A' - 1 - (key - 26)) | |
.align 16 | |
0: mov (%esi,%edx),%al | |
and $~0x20,%al # al: uppercase c | |
cmp $'Z'+1,%al # cf: uc <= 'Z' | |
sbb %ch,%ch # ch: 0xff if uc <= 'Z' | |
cmp %al,%ah # cf: thresh < uc | |
sbb %bh,%bh # bh: 0xff if thresh < uc | |
and %bh,%ch | |
and %al,%ch # ch: key - 26 & isleZ & isgttthres | |
not %bh # bh: ~isgtthresh | |
cmp $'A',%al | |
cmc # cf: 'A' <= uc | |
sbb %al,%al # al: 0xff if 'A' <= uc | |
and %bh,%al | |
and %cl,%al # al: key & isgeA & ~isgtthresh | |
or %ch,%al | |
add (%esi,%edx),%al | |
mov %al,(%edi,%edx) | |
inc %edx | |
jnz 0b | |
1: pop %esi | |
pop %edi | |
pop %ebx | |
leave | |
ret | |
.size caesar,.-caesar | |
.section .rodata.cst8,"aM",@progbits,8 | |
.align 8 | |
.type ucmask,@object | |
ucmask: .fill 8, 1, ~0x20 | |
.size ucmask, 8 | |
.type Amask,@object | |
Amask: .fill 8, 1, 'A' - 1 | |
.size Amask, 8 | |
.type Zmask,@object | |
Zmask: .fill 8, 1, 'Z' | |
.size Zmask, 8 | |
.type twentysix,@object | |
twentysix: | |
.fill 8, 1, 26 | |
.size twentysix, 8 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define _POSIX_C_SOURCE 200809L | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
extern void caesar(const char *out, char *in, size_t len, int key); | |
extern int | |
main(int argc, char *argv[]) | |
{ | |
char *buf = NULL; | |
size_t len = 0; | |
ssize_t count; | |
int key = 13; | |
if (argc > 1) | |
key = atoi(argv[1]) % 26; | |
while (count = getline(&buf, &len, stdin), count != EOF) { | |
caesar(buf, buf, strlen(buf), key); | |
fputs(buf, stdout); | |
} | |
return (EXIT_SUCCESS); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment