asmb: passt soweit. optimierungen fehlen noch
authorBernhard Urban <lewurm@gmail.com>
Tue, 2 Mar 2010 16:24:04 +0000 (17:24 +0100)
committerBernhard Urban <lewurm@gmail.com>
Tue, 2 Mar 2010 16:39:01 +0000 (17:39 +0100)
.gitignore
asmb/Makefile [new file with mode: 0755]
asmb/asmb.s [new file with mode: 0644]
asmb/main.c [new file with mode: 0644]

index 8f4fb4c4391a7942f3d81f16bd913493044069a8..a15a6a26d88c99e04160beabb5f5c7aff45d8a87 100644 (file)
@@ -8,5 +8,6 @@ oxout.*
 asma/asma
 
 #asmb
+asmb/asmb
 
 #weitere eintragen...
diff --git a/asmb/Makefile b/asmb/Makefile
new file mode 100755 (executable)
index 0000000..a4218dd
--- /dev/null
@@ -0,0 +1,20 @@
+NAME := asmb
+all: $(NAME).o
+
+$(NAME).o: $(NAME).s
+       @echo "  COMPILE  $<"
+       @gcc -c -o $(NAME).o $(NAME).s
+
+.PHONY: clean
+clean:
+       rm -f $(NAME).o $(NAME)
+
+1test: all
+       @echo "  COMPILE  $<"
+       @gcc -pedantic -ansi -Wall -g -o $(NAME) $(NAME).s main.c -D_GNU_SOURCE
+       @echo "execute ./$(NAME)"
+       @./$(NAME)
+
+2test:
+       /usr/ftp/pub/ublu/test/$(NAME)/test
+
diff --git a/asmb/asmb.s b/asmb/asmb.s
new file mode 100644 (file)
index 0000000..6a3afe2
--- /dev/null
@@ -0,0 +1,98 @@
+       .file   "asmb.c"
+       .text
+.globl asmb
+       .type   asmb, @function
+asmb:
+.LFB2:
+       xor %rdx, %rdx
+       xor %ecx, %ecx
+
+       //soll einfach null sein
+       pxor %xmm14, %xmm14
+
+.nextround:
+       /*init %xmm8 mit "'Z' + 1 + min_t - 'A'" fuer jedes byte
+       * 'Z' + 1 + min_t - 'A' = 90 + 1 - 128 - 65 = -102
+       * 102 = 01100110
+       * ~102 = 10011001
+       * (~102)+1 = 10011010 = 0x9A */
+       mov $0x9a9a9a9a9a9a9a9a, %rax
+       movq %rax, %xmm15
+       movddup %xmm15, %xmm8
+
+       //init %xmm9 mit "'a'-'A'= 97-65 = 32 = 0x20
+       mov $0x2020202020202020, %rax
+       movq %rax, %xmm15
+       movddup %xmm15, %xmm9
+
+       //speicheradresse des pointers zeigt auf 16*8 feld = 128bit
+       movdqu (%rdi, %rdx, 8), %xmm11
+       movdqu (%rdi, %rdx, 8), %xmm12
+
+       /*addiere in %xmm11 "min_t-'A'"
+       * = -128 - 65 = 63 = 0x3f */
+       mov $0x3f3f3f3f3f3f3f3f, %rax
+       movq %rax, %xmm15
+       movddup %xmm15, %xmm10
+
+       //c+min_t-'A'
+       paddb %xmm10, %xmm11
+
+       /*"Packed COMpare Greater Than (Byte)"
+       * X = 'Z' + 1 + min_t - 'A' > c + min_t - 'A' ? 0xff : 0
+       * achtung beim intuitiven lesen des befehles. 'kleiner' 
+       * ist mit 'groesser' vertauscht und vice versa */
+       pcmpgtb %xmm11, %xmm8
+
+       //Y = min(X, 'a' - 'A')
+       pminub %xmm9, %xmm8
+
+       //c += Y
+       paddb %xmm8, %xmm12
+
+       //retuniere an die richtige speicheradresse
+       movapd %xmm12, (%rdi, %rdx, 8)
+
+       //ist ein byte groesser als 0? dann steht 0xff drin
+       pcmpeqb %xmm14, %xmm12
+       //hol die MSBs aller bytes raus
+       pmovmskb %xmm12, %ecx
+       inc %rdx
+       inc %rdx
+       //ist %ecx gleich null? dann die naechsten 16byte bitte
+       jecxz .nextround
+
+       mov %rdi, %rax
+       ret
+.LFE2:
+       .size   asmb, .-asmb
+       .section        .eh_frame,"a",@progbits
+.Lframe1:
+       .long   .LECIE1-.LSCIE1
+.LSCIE1:
+       .long   0x0
+       .byte   0x1
+       .string "zR"
+       .uleb128 0x1
+       .sleb128 -8
+       .byte   0x10
+       .uleb128 0x1
+       .byte   0x3
+       .byte   0xc
+       .uleb128 0x7
+       .uleb128 0x8
+       .byte   0x90
+       .uleb128 0x1
+       .align 8
+.LECIE1:
+.LSFDE1:
+       .long   .LEFDE1-.LASFDE1
+.LASFDE1:
+       .long   .LASFDE1-.Lframe1
+       .long   .LFB2
+       .long   .LFE2-.LFB2
+       .uleb128 0x0
+       .align 8
+.LEFDE1:
+       .ident  "GCC: (Debian 4.3.2-1.1) 4.3.2"
+       .section        .note.GNU-stack,"",@progbits
diff --git a/asmb/main.c b/asmb/main.c
new file mode 100644 (file)
index 0000000..b63e8df
--- /dev/null
@@ -0,0 +1,66 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+extern unsigned char *asmb(unsigned char *s);
+
+unsigned char *asmb_ref(unsigned char *s)
+{
+       unsigned long i;
+       for (i=0; s[i]; i++) {
+               unsigned char c = s[i];
+               c += (c >= 'A' && c <= 'Z') ? 'a'-'A' : 0;
+               s[i] = c;
+       }
+       return s;
+}
+
+int main(int argc, char **argv) {
+       char *input1[]={"asdfA\0BCDEFGHKL5", "foofuuMUHkk\0AAAA", 
+                                       "AbC\0AAAAAAAAAAAA", "BLA|MUHMKUH|KAA\0", 
+                                       "ASDFASDFasdfasdfaBC\0AAAABBBBCCCC",
+                                       "ASDFASDFasdfasdfaBC0AAAABBBBCCCCmuhKA\0asASDFasdf"
+                                       /*      8      16  20  24  28  32  36   40      48 */
+                                       };
+       int len[] = {16,16,
+                               16,16,
+                               32,
+                               48};
+       char *output1;
+       char *output2;
+       char *input2;
+       char *input3;
+       int i, j;
+
+       for(i = 0; i < 6; i++) {
+               input2 = strdup(input1[i]);
+               input3 = strdup(input1[i]);
+               output1 = (char *)asmb_ref((unsigned char *)(input2));
+               output2 = (char *)asmb((unsigned char *)(input3));
+
+               printf("\n");
+#if 0
+               if(memcmp(output1,output2, len[i])) {
+#else
+               if(strncmp(output1,output2, len[i])) {
+#endif
+                       j = 0;
+                       printf("Testfall falsch; Input war: \"%s\"\n", input1[i]);
+                       printf("erwartet:\n\t\"%s\"\ntatsaechliches Ergebnis:\n\t\"%s\"\n", output1, output2);
+#if 0
+                       printf("0x");
+                       for(j = 0; j < 16; j++)
+                               printf("%02X", output2[j]);
+                       printf("\n");
+#endif
+               } else {
+                       printf("Testfall \"%s\" passt.\n", output1);
+               }
+
+               free(input2);
+               free(input3);
+       }
+
+       return 0;
+}
+