【发布时间】:2017-05-12 02:09:12
【问题描述】:
是否有显示/写入大型寄存器的约定,例如英特尔 AVX 指令集中可用的那些?
例如,如果最低有效字节为 1,最高有效字节为 20,xmm 寄存器中的其他位置为 0,则按字节显示是以下首选(小端序):
[1, 0, 0, 0, ..., 0, 20]
或者这是首选:
[20, 0, 0, 0, ..., 0, 1]
同样,当显示由较大数据项组成的寄存器时,是否应用相同的规则?例如,要将寄存器显示为 DWORD,我假设每个 DWORD 仍然以通常的(大端)方式写入,但是 DWORD 的顺序是什么:
[0x1, 0x0, ..., 0x14]
对
[0x14, 0x0, ..., 0x1]
讨论
我认为两个最有希望的答案只是“LSE1 first”(即上面示例中的第一个输出)或“MSE first”(第二个输出)。两者都不依赖于平台的字节序,因为确实在寄存器中的数据通常是字节序独立的(就像对 GP 寄存器或 long 或 int 或 C 中的任何内容的操作都独立于字节序)。字节序出现在寄存器 内存接口中,这里我询问的是寄存器中已经存在的数据。
可能存在其他答案,例如取决于字节序的输出(Paul R 的答案可能是一个,但我不知道)。
伦敦证券交易所第一
LSE-first 的一个优势似乎特别是字节输出:通常字节从 0 到 N 编号,LSB 为零2,因此 LSB-first 输出输出它随着索引的增加,就像你输出一个大小为 N 的字节数组一样。
它在小端架构上也很不错,因为输出与存储到内存中的同一向量的内存表示相匹配。
MSE 优先
这里的主要优势似乎是较小元素的输出与较大尺寸的输出顺序相同(仅具有不同的分组)。例如,对于 MSB 表示法 [0x4, 0x3, 0x2, 0x1] 的 4 字节向量,字节元素、字和双字元素的输出将是:
[0x4, 0x3, 0x2, 0x1] [0x0403,0x0201] [0x04030201]
基本上,即使从字节输出中,您也可以“读取”字或双字输出,反之亦然,因为字节已经按照通常的 MSB 优先顺序进行数字显示。另一方面,LSE-first 的相应输出是:
[0x1, 0x2, 0x3, 0x4] [ 0x0201 , 0x0403 ] [0x04030201]
请注意,每一层都会相对于它上面的行进行交换,因此读取更大或更小的值要困难得多。您需要更多地依赖输出最适合您的问题的元素。
这种格式还具有优势,即在 BE 架构上,输出与存储到内存中的同一向量的内存表示相匹配3。
英特尔在其手册中首先使用 MSE。
1 最不重要的元素
2 这样的编号不仅仅用于文档目的 - 它们在架构上是可见的,例如,在随机掩码中。
3 当然,与 LSE-first 在 LE 平台上的相应优势相比,这种优势是微不足道的,因为 BE 在商品 SIMD 硬件中几乎已死。
【问题讨论】:
-
我个人的看法是我更喜欢little-endian表示,但我不知道标准约定,这个问题似乎相当“基于意见”。我想许多调试器会使其成为一个可配置的选项,就像在显示字节大小的值、DWORD 大小的值、双精度值等之间切换的能力一样。
-
我的经验法则是:匹配内存中的等效布局,所以如果内存中有
0x1 0x2 0x3 ... 0xf,并且将其加载到向量寄存器,那么显示向量寄存器的内容也应该看起来像0x1 0x2 0x3 ... 0xf。 -
@PaulR 我很确定你会得到
0xf ... 0x3 0x2 0x1的内存布局:D -
@MargaretBloom:好吧,如果您使用某些编译器(例如Apple的gcc和clang)支持的
%v格式扩展printf,那么这就是您得到的行为,我发现它很有帮助,因为您几乎可以忘记小端序的变幻莫测。 -
@CodyGray - 如果它是“什么是代表......的最佳方式”,那将纯粹是基于意见 - 但在这里我只是问是否存在现有约定,所以我可以遵循它:是/否问题,原则上可以根据现有事实回答。当然,对于需要多少现有行为才能将其声明为约定,或者应该由谁来定义约定,意见可能会有所不同——但当然,几乎所有问题都需要在这些方面进行一定程度的判断。