【问题标题】:Is GDB interpreting the memory address correctly?GDB 是否正确解释了内存地址?
【发布时间】:2014-06-23 12:12:01
【问题描述】:

我正在使用 GDB 检查内存地址的内容,但不知道它是否正确显示。

(gdb) p (char *)0x8182f40
 $4 = 0x8182f40 "XYZ"
(gdb)


(gdb) x/40x 0x8182f40-16
0x8182f30:      0x00000000      0x00000000      0x000000a8      0x00000010
0x8182f40:      0x005a5958      0x00000000      0x00000000      0x00000029
0x8182f50:      0x00000000      0x00000000      0x00010000      0x082439d8
0x8182f60:      0x08199100      0x00000000      0x08000000      0x00002f08
0x8182f70:      0x00000002      0x000000b1      0x00000000      0x00000000
0x8182f80:      0x00000000      0x00000000      0x00000000      0x00000000
0x8182f90:      0x00000000      0x00000000      0x000000d4      0x00000002
0x8182fa0:      0x000003f1      0x00007162      0x00000002      0x08178d00
0x8182fb0:      0x00000000      0x080ef4b8      0x00000000      0x00000000
0x8182fc0:      0x00000000      0x00000000      0x0000021d      0x00000000

上面0x8182f40 的内容显示为0x005a5958,但这看起来是相反的。对吗?

现在按字节打印,我明白了:

(gdb) x/40bx 0x8182f40-16
0x8182f30:      0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0x8182f38:      0xa8    0x00    0x00    0x00    0x10    0x00    0x00    0x00
0x8182f40:      0x58    0x59    0x5a    0x00    0x00    0x00    0x00    0x00
0x8182f48:      0x00    0x00    0x00    0x00    0x29    0x00    0x00    0x00
0x8182f50:      0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00

这个更有意义:0x8182f40: 0x58 0x59 0x5a
X Y Z

如何正确解读这些地址和内容?

【问题讨论】:

    标签: c gdb


    【解决方案1】:

    那是little endian

    在内存中存储多字节值时,有两种1的存储方式:

    • 低地址上的低字节。这称为小端或最低有效字节优先 (LSB)。

    • 低地址上的高字节。这称为大端或最高有效字节优先 (MSB)。

    从历史上看,有些 CPU 是小端,有些是大端,大端可能更常见,但小端占了上风。部分原因是最常见的 ix86 架构是小端。第二个最常见的架构,ARM,可以配置为任何一种,虽然传统上许多操作系统使用它作为大端(包括早期的 Linux),但最近似乎每个人都使用它小端。主要原因可能是避免检查从 ix86 移植的代码是否是字节序中性的。

    原因是看起来“错误”只是两种约定的冲突:

    1. 数字从左到右书写,最高有效位在前
    2. 内存内容按地址递增的顺序从左到右写入。

    但这只是一个约定。在计算机中,在给定intx 的情况下,小端可能稍微更合乎逻辑,等式(char)x == *(char *)&x 成立,这在大端中不成立。当然,C 规范非常谨慎地定义了这个实现(char 它不违反严格的别名规则)。

    1PDP-11 采用了第三种方式,一种称为中间端的特殊可憎,其中 16 位值是小端,但 32 位值由两个 16-大端的位单位。

    【讨论】:

    • 所以在这种情况下,当打印为单词0x005a5958时,意味着首先写入最高地址0x8182f43 => '0x00',然后再写入递减地址0x8182f42 => '0x5a'0x8182f41 => '0x59'0x8182f40 => '0x58'
    【解决方案2】:

    看起来您的 GDB 设置为 Little-Endian。有关Endianness的更多详细信息,请参阅http://en.wikipedia.org/wiki/Endianness

    【讨论】:

    • GDB 设置为 Little-endian 很可能是因为平台几乎肯定是 little-endian。大端平台几乎绝迹。
    【解决方案3】:

    您可能需要设置字节顺序:http://www.delorie.com/gnu/docs/gdb/gdb_130.html

    【讨论】:

    • 字节序几乎可以肯定已为架构正确设置。
    猜你喜欢
    • 1970-01-01
    • 2011-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多