输出64位整数的十六进制转储

6

我目前正在处理一些二进制数据。 为了检查和调试应用程序以前生成的数据,我使用 hexdump,但遇到了 hexdump 似乎无法提取 64 位整数字段的障碍。 给定以下最小化示例:

#include <iostream>
#include <fstream>
#include <cstdint>

int main(int argc, char** argv){
    std::ofstream os("tmp.bin", std::ios::out | std::ios::binary);
    uint64_t x = 7;
    os.write((char*)&x,sizeof(uint64_t));
    os.close();
    return 0;
}

我在系统上执行了一个简单的十六进制转储:
hexdump tmp.bin

> 0000000: 0007 0000 0000 0000
> 0000008:

现在尝试提取64位宽度的无符号整数产生了以下结果:
hexdump -e '/8 "%u"' tmp.bin

> hexdump: bad byte count for conversion character u

根据由 David Mair 撰写的 hexdump 手册,应该可以做到这一点,但我没有成功。我错过了什么?

很遗憾,这只能修改输出的缩进宽度,不能做其他的修改。 - Lars Hadidi
在manpages中,它说x和u最多只支持4个字节。无论如何,在一番折腾后,我找到了这个解决方法:hexdump -e '2/4 "%08X" "\n"' FILE | awk '{system("echo "ibase=16; "$1""|bc")}'它基本上打印了两个4字节的十六进制对,然后使用bc将其转换为十进制。我不知道这2个十六进制对的顺序是否需要交换才能得到正确的值,但你可以试试看。 - fassl
好的,我刚刚试过了。 的确需要交换值。 它的工作原理如下:hexdump -e '2/4 "%08X " "\n"' HEX | awk 'BEGIN{printf "ibase=16; "}{print $2 $1}' | bc谢谢。 - Lars Hadidi
好的,现在我要处理有符号数。由于我不知道它们是使用符号位、反码、补码、偏移二进制还是负基表示法来表示的,因此这对于快速转储来说太多了。因此,我们的解决方案仅适用于无符号64位整数。 - Lars Hadidi
1
最终你想出了答案 ;) - fassl
显示剩余3条评论
4个回答

3
我们的最终解决方法如下所示:
x=`hexdump -n 8 -e '2/4 "%08X " "\n"' {FILENAME} | awk 'BEGIN{printf "0x"}{print $2$1}'`
echo $(($x))

每个部分的解释:

  • Extract the eight bytes of the 64-bit integer value from file {FILENAME} as two four byte chunks printed as hexadecimal encoded values.

    hexdump -n 8 -e '2/4 "%08X " "\n"' {FILENAME}
    
  • Reverses the byte order of the two chunks and prints it as a single eight byte chunk representing the binary value. Prepend 0x for the following processing.

    awk 'BEGIN{printf "0x"}{print $2$1}
    
  • Save the hexadecimal representation into x for bash to evaluate.

    x=`....`
    
  • Let the bourne shell interpret and output the hexadecimal encoded value of the 64-bit integer variable (here the previously prepended 0x is needed).

    echo $(($x))
    

这帮助我理解了很多,非常感谢。 - bballdave025
我成功地扩展了它,这非常有用。 - bballdave025

1

也可以使用sed。以下代码可匹配8字节十六进制整数并交换它们。同样,这仅适用于无符号整数。

hexdump ... | sed 's/0x\([0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]\)/0x\2\1/'

据我所知,人们应该能够更清晰地撰写文章。
hexdump ... | sed 's/0x\([0-9a-f]{8,8}\)\([0-9a-f]{8,8}\)/0x\2\1/'

通常需要使用一些命令行选项,如-E来启用扩展正则表达式,但至少在Mac OS X 10.10上,这种方法不起作用。

1
尝试使用“od”命令。od -xL 输出长整数。

0

我不明白为什么这个不能直接使用,但是我遇到了同样的问题,需要打印64位整数,最终从这里编译了一个更好的版本:util-linuxhttps://github.com/karelzak/util-linux。起初我尝试在Ubuntu中安装该软件包,但它没有更新hexdump,所以我决定尝试手动更新。

这需要一些工作,但并不太难。只需使用git获取源代码,运行autogen.sh脚本,然后运行./configure,再运行make hexdump编译该程序即可。在我的笔记本电脑上,编译只花了4秒钟。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接