如何解析十六进制转储

时间:2014-06-18 15:59:40

标签: c hexdump flash-memory

我有一个闪存转储文件,用于吐出地址和数据。 我想解析数据,以便它告诉我有效的标签 &#; 002F0900'列是起始地址。 有效标签的一个例子是" DC 08 00 06 00 00 07 26 01 25 05 09"在哪里" DC 08" =标签号," 00 06" =标签数据长度," 00 00" =标签版本。标签数据在版本之后开始,在这种情况下将是" 07 26 01 25 05 09"并且下一个标签将开始" DC 33"。

我能够将第一个标签打印到数据长度,但我不确定如何打印数据,因为我必须考虑数据是否会进入下一行,所以我&# 39; d必须以某种方式跳过地址。每行包含58列。每个地址长度为8个字符加上冒号和2个空格,直到下一个十六进制值开始。

我最终还是要考虑" DC"显示在地址列中。 如果有人能给出一些建议,因为我知道我这样做是不是最好的方法。我只是想让它先工作。

文本文件是数千行,如下所示:

002F0900:  09 FF DC 08 00 06 00 00 07 26 01 25 05 09 DC 33
002F0910:  00 07 00 00 1F A0 26 01 25 05 09 FF 9C 3E 00 08
002F0920:  00 01 07 DD 0A 0D 00 29 35 AD 9C 41 00 0A 00 01
002F0930:  07 DD 0A 0D 00 29 36 1C 1D 01 9C 40 00 02 00 01
002F0940:  01 00 9C 42 00 0A 00 01 07 DD 0A 0D 00 29 36 21
002F0950:  1D AD 9C 15 00 20 00 00 01 00 00 00 00 04 AD AE
002F0960:  C8 0B C0 8A 5B 52 01 00 00 00 00 00 FF 84 36 BA
002F0970:  4E 92 E4 16 28 86 75 C0 DC 10 00 05 00 00 00 00
002F0980:  00 00 01 FF DC 30 00 04 00 01 00 00 00 01 9C 41

示例输出将是:

Tag Number: DC 08
Address: 002E0000    
Data Length: 06
Tag Data: 07 26 01 25 05 09

源代码:

#include<stdio.h>
FILE *fp;

main()
{
    int i=0;
    char ch;
    char address[1024];
    char tag_number[5];
    char tag_length[4];
    int number_of_addresses = 0;
    long int length;

    fp = fopen(FILE_NAME,"rb");
    if(fp == NULL) {
        printf("error opening file");
    }
    else {
        printf("File opened\n");
        while(1){
            if((address[i]=fgetc(fp)) ==':')
                break;

            number_of_addresses++;
            i++;
        }

        printf("\nAddress:");
        for (i = 0; i < number_of_addresses;i++)
            printf("%c",address[i]);

        while((ch = fgetc(fp)) != 'D'){ //Search for valid tag
        }

        tag_number[0] = ch;
        if((ch = fgetc(fp)) == 'C')  //We have a valid TAG
        {
            tag_number[1] = ch;
            tag_number[2] = fgetc(fp);
            tag_number[3] = fgetc(fp);
            tag_number[4] = fgetc(fp);
        }

        printf("\nNumber:");
        for(i=0;i<5;i++)
            printf("%c",tag_number[i]);

        fgetc(fp);      //For space
        tag_length[0] = fgetc(fp);
        tag_length[1] = fgetc(fp);
        fgetc(fp);      //For space
        tag_length[2] = fgetc(fp);
        tag_length[3] = fgetc(fp);

        printf("\nLength:");

        for(i=0;i<4;i++)
            printf("%c",tag_length[i]);

        length = strtol(tag_length,&tag_length[4], 16);
        printf("\nThe decimal equilvant is: %ld",length);
        for (i = 0;i<165;i++)
            printf("\n%d:%c",i,fgetc(fp));
    }

    fclose(fp);
}

更新@ooga:标签是任意写的。如果我们也在逻辑中考虑无效标记,那么如果我花一些时间,我应该能够弄清楚其余部分。感谢

1 个答案:

答案 0 :(得分:1)

这只是一个让你入门的想法,因为我并不完全确定你需要什么。基本思想是read_byte将下一个两位十六进制值作为一个字节返回,并返回其地址。

#include <stdio.h>
#include <stdlib.h>

#define FILE_NAME "UA201_dump.txt"

void err(char *msg) {
  fprintf(stderr, "Error: %s\n", msg);
  exit(EXIT_FAILURE);
}

// read_byte
// Reads a single two-digit "byte" from the hex dump, also
// reads the address (if necessary).
// Returns the byte and current address through pointers.
// Returns 1 if it was able to read a byte, 0 otherwise.

int read_byte(FILE *fp, unsigned *byte, unsigned *addr_ret) {

  // Save current column and address between calls.
  static int column = 0;
  static unsigned addr;

  // If it's the beginning of a line...
  if (column == 0)
    // ... read the address.
    if (fscanf(fp, "%x:", &addr) != 1)
      // Return 0 if no address could be read.
      return 0;

  // Read the next two-digit hex value into *byte.
  if (fscanf(fp, "%x", byte) != 1)
    // Return 0 if no byte could be read.
    return 0;

  // Set return address to current address.
  *addr_ret = addr;
  // Increment current address for next time.
  ++addr;

  // Increment column, wrapping back to 0 when it reaches 16.
  column = (column + 1) % 16;

  // Return 1 on success.
  return 1;
}


int main() {
  unsigned byte, addr, afterdc, length, version, i;

  FILE *fp = fopen(FILE_NAME,"r");
  if (!fp) {
    fprintf(stderr, "Can't open %s\n", FILE_NAME);
    exit(EXIT_FAILURE);
  }

  while (read_byte(fp, &byte, &addr)) {
    if (byte == 0xDC) {

      // Read additional bytes like this:
      if (!read_byte(fp, &afterdc, &addr)) err("EOF 1");

      if (!read_byte(fp, &length, &addr)) err("EOF 2");
      if (!read_byte(fp, &byte, &addr)) err("EOF 3");
      length = (length << 8) | byte;

      if (!read_byte(fp, &version, &addr)) err("EOF 4");
      if (!read_byte(fp, &byte, &addr)) err("EOF 5");
      version = (version << 8) | byte;

      printf("DC: %02X, %u, %u\n  ", afterdc, length, version);
      for (i = 0; i < length; ++i) {
        if (!read_byte(fp, &byte, &addr)) err("EOF 6");
        printf("%02X ", byte);
      }
      putchar('\n');
    }
  }

  fclose(fp);
  return 0;
}

一些解释:

每次调用read_byte时,它都会从十六进制转储读取下一个打印字节(两位十六进制值)。它返回该字节以及该字节的地址。

每行有16个两位十六进制值。列号(0到15)保留在调用之间的静态变量中。读取每个字节后,该列递增,每次列达到16时,复位为0。

只要列号为0,它就会读取打印的地址,并将其保留在静态变量中的调用之间。它还会增加静态addr变量,以便它可以告诉您行中任何位置的字节地址(当列号不为零时)。

例如,你可以像这样使用read_bye,它会在一个单独的行上打印每个字节值及其地址:

// after opening file as fp
while (read_byte(fp, &byte, &addr))
    printf("%08X- %02X\n", addr, byte);

(并不是说这样做很有用,但为了测试它,您可以使用您在问题中提供的代码段来运行它。)