我正在使用 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
如何正确解读这些地址和内容?
That's 小端.
When storing multi-byte values in memory, there are two1 ways to store them:
从历史上看,有些 CPU 是小端字节序,有些是大端字节序,其中大端字节序可能更常见,但小端字节序占主导地位。部分原因是最常见的 ix86 架构是小尾数法。第二个最常见的架构,ARM,可以配置为任一,虽然传统上许多操作系统将其用作大端(包括早期的 Linux),但最近每个人似乎都使用它的小端。主要原因可能是为了避免检查从 ix86 移植的代码是否是字节序中立的。
原因是看起来“错误”只是两个约定的冲突:
- 数字从左到右书写,最高有效数字在前
- 内存内容按照地址递增的顺序从左到右写入。
但这只是一个惯例。在计算机中,小端可能在给定的情况下稍微更符合逻辑int
value x
,平等(char)x == *(char *)&x
成立,但在大端字节序中则不然。当然,C 规范足够仔细,保留了定义的实现(使用char
它不违反严格的别名规则)。
1PDP-11 featured a third way, a special abomination called middle endian, where 16-bit values were little endian, but 32-bit values were composed of the two 16-bit units in big endian.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)