【问题标题】:Assembly language - Why are characters stored in register as little endian?汇编语言 - 为什么将字符存储在寄存器中作为小端?
【发布时间】:2018-02-06 14:30:18
【问题描述】:

我是汇编语言的新手。我正在尝试下面的代码,你可以看到下面的代码。

bits 64
global _start
section .text
_start:

        mov rcx, 1234567890
        xor rcx, rcx
        mov rcx, 'wxyz'

        mov rax, 60
        mov rdi, 0 
        syscall

我想知道为什么数字在寄存器中存储为大端,而字符在寄存器中存储为小端

以下屏幕截图来自调试器。

我以为只有在内存中,数据以小端序存储。但我不明白为什么这些字符在寄存器中存储为小端。请告诉我。

谢谢。

【问题讨论】:

  • 这取决于你的汇编器(你没有指定但看起来像nasm)。这个想法是,如果写入内存,您将按预期顺序获取字符串。
  • x86 会将其读取为小端序。但是 NASM 将以这样的方式组装它,“abcd”将作为字节“a”、“b”、“c”、“d”进入内存......关于字符串字节序和这个特殊的原因没有太多意义NASM 关于字符串常量的特性就是这样设计的,它“额外的方便”,稍微偏离了严格的机器逻辑。因此,如果您使用mov eax,'0123'mov eax,0x30313233,这两个是不同的值(bswap 方式不同)。您只需记住这一点(就像任何其他语法“怪癖”一样)。或者在组装你得到的东西后检查列表文件中的机器代码。
  • 这更像是 NASM 将字符串常量视为字节流(在生成的机器代码中保持它们的“字符串”顺序),即使在上下文中用作单词或更大的类型时,数字常量也很少-endian 处理并在内存中“反转”。 CPU 不知道您的来源,因此它不知道(来自字符串和表示字符的值),如果您执行类似mov eax,'0123' => eax = 0x33323130.
  • @vanquish 我不太明白你在这里的最后一条评论,它是温和的“是”,在内存中小端,在寄存器中你可以认为它是大端,但它更像是在注册值只是 value (无字节序)。除了左移/右移之外,它几乎没有“空间方向”,它在 CPU 中的某个地方有位,很难说在哪里以及以什么顺序,你可以把它当作常识使用,作为二进制整数值/等等......当存储到内存中时被撕成LE字节。并且调试器自然地显示 reg 值(“BE”-like),但这是格式化代码。

标签: assembly x86-64 endianness


【解决方案1】:

谈论 CPU 寄存器的字节顺序没有多大意义,因为地址没有分配给组成寄存器的特定字节,即:没有字节顺序需要考虑。

也就是说,例如alrax的最低字节,ah是第二低的。考虑到这一点,alah 的地址是什么? ah 的地址是高于还是低于al 地址?它们没有关联的(内存)地址,因此根本不需要考虑字节顺序。

相关的是这些字节如何存储到内存中(例如:通过mov 指令)。字节序决定了这一点。对于 little-endian 机器,寄存器的最低字节将放置在目标操作数的最低地址,对于 big-endian 机器在最高地址。字节顺序与将内存操作数加载到寄存器中类似。

简而言之,为了谈论字节序,在字节的重要性和它们对应的高度之间必须存在一种映射地址。

【讨论】:

  • 寄存器有左移和右移。右移将位从更重要的位置带到不太重要的位置。正如您所说,这完全独立于它们在内存中的加扰方式,而不是字节序。它是一个位顺序,并且始终是左侧的 MSB,右侧的 LSB,根据左移和右移的定义。移位如何跨元素边界(pslld xmm0, 8 / psldq xmm0, 1)或跨子寄存器(shl eax, 8 设置 AH=AL 和 AL=0)定义它们之间的关系。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-16
  • 2022-01-02
  • 1970-01-01
  • 1970-01-01
  • 2013-11-11
相关资源
最近更新 更多