今天調(diào)試一個(gè)程序時(shí)遇到了一段奇怪的匯編代碼
mov eax, 68DB8BADh
push edi
movsx ecx, word ptr [esi+0Eh]
imul ecx
sar edx, 0Ch
mov eax, edx
shr eax, 1Fh
add edx, eax
看了半天也沒看明白,主要是這個(gè)68DB8BADh出現(xiàn)的很突兀,與前后代碼在邏輯上都不相關(guān)聯(lián)。到網(wǎng)上搜了下,還居然找到了答案。原來這是一段編譯器將除法優(yōu)化為乘法運(yùn)算的典型代碼。眾所周知,除法是最耗CPU的,能夠轉(zhuǎn)化為等效的乘法就要快得多了。但不是每次除法都能這么優(yōu)化的。對于一些特定數(shù)作為被除數(shù)時(shí),這種優(yōu)化還是很有效的。
http://www.thesolver.it/Manuali/Factotum/source/076.htm這里列出了一些典型數(shù)的除法轉(zhuǎn)換表。

這個(gè)表是32位運(yùn)算下除法轉(zhuǎn)換為乘法的一些案例。比如68DB8BADh這個(gè)魔術(shù)數(shù)就是用來轉(zhuǎn)換除以625的。要計(jì)算x/625 = (x * 68DB8BADh) >>8.所以上面的代碼其實(shí)就是計(jì)算[esi +0Eh] / 10000.
下面這個(gè)表是64位運(yùn)算時(shí)除法轉(zhuǎn)換為乘法的一些魔術(shù)數(shù),摘錄在此,以防備忘

如果想搞清楚相關(guān)的運(yùn)算原理可以看該網(wǎng)站的
Chapter 10. Integer Division by Constants ,網(wǎng)址是
http://www.thesolver.it/Manuali/Factotum/source/062.htm大家也可以自己編一段小程序驗(yàn)證一下。
1 #include <stdio.h>
2
3 int main(int argc, char* argv[])
4 {
5 int a = getchar();
6 int b = a / 10000;
7 printf("a=%d\nb=a/10000=%d\n", a, b);
8 return 0;
9 }
10
在VC2008下設(shè)置項(xiàng)目編譯屬性Assembler Output,選擇輸出匯編代碼,看看編譯出來的代碼與上面的完全一致。