Nehmen wir gleich das konkrete Beispiel von SirP. Wir wollen also eine Zahl mit 320 multiplizieren:
|
C-/C++-Quelltext
|
1
2
3
4
5
6
7
8
9
|
#include <iostream>
int main()
{
int x;
std::cin >> x;
return x * 320;
}
|
MSVC 10 generiert für das return folgenden Code:
|
Quellcode
|
1
2
|
lea eax, [eax + eax * 4]
shl eax, 6
|
Der Compiler verwendet hier tatsächlich das selbe Prinzip auf dem auch die Lösung von SirP basiert (nämlich der Tatsache dass
§x \cdot 320 = x \cdot 256 + x \cdot 64 = x \cdot 2^8 + x \cdot 2^6§). Anstatt aber mit Shifts und Multiplikationen zu rechnen, bedient sich der Compiler über die Instruction lea spezieller Hardware, die eigentlich für die Berechnung von Speicheradressen gedacht ist, in dem Fall aber auch für unsere Multiplikation zweckentfremdet werden kann und dabei schneller ist als eine explizite Addition gefolgt von einem Bitshift. Hätten wir von Hand "optimiert", wäre nun nicht nur der Code sehr viel schlechter lesbar, sondern der Compiler hätte möglicherweise sogar schlechteren Maschinencode erzeugt. Ein moderner Compiler wie MSVC 10 ist allerdings sogar so schlau zu erkennen, dass er (x << 8 ) + (x << 6) in (x + (x << 2)) << 6 umwandeln kann, sodass beide Lösungen hier identischen Maschinencode produzieren...