Benutzer:Martin: Unterschied zwischen den Versionen

Aus LaborWiki
Wechseln zu: Navigation, Suche
(17 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 11: Zeile 11:
== Meine Vorträge ==
== Meine Vorträge ==


* [[Optimierung durch Ganzzahlarithmetik für Microcontroller]]
* [[Vortragsprogramm/2011/Optimierung durch Ganzzahlarithmetik für Microcontroller]]
* [[Lightning Talks|Lightning-Talk]] "Multitasking ohne Betriebssytem im Mikrokontroller"
* [[Vortragsprogramm/2010/Lightning Talks]] Multitasking ohne Betriebssytem im Mikrokontroller
* [http://www.das-labor.org/files/madex/Farbborg3d_Labortag09.pdf Farbborgvortrag Labortage 09]
* [http://www.das-labor.org/files/madex/Farbborg3d_Labortag09.pdf Farbborgvortrag Labortage 09]
* Crashkurs C-Programmierung für 16x16x16 Borg 3D für Felix 3d in Stade
* Crashkurs C-Programmierung für 16x16x16 Borg 3D für Felix 3d in Stade
Zeile 22: Zeile 22:
* Portierung des [[Farb Borg 3d]] auf Cortex M3
* Portierung des [[Farb Borg 3d]] auf Cortex M3
* Optisches Stimmgerät [[Stimmmopped]].
* Optisches Stimmgerät [[Stimmmopped]].
* Weitere Projekte auf meiner [https://github.com/madex github-Seite]
== Mein Sudoku Solver ==
== Mein Sudoku Solver ==
  #include <stdio.h>
  #include <stdio.h>
Zeile 52: Zeile 54:
  l++%3)==2)puts("");j=0;puts("");}}}main(){char *b=sudoku,*r[]={q,c,w,0};p(b);
  l++%3)==2)puts("");j=0;puts("");}}}main(){char *b=sudoku,*r[]={q,c,w,0};p(b);
  if(t(0,b,r)){puts("solution:");p(b);}else puts("no solition found");return 0;}
  if(t(0,b,r)){puts("solution:");p(b);}else puts("no solition found");return 0;}
== Hilfreiche Funktionen ==
Da ich viel mit Mikrocontrollern mache, hapert es oft an grundlegenden Ausgabemöglichkeiten. Dann sucht man sich immer den Wolf, oder kopiert die Sachen aus alten Projekten, so dass ich hier einfach mal so ein paar optimierte Lösungen zum rauskopieren liegen habe. Viele sind auf Geschwindigkeit getrimmt, oder haben besondere lieb gewonnene Eigenschaften.
char* itoa(signed long val) {
    /** Die Ausgabe von itoa(i) ist identisch zu
    *  sprintf(buf, "%d", i);
    *  für den gesamten signed 32 bit Bereich. Selbst auf dem PC wesentlich schneller.
    */
    static char buf[13]; // vorsicht beim nächsten Aufruf von itoa ist str weg.
    char *sBuf = &buf[12];
    unsigned char negative = val < 0;
    unsigned long value, valueOld;
    *sBuf = 0;
    if (negative)
      value = (unsigned long) -val;
    else
      value = (unsigned long) val;
    do {
        valueOld = value;
        value /= 10;  // auch div 10
        *--sBuf = '0' + valueAlt - (value * 10); // schneller als % 10
    }  while (value);
    if (negative)
      *--sBuf = '-';
    return sBuf;
}
=== Ohne Multiplikation und Division ===
char *itoa(int32_t zahl) {
    static uint32_t subtractors[] = {1000000000,100000000,10000000,1000000,
                                    100000,10000,1000,100,10,1};
    static char string[12];
    char *str = string, n;
    uint32_t u, *sub = subtractors;
    uint8_t i = 10;
    if (zahl < 0) {
        *str++ = '-';
        u = (uint32_t) -zahl;
    } else
        u = (uint32_t) zahl;
    while (i > 1 && u < *sub) {
        i--;
        sub++;
    }
    while (i--) {
        char n = '0';
        while (u >= *sub) {
            n++;
            u -= *sub;
        }
        *str++ = n;
        sub++;
    }
    *str = 0;
    return string;
}
=== Ohne Multiplikation und Division mit fester Breite ===
char *itoaFixedWidth(int32_t zahl) {
    static uint32_t subtractors[] = {1000000000,100000000,10000000,1000000,
                                    100000,10000,1000,100,10,1};
    static char string[12];
    char n, *str = string, sign = zahl < 0 ? '-' : ' ';
    uint32_t *sub = subtractors;
    uint32_t u = zahl < 0 ? (uint32_t) -zahl : (uint32_t) zahl;   
    uint8_t  i = 10;
    *str++ = ' ';
    while (i > 1 && u < *sub) {
        i--;
        sub++;
        *str++ = ' ';
    }
    *(str-1) = sign;
    while (i--) {
        n = '0';
        while (u >= *sub) {
            u -= *sub;
            n++;
        }
        *str++ = n;
        sub++;
    }
    *str = 0;
    return string;
}
=== Schnelle Division / 10 mit Hilfe von Multiplikation und Schieben ===
// (uint64_t val) 26 bis 11184819 korrekt, (uint32_t val) 19 bis 81920 korrekt
#define BITS 19
#define MUL (((1L << BITS)/10) + 1)
unsigned long div10(unsigned long val) {
    return ((unsigned long) val * MUL) >> BITS;
}
getestet mit:
void main() {
    int i;
    printf("Multipilkator %d fuer %d Bits\n", MUL, BITS);
    for (i = 0; i < 99999999; i++) {
      if ((i/10) != div10(i)) {
          printf("Error At %d: %d != %d\n", i, i/10, div10(i));
          return;
      }
    }
}
=== Konfortable Ausgabe ===
char *itoaUint32VarLen(uint32_t value, uint8_t fillWith0, uint8_t lenghtInChars) {
    static uint8_t sBuf0[12];  // maximum Value -2147483649 = 12
    uint8_t *sBuf = &sBuf0[11], *sBufWerteBegrenzung;
    uint32_t valueAlt;  // Alte Wert für schneller % 10 Berechnung
    *sBuf = 0;
    if (value == 0) {
      *--sBuf = '0';
      lenghtInChars--; 
    } else while (value) {
      if (!lenghtInChars) {
        sBufWerteBegrenzung = sBuf;
        while (sBufWerteBegrenzung < &sBuf0[11])
            *sBufWerteBegrenzung++ = '9';
        break;
      }
      valueAlt  = value;
      value    /= 10;
      *--sBuf = '0' + valueAlt - (value * 10); // schneller als  *--sBuf = '0' + (valueAlt % 10)
      lenghtInChars--;
    }
    while (sBuf > sBuf0 && lenghtInChars--)    // mit Nullen auffüllen
        *--sBuf = fillWith0 ? '0' : ' ';
    return *sBuf;
}
=== Formatierte Augabe ===
char *itoaInt16Formated(int16_t value) {
    static uint8_t sBuf0[7];
    uint8_t *sBuf = &sBuf0[6];
    uint8_t  minus;
    uint16_t valueAlt;  // Alte Wert für schnellere % 10 Berechnung
    uint16_t valueCalc; // muss unsigned weil signed short kann kein 32768
    *sBuf = 0;
    if (value < 0) { // Vorzeichen behandeln
        minus = '-';
        valueCalc = -value;
    } else {
        minus = ' ';
        valueCalc = value;
    }
    do {
        valueAlt = valueCalc;
        valueCalc = div10(valueCalc); //  schneller als valueCalc /= 10;
        *--sBuf = '0' + valueAlt - (valueCalc * 10); // schneller als  *--sBuf = '0' + (valueAlt % 10)
    } while (valueCalc);
    *--sBuf = minus; // Minuszeichen vor die höchstwertigste Stelle setzen
    while (sBuf > sBuf0) // mit Leerzeichen auffüllen
        *--sBuf = ' ';
    return sBuf;
}
Mit dem IAR Compiler egiebt das folgenden AVR Assembler Output. Ohne externe Abhängigkeiten.
itoaInt16Formated:
        MOV    R3, R26
        MOVW    R23:R22, R25:R24
        MOVW    R25:R24, R17:R16
        LDI    R30, LOW((??sBuf0 + 6))
        LDI    R31, HIGH((??sBuf0 + 6))
        LDI    R16, 0
        ST      Z, R16
        TST    R17
        BRPL    ??itoaInt16Formated_0
        LDI    R26, 45
        MOV    R16, R24
        NEG    R17
        NEG    R16
        SBCI    R17, 0
        RJMP    ??itoaInt16Formated_1
??itoaInt16Formated_0:
        LDI    R26, 32
        MOV    R16, R24
??itoaInt16Formated_1:
        MOV    R18, R16
        OR      R18, R17
        BREQ    ??itoaInt16Formated_2
??itoaInt16Formated_3:
        MOVW    R21:R20, R17:R16
        LDI    R16, 205
        LDI    R17, 204
        CLR    R2
        MUL    R17, R21
        MOVW    R19:R18, R1:R0
        MUL    R17, R20
        MOV    R17, R0
        ADD    R18, R1
        ADC    R19, R2
        MUL    R16, R21
        ADD    R17, R0
        ADC    R18, R1
        ADC    R19, R2
        MUL    R16, R20
        ADD    R17, R1
        ADC    R18, R2
        ADC    R19, R2
        MOVW    R17:R16, R19:R18
        LSR    R17
        ROR    R16
        LSR    R17
        ROR    R16
        LSR    R17
        ROR    R16
        MOV    R18, R20
        SUBI    R18, 208
        MOV    R20, R16
        LDI    R19, 10
        MUL    R20, R19
        SUB    R18, R0
        ST      -Z, R18
        MOV    R18, R16
        OR      R18, R17
        BRNE    ??itoaInt16Formated_3
??itoaInt16Formated_2:
        OR      R24, R25
        BRNE    ??itoaInt16Formated_4
        LDI    R16, 48
        ST      -Z, R16
??itoaInt16Formated_4:
        ST      -Z, R26
        LDI    R16, LOW(??sBuf0)
        LDI    R17, (??sBuf0) >> 8
        CP      R16, R30
        CPC    R17, R31
        BRCC    ??itoaInt16Formated_5
??itoaInt16Formated_6:
        LDI    R18, 32
        ST      -Z, R18
        CP      R16, R30
        CPC    R17, R31
        BRCS    ??itoaInt16Formated_6
??itoaInt16Formated_5:
        MOVW    R17:R16, R31:R30
        MOVW    R25:R24, R23:R22
        MOV    R26, R3
        RET
=== atoi ===
int atoi(const char *c) {
    int result = 0;
    int sign  = 1;
    if (!c)
        return 0;
    while (*c == ' ')
        c++;
    if (*c == '-') {
        sign = -1;
        c++;
    }
    while (*c >= '0' && *c <= '9') {
        result *= 10;
        result += *c++ - '0';
    }
    return result * sign;
}
=== hexdump nur mit putchar ===
void hexDump(char *description, void *basisAddr, void *startAddr, unsigned long len) {
    unsigned char i = 0;
    unsigned long tempAdr;
    char hex[] = "0123456789abcdef";
    unsigned char buff[17], *ptrBuf;
    unsigned char *pc = (unsigned char*) startAddr;
    if (description != NULL) {
        while (*description)
            putchar(*description++);
        putchar('\n');
    }
    while (len--) {
        if (i >= 16) {
            i = 0;
            putchar(' ');
            putchar(' ');
            ptrBuf = buff;
            while (*ptrBuf)
                putchar(*ptrBuf++);
            putchar('\n');
        }
        if (i == 0) {
            putchar(' ');
            putchar(' ');
            tempAdr = pc - (unsigned char*) basisAddr;
            putchar(hex[(tempAdr >> 28) & 0xf]);
            putchar(hex[(tempAdr >> 24) & 0xf]);
            putchar(hex[(tempAdr >> 20) & 0xf]);
            putchar(hex[(tempAdr >> 16) & 0xf]);
            putchar(hex[(tempAdr >> 12) & 0xf]);
            putchar(hex[(tempAdr >>  8) & 0xf]);
            putchar(hex[(tempAdr >>  4) & 0xf]);
            putchar(hex[tempAdr & 0xf]);
            putchar(' ');
        }
        putchar(' ');
        putchar(hex[(*pc >>  4) & 0xf]);
        putchar(hex[*pc & 0xf]);
        if ((*pc < 0x20) || (*pc > 0x7e))
            buff[i] = '.';
        else
            buff[i] =  *pc;
        buff[i + 1] = '\0';
        pc++;
        i++;
    }
    while (i++ < 16) {
        putchar(' ');
        putchar(' ');
        putchar(' ');
    }
    putchar(' ');
    putchar(' ');
    ptrBuf = buff;
    while (*ptrBuf)
        putchar(*ptrBuf++);
    putchar('\n');
}

Version vom 11. Juni 2014, 14:44 Uhr

Seit dem ersten Mikrokontollerworkshop (2005) bin ich im Labor aktiv. Zu meinen beliebtesten Projkten zählt der Borg3d sowie der Farb Borg 3d die ich entwickelt, erbaut und programmiert habe.

Meine Interessen liegen in der Programmierung von C und C++ auf Microcontrollern wie den AVR, Soc-lm32, Arm Cortex M3 aber auch auf PC.

Ich setze Mac OSX schon seit etlichen Jahren und helfe gerne bei Fragen zu OSX.

Außerdem spiele ich Bass in einer Band und beschäftige mich in meiner Freizeit auch viel mit Musik.

Man kenn mich auch als madex (oder Martin3D wegen den großen Intresse an Dreidiminsionalität).

Meine Vorträge

Meine Projekte

Mein Sudoku Solver

#include <stdio.h>
#define _ 0
#define S(x) x,
#define D(x) x x x
#define L(x) D(S(x))
#define R(x) D(D(S(x)))
#define E(f,x) f(x)f(x+1)f(x+2)
char sudoku[] = { 
 1, _, _,  _, _, 7,  _, 9, _,
 _, 3, _,  _, 2, _,  _, _, 8,
 _, _, 9,  6, _, _,  5, _, _, 
   
 _, _, 5,  3, _, _,  9, _, _,
 _, 1, _,  _, 8, _,  _, _, 2,
 6, _, _,  _, _, 4,  _, _, _,
  
 3, _, _,  _, _, _,  _, 1, _, 
 _, 4, _,  _, _, _,  _, _, 7,
 _, _, 7,  _, _, _,  3, _, _,
};
char c[]={E(R,0)E(R,3)E(R,6)},q[]={D(D(E(S,0)E(S,3)E(S,6)))},w[]={D(E(L,0))
D(E(L,3))D(E(L,6))};v(char *b, char *r){int l[]={R(0)0},i=82,f,s;for(;--i;l[s]
|=1<<f){f=*b++;s=*r++;if(f&&s<9&&l[s]&(1<<f))return 0;}return 1;}h(char *b,char
**r){char *o;while(o=*r++)if(!v(b,o))return 0;return 1;}t(char n,char *b,char 
**r){char i=1;while(1){if(n>80)return 1;if(!b[n])break;n++;}for(;i<10;i++){
b[n]=i;if(h(b,r))if(t(n+1,b,r))return 1;}b[n]=0;return 0;}p(char*b){char j=0,l=
0,i=82;for(;--i;){printf(" %d",*b++);if((j%3)==2)printf(" ");if(++j==9){if((
l++%3)==2)puts("");j=0;puts("");}}}main(){char *b=sudoku,*r[]={q,c,w,0};p(b);
if(t(0,b,r)){puts("solution:");p(b);}else puts("no solition found");return 0;}

Hilfreiche Funktionen

Da ich viel mit Mikrocontrollern mache, hapert es oft an grundlegenden Ausgabemöglichkeiten. Dann sucht man sich immer den Wolf, oder kopiert die Sachen aus alten Projekten, so dass ich hier einfach mal so ein paar optimierte Lösungen zum rauskopieren liegen habe. Viele sind auf Geschwindigkeit getrimmt, oder haben besondere lieb gewonnene Eigenschaften.

char* itoa(signed long val) { 
   /** Die Ausgabe von itoa(i) ist identisch zu
    *  sprintf(buf, "%d", i);
    *  für den gesamten signed 32 bit Bereich. Selbst auf dem PC wesentlich schneller.	 
    */	 	
   static char buf[13]; // vorsicht beim nächsten Aufruf von itoa ist str weg.
   char *sBuf = &buf[12];
   unsigned char negative = val < 0;
   unsigned long value, valueOld;
   *sBuf = 0;
   if (negative)
      value = (unsigned long) -val;
   else
      value = (unsigned long) val;
   do {
       valueOld = value;
       value /= 10;  // auch div 10
       *--sBuf = '0' + valueAlt - (value * 10); // schneller als % 10
   }  while (value);
   if (negative)
      *--sBuf = '-';
   return sBuf;
}

Ohne Multiplikation und Division

char *itoa(int32_t zahl) {
   static uint32_t subtractors[] = {1000000000,100000000,10000000,1000000,
                                    100000,10000,1000,100,10,1};
   static char string[12];
   char *str = string, n;	
   uint32_t u, *sub = subtractors;
   uint8_t i = 10;
   if (zahl < 0) {
       *str++ = '-';
       u = (uint32_t) -zahl;
   } else
       u = (uint32_t) zahl;
   while (i > 1 && u < *sub) {
       i--;
       sub++;
   }
   while (i--) {
       char n = '0';
       while (u >= *sub) {
           n++;
           u -= *sub;
       }
       *str++ = n;
       sub++;
   }
   *str = 0;
   return string;
}

Ohne Multiplikation und Division mit fester Breite

char *itoaFixedWidth(int32_t zahl) {
   static uint32_t subtractors[] = {1000000000,100000000,10000000,1000000,
                                    100000,10000,1000,100,10,1};
   static char string[12];
   char n, *str = string, sign = zahl < 0 ? '-' : ' ';	
   uint32_t *sub = subtractors;
   uint32_t u = zahl < 0 ? (uint32_t) -zahl : (uint32_t) zahl;    
   uint8_t  i = 10;	
   *str++ = ' ';
   while (i > 1 && u < *sub) {
       i--;
       sub++;
       *str++ = ' ';
   }
   *(str-1) = sign;
   while (i--) {
       n = '0';
       while (u >= *sub) {
           u -= *sub;
           n++;
       }
       *str++ = n;
       sub++;
   }
   *str = 0;
   return string;
}

Schnelle Division / 10 mit Hilfe von Multiplikation und Schieben

// (uint64_t val) 26 bis 11184819 korrekt, (uint32_t val) 19 bis 81920 korrekt
#define BITS 19
#define MUL (((1L << BITS)/10) + 1)
unsigned long div10(unsigned long val) {
   return ((unsigned long) val * MUL) >> BITS; 
}

getestet mit:

void main() {
   int i;
   printf("Multipilkator %d fuer %d Bits\n", MUL, BITS);
   for (i = 0; i < 99999999; i++) {
      if ((i/10) != div10(i)) {
         printf("Error At %d: %d != %d\n", i, i/10, div10(i));
         return;
      }
   }
}

Konfortable Ausgabe

char *itoaUint32VarLen(uint32_t value, uint8_t fillWith0, uint8_t lenghtInChars) {
   static uint8_t sBuf0[12];   // maximum Value -2147483649 = 12
   uint8_t *sBuf = &sBuf0[11], *sBufWerteBegrenzung;
   uint32_t valueAlt;   // Alte Wert für schneller % 10 Berechnung
   *sBuf = 0;
   if (value == 0) {
     *--sBuf = '0';
     lenghtInChars--;  
   } else while (value) {
     if (!lenghtInChars) {
       sBufWerteBegrenzung = sBuf;
       while (sBufWerteBegrenzung < &sBuf0[11])
           *sBufWerteBegrenzung++ = '9';
       break;
     }
     valueAlt   = value;
     value     /= 10;
     *--sBuf = '0' + valueAlt - (value * 10); // schneller als  *--sBuf = '0' + (valueAlt % 10)
     lenghtInChars--;
   } 
   while (sBuf > sBuf0 && lenghtInChars--)    // mit Nullen auffüllen
       *--sBuf = fillWith0 ? '0' : ' ';
   return *sBuf;
}

Formatierte Augabe

char *itoaInt16Formated(int16_t value) {
   static uint8_t sBuf0[7];
   uint8_t *sBuf = &sBuf0[6];
   uint8_t  minus;
   uint16_t valueAlt;  // Alte Wert für schnellere % 10 Berechnung
   uint16_t valueCalc; // muss unsigned weil signed short kann kein 32768
   *sBuf = 0;
   if (value < 0) { // Vorzeichen behandeln
       minus = '-';
       valueCalc = -value;
   } else {
       minus = ' ';
       valueCalc = value;
   }
   do {
       valueAlt = valueCalc;
       valueCalc = div10(valueCalc); //  schneller als valueCalc /= 10;
       *--sBuf = '0' + valueAlt - (valueCalc * 10); // schneller als  *--sBuf = '0' + (valueAlt % 10)
   } while (valueCalc);
   *--sBuf = minus; // Minuszeichen vor die höchstwertigste Stelle setzen
   while (sBuf > sBuf0) // mit Leerzeichen auffüllen
       *--sBuf = ' ';
   return sBuf;
}

Mit dem IAR Compiler egiebt das folgenden AVR Assembler Output. Ohne externe Abhängigkeiten.

itoaInt16Formated:
       MOV     R3, R26
       MOVW    R23:R22, R25:R24
       MOVW    R25:R24, R17:R16
       LDI     R30, LOW((??sBuf0 + 6))
       LDI     R31, HIGH((??sBuf0 + 6))
       LDI     R16, 0
       ST      Z, R16
       TST     R17
       BRPL    ??itoaInt16Formated_0
       LDI     R26, 45
       MOV     R16, R24
       NEG     R17
       NEG     R16
       SBCI    R17, 0
       RJMP    ??itoaInt16Formated_1
??itoaInt16Formated_0:
       LDI     R26, 32
       MOV     R16, R24
??itoaInt16Formated_1:
       MOV     R18, R16
       OR      R18, R17
       BREQ    ??itoaInt16Formated_2
??itoaInt16Formated_3:
       MOVW    R21:R20, R17:R16
       LDI     R16, 205
       LDI     R17, 204
       CLR     R2
       MUL     R17, R21
       MOVW    R19:R18, R1:R0
       MUL     R17, R20
       MOV     R17, R0
       ADD     R18, R1
       ADC     R19, R2
       MUL     R16, R21
       ADD     R17, R0
       ADC     R18, R1
       ADC     R19, R2
       MUL     R16, R20
       ADD     R17, R1
       ADC     R18, R2
       ADC     R19, R2
       MOVW    R17:R16, R19:R18
       LSR     R17
       ROR     R16
       LSR     R17
       ROR     R16
       LSR     R17
       ROR     R16
       MOV     R18, R20
       SUBI    R18, 208
       MOV     R20, R16
       LDI     R19, 10
       MUL     R20, R19
       SUB     R18, R0
       ST      -Z, R18
       MOV     R18, R16
       OR      R18, R17
       BRNE    ??itoaInt16Formated_3
??itoaInt16Formated_2:
       OR      R24, R25
       BRNE    ??itoaInt16Formated_4
       LDI     R16, 48
       ST      -Z, R16
??itoaInt16Formated_4:
       ST      -Z, R26
       LDI     R16, LOW(??sBuf0)
       LDI     R17, (??sBuf0) >> 8
       CP      R16, R30
       CPC     R17, R31
       BRCC    ??itoaInt16Formated_5
??itoaInt16Formated_6:
       LDI     R18, 32
       ST      -Z, R18
       CP      R16, R30
       CPC     R17, R31
       BRCS    ??itoaInt16Formated_6
??itoaInt16Formated_5:
       MOVW    R17:R16, R31:R30
       MOVW    R25:R24, R23:R22
       MOV     R26, R3
       RET

atoi

int atoi(const char *c) {
   int result = 0;
   int sign   = 1;
   if (!c)
       return 0;
   while (*c == ' ') 
       c++;
   if (*c == '-') {
       sign = -1;
       c++;
   }
   while (*c >= '0' && *c <= '9') {
       result *= 10;
       result += *c++ - '0';
   }
   return result * sign;
}

hexdump nur mit putchar

void hexDump(char *description, void *basisAddr, void *startAddr, unsigned long len) {
   unsigned char i = 0;
   unsigned long tempAdr;
   char hex[] = "0123456789abcdef";
   unsigned char buff[17], *ptrBuf;
   unsigned char *pc = (unsigned char*) startAddr;
   if (description != NULL) {
       while (*description)
           putchar(*description++);
       putchar('\n');
   }
   while (len--) {
       if (i >= 16) {
           i = 0;
           putchar(' ');
           putchar(' ');
           ptrBuf = buff;
           while (*ptrBuf)
               putchar(*ptrBuf++);
           putchar('\n');
       }
       if (i == 0) {
           putchar(' ');
           putchar(' ');
           tempAdr = pc - (unsigned char*) basisAddr;
           putchar(hex[(tempAdr >> 28) & 0xf]);
           putchar(hex[(tempAdr >> 24) & 0xf]);
           putchar(hex[(tempAdr >> 20) & 0xf]);
           putchar(hex[(tempAdr >> 16) & 0xf]);
           putchar(hex[(tempAdr >> 12) & 0xf]);
           putchar(hex[(tempAdr >>  8) & 0xf]);
           putchar(hex[(tempAdr >>  4) & 0xf]);
           putchar(hex[tempAdr & 0xf]);
           putchar(' ');
       }
       putchar(' ');
       putchar(hex[(*pc >>  4) & 0xf]);
       putchar(hex[*pc & 0xf]);
       if ((*pc < 0x20) || (*pc > 0x7e))
           buff[i] = '.';
       else
           buff[i] =  *pc;
       buff[i + 1] = '\0';
       pc++;
       i++;
   }
   while (i++ < 16) {
       putchar(' ');
       putchar(' ');
       putchar(' ');
   }
   putchar(' ');
   putchar(' ');
   ptrBuf = buff;
   while (*ptrBuf)
       putchar(*ptrBuf++);
   putchar('\n');
}