asma: formel "umgeformt" und im endeffekt einen befehl "gewonnen" (haha)
authorBernhard Urban <lewurm@gmail.com>
Tue, 9 Mar 2010 18:21:45 +0000 (19:21 +0100)
committerBernhard Urban <lewurm@gmail.com>
Tue, 9 Mar 2010 21:09:11 +0000 (22:09 +0100)
ausserdem hab ich die testumgebung vom ertl eingebaut und ein wenig erweitert

asma/Makefile
asma/asma.s
asma/asma_ref.s [deleted file]
asma/callingconvention.c [new file with mode: 0644]
asma/main.c

index 6ce51e4f3b8e4d128e2014bd1724b953af6134b6..d2f9841064f21ce0afc7ed1b1dfcdb928d538d52 100755 (executable)
@@ -10,8 +10,10 @@ clean:
        rm -f $(NAME).o $(NAME)
 
 1test: all
+       @echo "  COMPILE  callingconvention.c"
+       @gcc -c -fomit-frame-pointer -fno-defer-pop callingconvention.c
        @echo "  COMPILE  $<"
-       @gcc -pedantic -ansi -Wall -g -o $(NAME) $(NAME).s main.c -D_GNU_SOURCE
+       @gcc -Wall -g -o $(NAME) $(NAME).s main.c callingconvention.o -D_GNU_SOURCE
        @echo "execute ./$(NAME)"
        @./$(NAME)
 
index d1202ced60a193c1466f7ae3035f0d99abff2a5a..9ea72d32ba5a7e8e62c46648c08337ada17bd5be 100644 (file)
@@ -2,17 +2,17 @@
 
 .section .rodata
 .align 128
-const9a:
+const65:
        .rept 16
-       .byte 0x9a
+       .byte 0x65
        .endr
 const20:
        .rept 16
        .byte 0x20
        .endr
-const3f:
+constc0:
        .rept 16
-       .byte 0x3f
+       .byte 0xc0
        .endr
 
        .text
@@ -20,37 +20,41 @@ const3f:
        .type   asma, @function
 asma:
 .LFB2:
-       /*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 */
-       movdqa const9a, %xmm8
+       // folgendes kann umgeformt werden:
+       // (mathematisch ned ganz korrekt)
+       // X = 'Z' + 1 + min_t - 'A' > c + min_t - 'A' ? 0xff : 0
+       // X = -102         >  c + 63 ? 0xff : 0
+       // X = c + 63       < -102 ? 0xff : 0
+       // X = -(c + 63)    >  102 ? 0xff : 0
+       // X = -63 - c      >  102 ? 0xff : 0
+       // X = -63 - c - 1  >  102 - 1 ? 0xff : 0
+       // X = -64 - c      >  101 ? 0xff : 0
+       // ...
+       // 101 = 0x65
+       // -64 = 0xc0
 
-       //speicheradresse des pointers zeigt auf 16*8 feld = 128bit
+       // speicheradresse des pointers zeigt auf 16*8 feld = 128bit
        movdqu (%rdi), %xmm11
 
-       /*addiere in %xmm11 "min_t-'A'"
-       * = -128 - 65 = 63 = 0x3f
-       * c+min_t-'A' */
-       paddb const3f, %xmm11
+       // -64 - c
+       movdqa constc0, %xmm9
+       psubb %xmm11, %xmm9
 
-       /*"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
+       // "Packed COMpare Greater Than (Byte)"
+       // achtung beim intuitiven lesen des befehles. 'kleiner'
+       // ist mit 'groesser' vertauscht und vice versa
+       pcmpgtb const65, %xmm9
 
-       /*Y = min(X, 'a' - 'A')
-       * mit "'a'-'A'= 97-65 = 32 = 0x20 */
-       pminub const20, %xmm8
+       /Y = min(X, 'a' - 'A')
+       // mit 'a'-'A'= 97-65 = 32 = 0x20
+       pminub const20, %xmm9
 
-       //retuniere an die richtige speicheradresse
+       // c += Y
+       paddb %xmm9, %xmm11
+
+       // retuniere an die richtige speicheradresse
        mov %rdi, %rax
-       //c += Y
-       psubb const3f, %xmm11
-       paddb %xmm11, %xmm8
-       movdqu %xmm8, (%rax)
+       movdqu %xmm11, (%rax)
 
        ret
 .LFE2:
diff --git a/asma/asma_ref.s b/asma/asma_ref.s
deleted file mode 100644 (file)
index 1480455..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-       .file   "asma_ref.c"
-       .text
-.globl asma_ref
-       .type   asma_ref, @function
-asma_ref:
-.LFB2:
-       movl    $0, %ecx
-.L4:
-       movzbl  (%rdi,%rcx), %edx
-       leal    -65(%rdx), %eax
-       cmpb    $26, %al
-       sbbl    %eax, %eax
-       andl    $32, %eax
-       addl    %edx, %eax
-       movb    %al, (%rdi,%rcx)
-       addq    $1, %rcx
-       cmpq    $16, %rcx
-       jne     .L4
-       movq    %rdi, %rax
-       ret
-.LFE2:
-       .size   asma_ref, .-asma_ref
-       .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/asma/callingconvention.c b/asma/callingconvention.c
new file mode 100644 (file)
index 0000000..5ed4e52
--- /dev/null
@@ -0,0 +1,33 @@
+/* gcc -c -fomit-frame-pointer -fno-defer-pop callingconvention.c */
+
+#include <stdlib.h>
+
+extern unsigned char *asma(unsigned char *s);
+
+/* geprueft werden callee gesicherte Register: rbx,r12-r15, 
+ * rsp (stackptr), rbp (frameptr) */
+
+#define CHECKNUM 0x1234567812345678
+unsigned char *asma_callchecking(unsigned char *s)
+{
+  register long x0 asm("%rbx")=CHECKNUM+0;
+  register long x1 asm("%r12")=CHECKNUM+1;
+  register long x2 asm("%r13")=CHECKNUM+2;
+  register long x3 asm("%r14")=CHECKNUM+3;
+  register long x4 asm("%r15")=CHECKNUM+4;
+  register long x5 asm("%rbp")=CHECKNUM+5;
+  static void* origsp;
+  void*newsp;
+  unsigned char *res;
+  asm("movq %%rsp,%0":"=g"(origsp):);
+  res=asma(s);
+  if(x0!=CHECKNUM+0) exit(11);
+  if(x1!=CHECKNUM+1) exit(12);
+  if(x2!=CHECKNUM+2) exit(13);
+  if(x3!=CHECKNUM+3) exit(14);
+  if(x4!=CHECKNUM+4) exit(15);
+  if(x5!=CHECKNUM+5) exit(16);
+  asm("movq %%rsp,%0":"=g"(newsp):);
+  if(origsp!=newsp) exit(30);
+  return res;
+}
index a228147f4133c39147f5a69341ab6fa84e6bce5f..4d5211528404c2d1f5b31330e52fa4bf1ad0b6ef 100644 (file)
@@ -1,33 +1,60 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <mcheck.h>
 
 extern unsigned char *asma(unsigned char *s);
+extern unsigned char *asma_callchecking(unsigned char *s);
 
-unsigned char *asma_ref(unsigned char *s)
+unsigned char *orig_asma(unsigned char *s)
 {
        int i;
        for (i=0; i<16; i++) {
-               unsigned char c = s[i];
-               c += (c >= 'A' && c <= 'Z') ? 'a'-'A' : 0;
+               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[]={"asdfABCDEFGHKL54", "foofuuMUHkk", "AbC", "BLA|MUHMKUH|KA"};
+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");
+       }
+}
+
+int main2(void)
+{
+       char *input1[]={"asdfABCDEFGHKL54", "foofuuMUHkk", "AbC", "BLA|MUHMKUH|KA", "XZY"};
        char *output1;
        char *output2;
        char *input2;
        char *input3;
        int i, j;
-       int off[] = {2,0,0,0};
+       int off[] = {2,0,0,0,0};
 
-       for(i = 0; i < 4; i++) {
+       for(i = 0; i < 5; i++) {
                input2 = strdup(input1[i]);
                input3 = strdup(input1[i]);
-               output1 = (char *)asma_ref((unsigned char *)(input2 + off[i]));
+               output1 = (char *)orig_asma((unsigned char *)(input2 + off[i]));
                output2 = (char *)asma((unsigned char *)(input3 + off[i]));
 
                output1[16]='\0';
@@ -38,12 +65,6 @@ int main(int argc, char **argv) {
                        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);
                }
@@ -55,3 +76,122 @@ int main(int argc, char **argv) {
        return 0;
 }
 
+void printchar(unsigned char c)
+{
+       if (c<' ' || c>126 || c=='"')
+               printf("\\x%02x",c);
+       else
+               putchar(c);
+}
+
+void printarray(unsigned char* bufstart, int buflength, unsigned char* s)
+{
+       int i;
+       unsigned char *p=s-16;
+       unsigned long pl;
+       unsigned long l=16;
+       if (p<bufstart)
+               p=bufstart;
+       pl=s+l+16-p;
+       if (p+pl>bufstart+buflength)
+               pl=bufstart+buflength-p;
+       printf("%p=",p);
+       for(i=0; ;i++) {
+               if (p+i==s+l)
+                       printf("\"");
+               if (!(i<pl))
+                       break;
+               if(p+i==s)
+                       printf("\"");
+               printchar(p[i]);
+       }
+       printf("\n");
+}
+
+int test(unsigned char* s,unsigned char* t, unsigned char* u,
+               unsigned long sa,unsigned long ta, unsigned long ua)
+{
+       unsigned long l=16;
+       unsigned char utmp[l+16];
+       unsigned char stmp[l+16];
+       unsigned char *r, *orig_r;
+
+       // init
+       int i;
+       int off = sa + ta + ua * 8;
+       for (i=0; i<l+16; i++) {
+               s[i] = i * 14 + off;
+       }
+
+       // check
+       memcpy(stmp, s, l+16);
+       memset(u, 0xff, l);
+       memset(utmp, 0xff, l);
+
+       printf("\nCalling asma(%p) with\n", s+sa);
+       printarray(s+sa, l, s+sa);
+
+       printf("Result:\n");
+       r = asma_callchecking(s+sa);
+
+       printarray(r,l,r);
+
+       orig_r = orig_asma(stmp+sa);
+
+       if(r != s+sa) {
+               printf("[Error] return value wrong. Expected: %p\n", s+sa);
+               return 0;
+       }
+       if(memcmp(stmp+sa, s+sa, 16) != 0) {
+               printf("[Error] returned string wrong. Expected:\n");
+#if 1
+               printarray(utmp+ua, l, utmp+ua);
+#endif
+               printf("=== memcmp ===\n");
+               printf("memcmp(stmp+sa, orig_r, 16): %i\n", memcmp(stmp+sa, orig_r, 16));
+               printf("memcmp(s+sa, r, 16): %i\n", memcmp(s+sa, r, 16));
+               printf("=== input  ===\n");
+
+               printf("ref (s+sa):\n");
+               hexdump(stmp+sa, 16);
+               printf("asma (stmp+sa):\n");
+               hexdump(s+sa, 16);
+
+               printf("=== return ===\n");
+
+               printf("ref (orig_r):\n");
+               hexdump(orig_r, 16);
+               printf("asma (r):\n");
+               hexdump(r, 16);
+               return 0;
+       } else {
+               printf("succeeded\n");
+               return 1;
+       }
+}
+
+int main(int argc, char **argv)
+{
+       int success = 1;
+       int l=16+16+16;
+       int i, j, k;
+
+       unsigned char u[l];
+       unsigned char t[l];
+       unsigned char s[l];
+
+       for(i=0; i<16; i+=3) {
+               for(k=0; k<5; k++) {
+                       printf("==i: %d, k: %d\n", i, k);
+                       success &= test(s, t, u, i, 0, k);
+               }
+       }
+
+       if (!success)
+               fprintf(stdout,"\nTest failed.\n");
+       else
+               fprintf(stdout,"\nTest succeeded.\n");
+
+       return main2();
+}
+