我一直在阅读div
和mul
汇编操作,我决定通过用C编写一个简单程序来看到它们的作用:
文件分割
#include <stdlib.h>
#include <stdio.h>
int main()
{
size_t i = 9;
size_t j = i / 5;
printf("%zu\n",j);
return 0;
}
然后使用以下命令生成汇编语言代码:
gcc -S division.c -O0 -masm=intel
但是查看生成的division.s
文件,它不包含任何div操作!取而代之的是,它执行某种带有移位和魔术数字的黑魔法。这是一个计算的代码片段i/5
:
mov rax, QWORD PTR [rbp-16] ; Move i (=9) to RAX
movabs rdx, -3689348814741910323 ; Move some magic number to RDX (?)
mul rdx ; Multiply 9 by magic number
mov rax, rdx ; Take only the upper 64 bits of the result
shr rax, 2 ; Shift these bits 2 places to the right (?)
mov QWORD PTR [rbp-8], rax ; Magically, RAX contains 9/5=1 now,
; so we can assign it to j
这里发生了什么?为什么GCC根本不使用div?它是如何产生这个幻数的?为什么一切正常?
-3689348814741910323
转换CCCCCCCCCCCCCCCD
为a uint64_t
或约为(2 ^ 64)* 4/5。
div
指令-O0
。(抄送@悬崖)