* ist mit 'groesser' vertauscht und vice versa */
pcmpgtb %xmm11, %xmm15
+.differenz:
//Y = min(X, 'a' - 'A')
pminub %xmm9, %xmm15
//retuniere an die richtige speicheradresse
movapd %xmm12, (%rdi, %rdx, 8)
- //ist ein byte groesser als 0? dann steht 0xff drin
+ //entspricht ein byte dem nullbyte dann steht an jener stelle 0xff sonst 0x00
pcmpeqb %xmm14, %xmm12
//hol die MSBs aller bytes raus
pmovmskb %xmm12, %ecx
//ist %ecx gleich null? dann die naechsten 16byte bitte
jecxz .nextround
+ //speicheradresse des parameters zurueckgeben (wird noch modifziert)
mov %rdi, %rax
+
+ /*===============
+ * ab hier uebler hax um nach \0 trotzdem die gleichen bytes wie
+ * input zu haben, also um selbiges verhalten wie asmb_ref zu erzwingen */
+
+ //\0 byte stelle durch rausfinden des MSB des %ecx
+ bsf %ecx, %r11d
+
+ //das ergebnis zweimal abspeichern
+ mov %r11d, %ecx
+
+ //hint: in %xmm15 ist differenz gespeichert (vgl .differenz)
+
+ //leider shiften nur mit immediate! :(
+ cmp $8, %r11d
+ jc .rechtsshift1
+ psrldq $8, %xmm15
+ sub $8, %r11d
+
+.rechtsshift1:
+ cmp $4, %r11d
+ jc .rechtsshift2
+ psrldq $4, %xmm15
+ sub $4, %r11d
+
+.rechtsshift2:
+ cmp $2, %r11d
+ jc .rechtsshift3
+ psrldq $2, %xmm15
+ sub $2, %r11d
+
+.rechtsshift3:
+ cmp $1, %r11d
+ jc .linksshift
+ psrldq $1, %xmm15
+ sub $1, %r11d
+#==================
+.linksshift:
+ cmp $8, %ecx
+ jc .linksshift1
+ pslldq $8, %xmm15
+ sub $8, %ecx
+
+.linksshift1:
+ cmp $4, %ecx
+ jc .linksshift2
+ pslldq $4, %xmm15
+ sub $4, %ecx
+
+.linksshift2:
+ cmp $2, %ecx
+ jc .linksshift3
+ pslldq $2, %xmm15
+ sub $2, %ecx
+
+.linksshift3:
+ cmp $1, %ecx
+ jc .endshift
+ pslldq $1, %xmm15
+ sub $1, %ecx
+
+.endshift:
+ //betreffende speicherstelle in %xmm11 laden
+ movdqu -16(%rax, %rdx, 8), %xmm11
+ //und overhead wieder subtrahieren
+ psubb %xmm15, %xmm11
+
+ //ergebnis zurueckspielen und fertig \o/
+ movapd %xmm11, -16(%rax, %rdx, 8)
+
ret
.LFE2:
.size asmb, .-asmb
return s;
}
-#define NUM_TESTCASES 13
+static char ascii(char s) {
+ if(s < 0x20) return '.';
+ if(s > 0x7E) return '.';
+ return s;
+}
+
+static void hexdump(void *d, int len) {
+ unsigned char *data;
+ int i, off;
+ data = (unsigned char*)d;
+ for (off=0; off<len; off += 16) {
+ printf("\t%08x ",off);
+ for(i=0; i<16; i++)
+ if((i+off)>=len) printf(" ");
+ else printf("%02x ",data[off+i]);
+
+ printf(" ");
+ for(i=0; i<16; i++)
+ if((i+off)>=len) printf(" ");
+ else printf("%c",ascii(data[off+i]));
+ printf("\n");
+ }
+}
+
+#define NUM_TESTCASES 17
int main()
{
- char *input[NUM_TESTCASES]={"asdfABCDEFGHKL54",
+ char *input[NUM_TESTCASES]={
+ "AAaaB\0BBUUUUZZZZ",
+ "AAaaBBB\0",
+ "AaA\0ABBB",
+ "A\0ABCDEF",
"foofuuMUHkk",
"AbC",
"BLA|MUHMKUH|KA",
"AbC\0AAAAAAAAAAAA",
"BLA|MUHMKUH|KAA\0",
"ASDFASDFasdfasdfaBC\0AAAABBBBCCCC",
- "ASDFASDFasdfasdfaBC0AAAABBBBCCCCmuhKA\0asASDFasdf" ,
- "ASas\0ASas"
+ "ASDFASDFasdfasdfaBC0AAAABBBBCCCCmuhKA\0asASDFasdf",
+ "ASas\0ASas",
+ "asdfABCDEFGHKL54",
};
- int len[NUM_TESTCASES] = {16,
+ int len[NUM_TESTCASES] = {
+ 16,
+ 8,
+ 8,
+ 8,
11,
3,
14,
16,
32,
48,
- 9
+ 9,
+ 16
};
char *output_our, *output_ref;
char *input_our, *input_ref;
+ int right=0, wrong=0, neither=0, i;
- int i,j;
for(i = 0; i < NUM_TESTCASES; i++) {
input_our = (char *) malloc (len[i]);
input_ref = (char *) malloc (len[i]);
output_ref = (char *) asmb_ref((unsigned char *) input_ref);
if(memcmp(output_our,output_ref, len[i]) != 0) {
- if(strncmp(output_our, output_ref, len[i]) == 0)
+ if(strncmp(output_our, output_ref, len[i]) == 0) {
+ neither++;
printf("Testfall%02i nach Nullbyte ungleich\n", i);
- else
- printf("Testfall%02i falsch!\n", i);
-
- printf("Input(\"%s\"):\n\t", input[i]);
- for(j = 0; j <= len[i]; j++) {
- printf("%02X ", input[i][j]);
}
- printf("\nerwartet:\n\t");
- for(j = 0; j <= len[i]; j++) {
- printf("%02X ", output_ref[j]);
- }
- printf("\ntatsaechliches Ergebnis:\n\t");
- for(j = 0; j <= len[i]; j++) {
- printf("%02X ", output_our[j]);
+ else {
+ wrong++;
+ printf("Testfall%02i falsch!\n", i);
}
+
+ printf("Input(\"%s\"):\n", input[i]);
+ hexdump(input[i], len[i]);
+
+ printf("\nerwartet:\n");
+ hexdump(output_ref, len[i]);
+
+ printf("\ntatsaechliches Ergebnis:\n");
+ hexdump(output_our, len[i]);
printf("\n");
}
else {
+ right++;
printf("Testfall%02i korrekt\n", i);
}
free(input_our);
free(input_ref);
}
+ printf("========\n%2i Testfaelle sind korrekt\n%2i Testfaelle sind nach dem Nullbyte ungleich\n"
+ "%2i Testfaelle sind falsch\n", right, neither, wrong);
return 0;
}