Home | History | Annotate | Download | only in x86
      1 #include "tests/asm.h"
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 #include <string.h>
      5 #include <assert.h>
      6 
      7 /* These fns taken from dietlibc-0.30 (is GPL v2'd) */
      8 
      9 /*
     10   Copyright (C) 2002 Thomas M. Ogrisegg
     11 
     12   This is free software. You can redistribute and
     13   modify it under the terms of the GNU General Public
     14   Public License.
     15 
     16   strncpy.S
     17     i386 assembler implementation of strncpy(3)
     18 */
     19 extern char *mystrncpy(char *dest, const char *src, size_t n);
     20 asm(
     21 ".text\n"
     22 "\n"
     23 VG_SYM(mystrncpy) ":\n"
     24 "	pushl %esi\n"
     25 "	pushl %edi\n"
     26 "	movl %esp, %ecx\n"
     27 "	movl  0x0c(%ecx), %edi\n"
     28 "	movl  0x10(%ecx), %esi\n"
     29 "	movl  0x14(%ecx), %ecx\n"
     30 "\n"
     31 "	movl %edi, %edx\n"
     32 "	cld\n"
     33 "0:\n"
     34 "	dec %ecx\n"
     35 "	js 1f\n"
     36 "	lodsb\n"
     37 "	stosb\n"
     38 "	or %al, %al\n"
     39 "	jnz 0b\n"
     40 "	repnz stosb\n"
     41 "1:\n"
     42 "	movl %edx, %eax\n"
     43 "	popl %edi\n"
     44 "	popl %esi\n"
     45 "	ret\n"
     46 "\n"
     47 );
     48 
     49 
     50 /*
     51    Copyright (C) 2002 Thomas M. Ogrisegg
     52 
     53    __ltostr.S -- convert an integer into a string
     54 
     55  %eax = dividend
     56  %ebx = divisor
     57  %ecx = size of output-buffer
     58  %edi = output-buffer
     59  %ebp = if uppercase is set, then %ebp is 'A'-10 else %ebp is 'a'-10
     60 
     61 */
     62 extern int __ltostr(char *s, unsigned int size, unsigned long i,
     63                              unsigned int base, int UpCase);
     64 asm(
     65 ".text\n"
     66 VG_SYM(__ltostr) ":\n"
     67 "        pushl %esi\n"
     68 "        pushl %edi              # destination\n"
     69 "        pushl %ebp\n"
     70 "        pushl %ebx\n"
     71 "        movl %esp, %eax\n"
     72 "        movl 0x14(%eax), %edi\n"
     73 "        movl 0x18(%eax), %ecx   # size\n"
     74 "        movl 0x20(%eax), %ebx   # divisor\n"
     75 "        movl 0x1c(%eax), %eax   # dividend\n"
     76 "        decl %ecx\n"
     77 "        movl %ecx, %esi\n"
     78 "        movl $55, %ebp          # 55 == char(A)-10\n"
     79 "        xorl %edx, %edx         # must be 0 -- used by idiv\n"
     80 "        cmpl $0x0, 36(%esp)     # check for uppercase\n"
     81 "        jnz 0f\n"
     82 "        addl $0x20, %ebp        # set lowercase\n"
     83 "0:\n"
     84 "        idiv %ebx, %eax\n"
     85 "        cmpb $0x9, %dl\n"
     86 "        jg 1f\n"
     87 "        addb $48, %dl           # 48 == '0'\n"
     88 "        jmp 2f\n"
     89 "1:\n"
     90 "        addl %ebp, %edx\n"
     91 "2:\n"
     92 "        movb %dl, (%edi, %ecx)\n"
     93 "        xorl %edx, %edx\n"
     94 "        decl %ecx\n"
     95 "        jz 3f\n"
     96 "        orl %eax, %eax\n"
     97 "        jnz 0b\n"
     98 "3:\n"
     99 "        cld\n"
    100 "        movl %esi, %ebx\n"
    101 "        leal 1(%edi, %ecx), %esi\n"
    102 "        subl %ebx, %ecx\n"
    103 "        negl %ecx\n"
    104 "        movl %ecx, %eax\n"
    105 "        repnz movsb\n"
    106 "        movb $0x0, (%edi)\n"
    107 "        popl %ebx\n"
    108 "        popl %ebp\n"
    109 "        popl %edi\n"
    110 "        popl %esi\n"
    111 "        ret\n"
    112 );
    113 
    114 #define STREQ(a, b)     (strcmp((a), (b)) == 0)
    115 
    116 const char *it = "<UNSET>";     /* Routine name for message routines. */
    117 size_t errors = 0;
    118 
    119 /* Complain if condition is not true.  */
    120 static void
    121 check (int thing, int number)
    122 {
    123   if (!thing)
    124     {
    125       printf("%s flunked test %d\n", it, number);
    126       ++errors;
    127     }
    128 }
    129 
    130 /* Complain if first two args don't strcmp as equal.  */
    131 static void
    132 equal (const char *a, const char *b, int number)
    133 {
    134   check(a != NULL && b != NULL && STREQ (a, b), number);
    135 }
    136 
    137 char one[50];
    138 char two[50];
    139 char *cp;
    140 
    141 static void
    142 test_strncpy (void)
    143 {
    144   /* Testing is a bit different because of odd semantics.  */
    145   it = "strncpy";
    146   check (mystrncpy (one, "abc", 4) == one, 1);    /* Returned value. */
    147   equal (one, "abc", 2);                        /* Did the copy go right? */
    148 
    149   (void) strcpy (one, "abcdefgh");
    150   (void) mystrncpy (one, "xyz", 2);
    151   equal (one, "xycdefgh", 3);                   /* Copy cut by count. */
    152 
    153   (void) strcpy (one, "abcdefgh");
    154   (void) mystrncpy (one, "xyz", 3);               /* Copy cut just before NUL. */
    155   equal (one, "xyzdefgh", 4);
    156 
    157   (void) strcpy (one, "abcdefgh");
    158   (void) mystrncpy (one, "xyz", 4);               /* Copy just includes NUL. */
    159   equal (one, "xyz", 5);
    160   equal (one+4, "efgh", 6);                     /* Wrote too much? */
    161 
    162   (void) strcpy (one, "abcdefgh");
    163   (void) mystrncpy (one, "xyz", 5);               /* Copy includes padding. */
    164   equal (one, "xyz", 7);
    165   equal (one+4, "", 8);
    166   equal (one+5, "fgh", 9);
    167 
    168   (void) strcpy (one, "abc");
    169   (void) mystrncpy (one, "xyz", 0);               /* Zero-length copy. */
    170   equal (one, "abc", 10);
    171 
    172   (void) mystrncpy (one, "", 2);          /* Zero-length source. */
    173   equal (one, "", 11);
    174   equal (one+1, "", 12);
    175   equal (one+2, "c", 13);
    176 
    177   (void) strcpy (one, "hi there");
    178   (void) mystrncpy (two, one, 9);
    179   equal (two, "hi there", 14);          /* Just paranoia. */
    180   equal (one, "hi there", 15);          /* Stomped on source? */
    181 }
    182 
    183 
    184 int main ( void )
    185 {
    186   char buf[1024];
    187 
    188   /* test strncpy, hence repnz stosb */
    189   test_strncpy();
    190     if (errors == 0)
    191     {
    192       printf("No errors.\n");
    193     }
    194   else
    195     {
    196       printf("%d errors.\n", (int)errors);
    197     }
    198 
    199     /* test __ltostr, hence repnz stosb */
    200   assert(__ltostr(buf,10,1723,10,0)==4); assert(!strcmp(buf,"1723"));
    201   assert(__ltostr(buf,3,1723,10,0)==2); assert(!strcmp(buf,"23"));
    202   assert(__ltostr(buf,2,0x1234,16,0)==1); assert(!strcmp(buf,"4"));
    203   assert(__ltostr(buf,3,0xFEFE,16,1)==2); assert(!strcmp(buf,"FE"));
    204 
    205  return 0;
    206 }
    207