asmb: asmb verhaelt sich nun exakt wie asmb_ref
authorBernhard Urban <lewurm@gmail.com>
Fri, 5 Mar 2010 21:27:22 +0000 (22:27 +0100)
committerBernhard Urban <lewurm@gmail.com>
Sat, 6 Mar 2010 00:48:13 +0000 (01:48 +0100)
d.h. die daten nach dem nullbyte bleiben erhalten.
TODO: wirklich noetig? (war aber lustig... ^^)

asmb/asmb.s
asmb/asmbtest.c

index 9d08b641bb6b0a49638c4c92aa7e7d542719a90a..e94d189c7f0b9bf56cbe620177e8b9760d984400 100644 (file)
@@ -46,6 +46,7 @@ asmb:
        * ist mit 'groesser' vertauscht und vice versa */
        pcmpgtb %xmm11, %xmm15
 
+.differenz:
        //Y = min(X, 'a' - 'A')
        pminub %xmm9, %xmm15
 
@@ -55,7 +56,7 @@ asmb:
        //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
@@ -64,7 +65,78 @@ asmb:
        //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
index ed928c5fb8750a6d2ab97adb73c66bd66c2f3b82..bea72ba703a03c8ba70ee44607bc426bf08f929f 100644 (file)
@@ -15,10 +15,38 @@ unsigned char *asmb_ref(unsigned char *s)
        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", 
@@ -29,10 +57,15 @@ int main()
                "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,
@@ -44,12 +77,13 @@ int main()
                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]);
@@ -61,31 +95,34 @@ int main()
                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;
 }