我正在使用 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
如何正确解读这些地址和内容?
那是小端。
当在内存中存储多字节值时,有两种1存储方式:
较低地址上的较低字节。这称为小尾数或最低有效字节优先 (LSB)。
较低地址上的较高字节。这称为大端字节序或最高有效字节优先 (MSB)。
从历史上看,有些 CPU 是小端字节序,有些是大端字节序,其中大端字节序可能更常见,但小端字节序占主导地位。部分原因是最常见的 ix86 架构是小尾数法。第二个最常见的架构,ARM,可以配置为任何一种,虽然传统上许多操作系统将其用作大端(包括早期的 Linux),但最近似乎每个人都使用它的小端。主要原因可能是为了避免检查从 ix86 移植的代码是否是字节序中立的。
原因是看起来“错误”只是两个约定的冲突:
但这只是一个惯例。int在计算机中,小端在给定值中可能稍微更符合逻辑x,相等性(char)x == *(char *)&x成立,而在大端中则不然。当然,C 规范非常小心地保留了定义的实现(char它不违反严格的别名规则)。
1 PDP-11 采用了第三种方式,一种称为中间字节序的特殊令人讨厌的方式,其中 16 位值是小字节序,但 32 位值由大字节序中的两个 16 位单元组成。
| 归档时间: |
|
| 查看次数: |
997 次 |
| 最近记录: |