From: Bernhard Urban Date: Fri, 5 Mar 2010 21:27:22 +0000 (+0100) Subject: asmb: asmb verhaelt sich nun exakt wie asmb_ref X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=6ba4e2bae67a4c3948d52bba8f3a66b74d555adb;hp=7628166391caf88dc595a4810b535e3e1cacc7b6;p=uebersetzerbau-ss10.git asmb: asmb verhaelt sich nun exakt wie asmb_ref d.h. die daten nach dem nullbyte bleiben erhalten. TODO: wirklich noetig? (war aber lustig... ^^) --- diff --git a/asmb/asmb.s b/asmb/asmb.s index 9d08b64..e94d189 100644 --- a/asmb/asmb.s +++ b/asmb/asmb.s @@ -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 diff --git a/asmb/asmbtest.c b/asmb/asmbtest.c index ed928c5..bea72ba 100644 --- a/asmb/asmbtest.c +++ b/asmb/asmbtest.c @@ -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) 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; }