1/* 2 This file contains a simple hex dump routine. 3 4 THIS CODE COPYRIGHT DOMINIC GIAMPAOLO. NO WARRANTY IS EXPRESSED 5 OR IMPLIED. YOU MAY USE THIS CODE AND FREELY DISTRIBUTE IT FOR 6 NON-COMMERCIAL USE AS LONG AS THIS NOTICE REMAINS ATTACHED. 7 8 FOR COMMERCIAL USE, CONTACT DOMINIC GIAMPAOLO (dbg@be.com). 9 10 Dominic Giampaolo 11 dbg@be.com 12*/ 13#include <stdio.h> 14#include <ctype.h> 15 16#include "compat.h" 17 18/* 19 * This routine is a simple memory dumper. It's nice and simple, and works 20 * well. 21 * 22 * The bad things about it are that it assumes roughly an 80 column output 23 * device and that output is fixed at BYTES_PER_LINE/2 columns (separated 24 * every two bytes). 25 * 26 * Obviously the bad things are fixable, but I don't need the extra 27 * flexibility at the moment, so I don't feel like doing it. 28 * 29 * Dominic Giampaolo 30 * (dbg@be.com) 31 */ 32 33#define BYTES_PER_LINE 16 /* a reasonable power of two */ 34 35 36void hexdump(void *address, int size) 37{ 38 int i; 39 int offset, num_spaces; 40 unsigned char *mem, *tmp; 41 42 43 offset = 0; 44 mem = (unsigned char *)address; 45 46 /* 47 * Each line contains BYTES_PER_LINE bytes of data (presently 16). I 48 * chose 16 because it is a nice power of two and makes reading the 49 * hex offset column much easier. I used to use a value of 18 to fit 50 * more info on the screen, and 20 is also doable but much too crowded. 51 * Ideally it should be an argument or settable parameter... 52 * 53 * The data is formatted into BYTES_PER_LINE/2 (8) columns of 2 bytes 54 * each (printed in hex). 55 * 56 * The offset is formatted as a 4 byte hex number (i.e. 8 characters). 57 */ 58 while(offset < size) 59 { 60 printf("%.8x: ", offset); 61 62 for(i=0,tmp=mem; i < BYTES_PER_LINE && (offset+i) < size; i++,tmp++) 63 { 64 printf("%.2x", *tmp); 65 if (((i+1) % 4) == 0) 66 printf(" "); 67 } 68 69 /* 70 * This formula for the number of spaces to print is as follows: 71 * 10 is the number of characters printed at the beginning of 72 * the line (8 hex digits, the colon and a space). 73 * i*2 is the number of characters of data we dumped in hex. 74 * i/2 is the number of blanks we printed between columns. 75 * i is the number of bytes we will print in ascii. 76 * 77 * Then we subtract all that from 74 (the width of the output 78 * device) to decide how many spaces we need to push the ascii 79 * column as far to the right as possible. 80 * 81 * The number 58 is the column where we start we start printing 82 * the ascii dump. We subtract how many characters we've already 83 * printed and that gets us to where we need to be to start the 84 * ascii portion of the dump. 85 * 86 */ 87 num_spaces = 58 - (12 + i*2 + i/4); 88 for(i=0; i < num_spaces; i++) 89 printf(" "); 90 91 for(i=0,tmp=mem; i < BYTES_PER_LINE && (offset+i) < size; i++, tmp++) 92 if (isprint(*tmp)) 93 printf("%c", *tmp); 94 else 95 printf("."); 96 97 printf("\n"); 98 99 offset += BYTES_PER_LINE; 100 mem = tmp; 101 } 102} 103 104 105 106#ifdef TEST 107 108 109char buff[] = "!blah, blah blah blah blah asldfj lkasjdf lka lkjasdflasdlj" 110 "asdj lasdfj lasdjf lasdjf lkasjdfl kjasdlf jasldfj lasdfj l" 111 "asdjflkasjdflk;ja sdfljasdfjk asjkfl;kasjfl;asjdfl;azzzzzzz"; 112 113main(int argc, char **argv) 114{ 115 int i,j,k; 116 FILE *fp; 117 118 hexdump(buff, 171); 119 120 printf("---------\n"); 121 122 hexdump(main, 57); 123} 124 125#endif /* TEST */ 126