.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
.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:
--- /dev/null
+/* 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;
+}
#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';
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);
}
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();
+}
+