GDB是否正确解释了内存地址? [英] Is GDB interpreting the memory address correctly?

查看:200
本文介绍了GDB是否正确解释了内存地址?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

 (gdb)p(char *)0x8182f40 
$ 4 = 0x8182f40XYZ
(gdb)

$ b $(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

XYZ



我如何正确解释这些地址和内容? little endian

当存储多字节val在存储器中,有两种 1 方式来存储它们:


  • 。这被称为Little Endian或最低有效字节优先(LSB)。


  • 较低地址上的较高字节。这被称为Big Endian或最高有效字节在先(MSB)。


    从历史上看,一些CPU是小端的,有些是大端的大端序列可能更常见,但小端序列盛行。部分原因是最常见的ix86架构是小端。第二种最常见的架构ARM可以被配置为传统上很多操作系统都被用作大端(包括早期的Linux),最近每个人似乎都使用它作为小端。主要原因可能是为了避免检查从ix86移植的代码是否是endian-neutral。



    原因看起来错误只是两个约定的冲突: / p>


    1. 数字从最左边到最右边的数字是先写入的
    2. 写入内存内容按地址递增的顺序从左到右。

    但这只是一个约定。在计算机中,在给定 int x 时,little endian可能稍微更合理,等于(char)x == *(char *)& x 成立,这在大端中是不正确的。当然,C规范非常小心,可以定义此实现(使用 char 它不违反严格的别名规则)。



    < PDP-11具有第三种方式,称为中端的特殊憎恶,其中16位值是小端,但32位值是由两个16位组成的单位在大端。


    I am examining the contents of a memory address using GDB, but don't know if it is being displayed correctly.

    (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
    

    Content at 0x8182f40 above is shown as 0x005a5958, but this looks reversed. Is that correct?

    Now printing per byte, I get this:

    (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
    

    This one makes more sense: 0x8182f40: 0x58 0x59 0x5a
    X Y Z

    How do I correctly interpret these addresses and contents?

    解决方案

    That's little endian.

    When storing multi-byte values in memory, there are two1 ways to store them:

    • Lower bytes on lower addresses. This is called Little Endian or Least Significant Byte First (LSB).

    • Higher bytes on lower addresses. This is called Big Endian or Most Significant Byte First (MSB).

    Historically some CPUs were little endian and some were big endian with big endian perhaps more common, but little endian prevailed. In part because the most common ix86 architecture is little endian. The second most common architecture, ARM, can be configured for either and while traditionally many operating systems used it as big endian (including early Linux), recently everybody seems to use it little endian. Main reason is probably to avoid having to check that code ported from ix86 is endian-neutral.

    The reason is looks "wrong" is just a conflict of two conventions:

    1. Numbers are written left-to-right with most significant digit first
    2. Content of memory is written left-to-right in order of increasing addresses.

    But this is merely a convention. In computer, little endian might be slightly more logical in that given int value x, the equality (char)x == *(char *)&x holds, which is not true in big endian. Of course C specification is careful enough to leave this implementation defined (with char it does not violate strict aliasing rules).

    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.

    这篇关于GDB是否正确解释了内存地址?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆