请注意,以下内容改编自 Bryant 和 O'Hallaron 的文本 (CSAPP3e) 的问题 3.4。除了我的基本问题之外,我已经删除了所有内容。
上下文:我们正在研究 x86-64/Linux/gcc 组合,其中
int
是 4 字节,char
被视为有符号(当然,1 字节)。我们有兴趣编写与 int 到 char 的转换相对应的程序集,在较高的层次上,我们知道这是由于执行截断而产生的。
他们提出了以下解决方案:
movl (%rdi), %eax // Read 4 bytes
movb %al, (%rsi) // Store low-order byte
我的问题是我们是否可以将
movl
更改为movb
,因为毕竟我们最终只使用了一个字节。我对这种怀疑的担忧是,读取可能存在一些字节序依赖性,如果我们的处理器/操作系统处于小字节序模式,我们可能会以某种方式获得高位。这种怀疑是否正确,或者无论如何我的改变都会起作用?
我会尝试一下,但是 1)我使用的是带有 Apple 芯片的 Mac,2)即使我的怀疑有效,我也无法确定这种事情是否依赖于实现。
您担心这种操作的字节序是正确的,但在这种情况下,您的替代方法将在 big-endian 机器上失败,而不是在 Little-endian 机器上失败。
x86 是小端字节序,这意味着 32 位整数的低位 8 位存储在该整数的 first(最低地址)字节中,因此
movb (%rdi), %al // Read low-order byte
movb %al, (%rsi) // Store low-order byte
将执行您想要在 x86 上执行的截断。 但在大端机器上,等效操作将读取 32 位整数的“最高”八位。 (我想举一个例子,但我不记得任何大端架构的汇编语言了,无法再喋喋不休了。) 按照 CS:APP 的方式进行操作的优点是,相同的构造可以在
big-endian 和 Little-endian 架构上正确工作。 当然,如果您使用汇编语言进行编程,您就必须重写代码无论如何,但这样做时需要担心的事情就少了。