我正在阅读计算机系统:程序员的视角作业是描述这个算法是如何工作的。
C函数:
void store_prod(__int128 *dest, int64_t x, int64_t y) {
*dest = x * (__int128)y;
}
集会:
movq %rdx, %rax
cqto
movq %rsi, %rcx
sarq $63, %rcx
imulq %rax, %rcx
imulq %rsi, %rdx
addq %rdx, %rcx
mulq %rsi
addq %rcx, %rdx
movq %rax, (%rdi)
movq %rdx, 8(%rdi)
ret
我不知道为什么它会执行:xh * yl + yh * xl = value which we add after unsigned multiplication
一如既往,编译器选项很重要。该源代码与gcc -Og
(针对调试进行优化)生成与您的清单非常相似的 asm(在进行完整的 128x128 => 128 位乘法之前,强制转换将两个操作数符号扩展为 128 位)。这是 C 标准所说应该发生的事情的简单实现(用于将两个操作数转换为相同类型的整数优先规则)。
如果您要谈论编译器输出,您应该始终说明哪个版本的哪个编译器以及哪个选项。或者只是发布一个链接到godbolt,就像上面那个一样。 (编辑:哎呀,源代码和 asm 来自一本没有提供该信息的书。如果那是 CS:APP 3e 的全球版本,请注意练习题充满了错误在全球版中。)
With gcc -O3
or -O2
,GCC 利用了两个操作数实际上仍然只有 64 位的事实,所以单个imul足够。 (这仍然为每个输入产生相同的结果,因此仍然按照 as-if 规则实现 C 逻辑。C 没有扩展操作,因此您被迫以“低效”方式编写源代码,这取决于编译器将其转换为高效的 asm。)
The sar $63, %rcx
是符号扩展的一部分rsi
into rcx:rsi
, 就像cqto
符号扩展rax
into rdx:rax
。它用原始符号位的副本替换 RCX 的每一位。
这个答案的大部分已经由其他人在评论中给出,但我认为其他人没有注意到这一点gcc -Og
/ -O1
几乎完全给出了 asm 输出。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)