为什么汇编等同于此 C 代码?

why is the assembly equivalent of this C code, as such?

我正在使用这本 Randal E. Bryant、David R. O'Hallaron - Computer Systems 教科书。程序员的视角 [第 3 版](2016 年,Pearson)。对于这个问题 3.43 我不知道为什么 一些问题会产生一个汇编代码,如给定答案所示。

首先,我不确定为什么 &up->t1.wmovw 之前加了 10。

其次,当前两个示例要求我们执行以下操作时,我不确定为什么 up->t2.a 在汇编中只产生一行:

movq (%rdi), %rax
movq %rax, (%rsi)

有什么变化?

第三,up->t2.a[up->t1.u] 行的类似混淆被翻译成这样:

movq (%rdi), %rax
movl (%rdi,%rax,4), %eax
movl %eax, (%rsi)

感谢任何帮助,谢谢!

What changed?

a只是一个指针; rdi可以直接写入rsi中的地址:

mov    QWORD PTR [rsi],rdi

u 是一个值,它在内存中,因为它是一个结构成员。这需要一个加载和一个存储,x86 can't do with a single mov;必须涉及寄存器。这里 rax 是一个 tmp 变量:

mov    rax,QWORD PTR [rdi]
mov    QWORD PTR [rsi],rax

这相当于一个假设:

mov    QWORD PTR [rsi], QWORD PTR [rdi]   !!! NOT encodeable into machine code

更复杂的寻址方式:

这是Base-Scale/Index-Displacement

movl (%rdi,%rax,4), ...

rdi为基加上4*rax作为偏移量,或者在C语法中:int rdi[rax]。在 Intel 语法 asm 中,它看起来像这样(因为 asm 使用字节偏移量,没有按操作数大小进行隐式缩放):

mov  ..., [rdi + rax*4]

遗憾的是,AT&T 和 Intel 语法看起来非常不同...我更喜欢显式 xWORD PTR [] 和从右到左。

这是 int 数组的 get():

void get_a(u_type *up, int **dest) {
    *dest = up->t2.a;
}

真的只是强制复制一个(数组)指针。