GDB 是否正确解释内存地址?

adi*_*one 4 c gdb endianness

我正在使用 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
Run Code Online (Sandbox Code Playgroud)

上面的内容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
Run Code Online (Sandbox Code Playgroud)

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

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

Jan*_*dec 5

那是小端

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

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

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

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

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

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

但这只是一个惯例。int在计算机中,小端在给定值中可能稍微更符合逻辑x,相等性(char)x == *(char *)&x成立,而在大端中则不然。当然,C 规范非常小心地保留了定义的实现(char它不违反严格的别名规则)。

1 PDP-11 采用了第三种方式,一种称为中间字节序的特殊令人讨厌的方式,其中 16 位值是小字节序,但 32 位值由大字节序中的两个 16 位单元组成。