CPU寄存器内的字节顺序

wrx*_*xyz 9 x86 endianness cpu-registers

我需要帮助理解x86处理器的CPU寄存器内的字节序.我写了这个小装配程序:

section .data
section .bss

section .text
    global _start
_start:
    nop
    mov eax, 0x78FF5ABC
    mov ebx,'WXYZ'
    nop  ; GDB breakpoint here.
    mov eax, 1
    mov ebx, 0
    int 0x80
Run Code Online (Sandbox Code Playgroud)

我在GDB中使用第10行的断点运行此程序(在上面的源代码中注释).在此断点,info registers显示的数值eax=0x78ff5abcebx=0x5a595857.

由于W,X,Y,Z的ASCII码分别为57,58,59,5A; 并且intel是小端,0x5a595857似乎是正确的字节顺序(最低有效字节优先).那么为什么不是eax寄存器的输出0xbc5aff78(数字0x78ff5abc的最低有效字节)而不是0x78ff5abc

sle*_*man 19

寄存器内的字节顺序没有意义,因为字节顺序描述字节顺序是从低存储器地址到高存储器地址还是从高存储器地址到低存储器地址.寄存器不是字节可寻址的,因此寄存器中没有低地址或高地址.您看到的是调试器打印数据的方式.

  • 实际上,寄存器*是*部分字节可寻址的.您可以使用AL和AH访问EAX的低两个字节. (4认同)
  • 这是字节可访问的,而不是字节"可寻址".您可以访问该较低字节但仍无法回答问题:"是低位字节位于高于或低于高字节的存储器地址".(好吧,你可以说操作码,如果被解释为整数,则大于或小于另一个,但这是非常随意的) (3认同)
  • 那么,当我们说CPU是小端字节序时,我们是在说CPU会遵循“小端字节序”规则从内存中读取多个字节吗?寄存器中的值将始终以大尾数保存? (2认同)
  • @KorayTugay:硬盘驱动器也是存储器:磁存储器。由于硬盘驱动器可以逐字节寻址,因此磁盘上的字节顺序很重要。 (2认同)

Jim*_*hel 13

汇编程序以不同方式处理这两个常量.在内部,EAX寄存器中的值以big-endian格式存储.你可以通过写:

mov eax, 1
Run Code Online (Sandbox Code Playgroud)

如果你检查寄存器,你会看到它的值是0x00000001.

当您告诉汇编程序您想要常量值时0x78ff5abc,这正是存储在寄存器中的内容.EAX的高8位将包含0x78,AL寄存器包含0xbc.

现在,如果您要将EAX中的值存储到内存中,它将以相反的顺序布置在内存中.也就是说,如果你要写:

mov [addr],eax
Run Code Online (Sandbox Code Playgroud)

然后在[addr]检查内存,你会看到0xbc,0x5a,0xff,0x78.

在'WXYZ'的情况下,汇编程序假定您要加载该值,以便在将其写入内存时,它将被布局为0x57,0x58,0x59,0x5a.

看看汇编程序生成的代码字节,你会看到差异.在这种情况下mov eax,0x78ff5abc,你会看到:

<opcodes for mov eax>, 0xbc, 0x5a, 0xff, 0x78
Run Code Online (Sandbox Code Playgroud)

在这种情况下mov eax,WXYZ,你会看到:

<opcodes for mov eax>, 0x57, 0x58, 0x59, 0x5a
Run Code Online (Sandbox Code Playgroud)

  • @KorayTugay:据我所知,现代处理器也是如此.我不知道旧处理器,但我怀疑它是真的."Endianess"仅关注CPU期望值如何存储在内存中. (4认同)
  • 所以当我们说CPU是小端的时候,我们是说CPU会按照"小端"规则从内存中读取多个字节吗?寄存器中的值将始终保存在Big Endian中? (3认同)

rus*_*lik 7

字节序仅对内存有意义,每个字节都有一个数字地址.当一个值的MSByte被放入比LSByte更高的内存地址时,它被称为Littte endian,这是任何x86处理器的字节顺序.

而对于整数,LSByte和MSByte之间的区别很明显:

    0x12345678
MSB---^^    ^^---LSB
Run Code Online (Sandbox Code Playgroud)

它没有为字符串文字定义!WXYZLSB或MSB应该被视为哪个部分并不明显:

1)最明显的方式,

'WXYZ' ->  0x5758595A
Run Code Online (Sandbox Code Playgroud)

会导致记忆秩序ZYXW.

2)当内存顺序与文字顺序相匹配时,并非如此明显的方式:

'WXYZ' ->  0x5A595857
Run Code Online (Sandbox Code Playgroud)

汇编程序必须选择其中一个,显然它选择了第二个.


Ang*_*llo 5

简而言之,将寄存器视为只是值,它们最终如何存储的字节序并不重要。

您知道在 eax 上写入您写入的是一个 32 位数字,并且您知道从 eax 读取您将读取相同的 32 位数字。从这个角度来说,字节序并不重要。

您知道,在“al”中,您拥有该值的较低有效 8 位部分,而在“ah”中,您拥有较低 16 位的最高有效 8 位部分。无法访问高 16 位上的单个字节,当然读取整个 32 位值除外。