Interesting Arithmetic Assembly Sequences
Microsoft Visual C Compiler generates some interesting assembly instructions for common operations such as multiplication with, taking remainder and quotient by constants, especially powers of 2.
All examples below use signed integers.
Multiplication with a power of 2
We all know shl is normally used to multiply a number with a power of 2. This sequence uses lea instruction instead.
The ASM code
mov eax, DWORD PTR _a$[esp+52] ; eax takes value of a lea ecx, DWORD PTR [eax*8] ; ecx takes value of a * 8
The C code
a * 8;
Multiplication with a constant
The compiler will try to fit the multiplication with lea and add instructions.
The ASM code
mov eax, DWORD PTR _a$[esp+28] ; eax takes value of a lea ecx, DWORD PTR [eax+eax*2] ; ecx = eax * 3 add ecx, ecx ; ecx = ecx * 2 (or, eax * 6)
The C code
a * 6;
Taking quotient of a division by a power of 2
This sequence is interesting because there is a conditional jump jns instruction.
The ASM code
mov edx, DWORD PTR _a$[esp+36] and edx, -2147483641 ; 80000007H jns SHORT $LN3@main dec edx or edx, -8 ; fffffff8H inc edx $LN3@main: ; here edx takes the value of the quotient
The C code
a % 8;
Taking remainder of a division by a power of 2
There is only one shift instruction sar in this sequence.
The ASM code
mov eax, DWORD PTR _a$[esp+44] cdq and edx, 7 add eax, edx sar eax, 3 ; here eax takes the value of the remainder
The C code
a / 8;
Taking remainder of a division by a constant
Notice that 2aaaaaabH is 2^32 / 6.
The ASM code
mov ecx, DWORD PTR _c$[esp+20] mov eax, 715827883 ; 2aaaaaabH imul ecx mov eax, edx shr eax, 31 ; 0000001fH add eax, edx
The C code
c / 6
Taking quotient of a division by a constant
First, take the remainder. Then substract the original value with the multiplication of remainder and constant.
The ASM code
mov ecx, DWORD PTR _c$[esp+12] mov eax, 715827883 ; 2aaaaaabH imul ecx mov eax, edx shr eax, 31 ; 0000001fH add eax, edx lea edx, DWORD PTR [eax+eax*2] add edx, edx sub ecx, edx
The C code
c % 6