c - 如何解析十六进制转储

标签 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”开始。

我能够打印出第一个标签直到数据长度,但我不确定如何打印数据,因为我必须考虑数据是否会进入下一行,所以我不得不跳过地址不知何故。每行包含 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:标签是乱写的。如果我们还在逻辑中考虑无效标签,那么如果我花一些时间,我应该能够弄清楚其余部分。谢谢

最佳答案

这只是一个让您入门的想法,因为我不完全确定您需要什么。基本思想是 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,它就会读取打印的地址,并在调用之间将其保留在静态变量中。它还会增加静态地址变量,以便它可以告诉您行中任意位置的字节地址(当列号不为零时)。

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

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

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

关于c - 如何解析十六进制转储,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24290156/

相关文章:

binary-data - SREC 或 Intel HEX 等十六进制格式的优势

linux - 如何通过文件名获取NAND中的真实文件偏移量?

c - 在 C 中为宏使用预处理器语句

c - 谁在 linux 内核中调用 tty_open()?

c - 原始 TCP 套接字在发送初始数据后接收恒定的 PSH、ACK 数据包

linux - 使用binwalk提取所有文件

java - 将十六进制字符串转换为字节数组以进行 RSA 解密

c - 我应该使用什么来代替 goto 语句?

c++ - 无法写入闪存程序存储器(PIC18F4620)

c - 将 rodata 与创建它的函数一起定位