c++ - 为什么会发出如此复杂的代码来将有符号整数除以 2 的幂?

标签 c++ visual-c++ assembly x86 division

当我用 VC++10 编译这段代码时:

DWORD ran = rand();
return ran / 4096;

我得到了这个反汇编:

299: {
300:    DWORD ran = rand();
  00403940  call        dword ptr [__imp__rand (4050C0h)]  
301:    return ran / 4096;
  00403946  shr         eax,0Ch  
302: }
  00403949  ret

简洁明了,用逻辑右移代替了除以 2 的幂。

当我编译这段代码时:

int ran = rand();
return ran / 4096;

我得到了这个反汇编:

299: {
300:    int ran = rand();
  00403940  call        dword ptr [__imp__rand (4050C0h)]  
301:    return ran / 4096;
  00403946  cdq  
  00403947  and         edx,0FFFh  
  0040394D  add         eax,edx  
  0040394F  sar         eax,0Ch  
302: }
  00403952  ret

在进行算术右移之前执行一些操作。

这些额外的操作需要什么?为什么算术移位还不够?

最佳答案

原因是无符号除以 2^n 可以非常简单地实现,而有符号除则稍微复杂一些。

unsigned int u;
int v;

u / 4096相当于 u >> 12对于 u 的所有可能值.

v / 4096 等于v >> 12 - 它在 v < 0 时崩溃,因为当涉及负数时,移位和除法的舍入方向不同。

关于c++ - 为什么会发出如此复杂的代码来将有符号整数除以 2 的幂?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12692111/

相关文章:

assembly - 为什么RISC指令集通常不包含寄存器到寄存器复制指令?

c++ - 如何使用Qt建立命令窗口?

c++ - 使用 D3D12Device 调用 DuplicateOutput 失败并出现 E_NOINTERFACE

c++ - Flag 检查编译器是 gcc/mingw 还是 VC++ cl?

c++ - 无法使用嵌套的 lambda 捕获静态成员

c - 编译C文件时出现Unsupported x86-64 instruction set错误

macos - 用户输入和输出在我的汇编代码中不起作用

c++ - 计算一个非常大的矩阵的逆

c++ - 使用 this-> 访问成员是否有任何开销?

c - fopen 在尝试打开 bmp 文件(C++)时返回 NULL?