ℹ️ Select 'Choose Exercise', or randomize 'Next Random Exercise' in selected language.

Choose Exercise:
Timer 00:00
WPM --
Score --
Acc --
Correct chars --

ASM x86 Integer Arithmetic: Optimized Division by Constant

ASM x86

Goal -- WPM

Ready
Exercise Algorithm Area
1; Optimized Integer Division by a Constant (Unsigned)
2; Divides a 64-bit unsigned integer by a constant unsigned divisor.
3; Uses multiplication and bit shifts for performance.
4
5section .data
6; Constant divisor
7divisor dq 7
8
9section .text
10global _start
11
12_start:
13; Example usage: divide 100 by 7
14mov rax, 100
15call divide_by_7_unsigned
16; Result (quotient) is in RAX
17; Remainder is in RDX (if needed, not explicitly calculated here)
18
19; Example usage: divide 0 by 7
20mov rax, 0
21call divide_by_7_unsigned
22
23; Example usage: divide 6 by 7
24mov rax, 6
25call divide_by_7_unsigned
26
27; Example usage: divide 7 by 7
28mov rax, 7
29call divide_by_7_unsigned
30
31; Example usage: divide 13 by 7
32mov rax, 13
33call divide_by_7_unsigned
34
35; Exit program
36mov rax, 60
37mov rdi, 0
38syscall
39
40; Function: divide_by_7_unsigned
41; Divides a 64-bit unsigned integer in RAX by the constant 7.
42; Uses the "magic number" method for division by constant.
43; Input: RAX = dividend (unsigned 64-bit)
44; Output: RAX = quotient (unsigned 64-bit)
45; RDX = remainder (unsigned 64-bit) - implicitly available from DIV
46divide_by_7_unsigned:
47; Magic number for division by 7 (unsigned 64-bit)
48; For divisor D, we need M and S such that N/D = (N*M) >> S.
49; For D=7, M=3067798037041714032 (0x2A05F200674A4500), S=3
50; This magic number is pre-calculated.
51mov rbx, 0x2A05F200674A4500 ; Magic number M
52mov rcx, 3 ; Shift amount S
53
54; Perform multiplication: N * M
55mov rdx, rax ; Copy dividend to RDX for multiplication
56mul rbx ; RAX = N * M (high part in RDX, low part in RAX)
57; The full 128-bit product is in RDX:RAX
58
59; Shift right by S bits
60shr rdx, cl ; Shift RDX by S bits (cl holds S)
61; The quotient is approximately RDX >> S
62; For unsigned division, the quotient is (N * M) >> S.
63; The exact quotient requires further adjustment based on the remainder.
64; However, for many compilers, this is sufficient for unsigned division.
65; A more precise method involves checking the remainder.
66; For simplicity, we'll use the direct shift result.
67
68; The result of (N * M) >> S is the quotient.
69; The remainder can be calculated as N - quotient * D.
70; For this drill, we focus on the quotient calculation.
71
72; The result is in RDX after the shift.
73; Let's move it to RAX for the return value.
74mov rax, rdx
75
76; To get the remainder, we'd typically do:
77; mov rbx, rax ; quotient
78; mov rcx, 7 ; divisor
79; mul rcx ; product of quotient and divisor
80; sub original_dividend, product ; remainder
81; But this function only returns the quotient.
82
83ret
Algorithm description viewbox

ASM x86 Integer Arithmetic: Optimized Division by Constant

Algorithm description:

This ASM x86 code implements an optimized unsigned integer division by a constant (7) using the 'magic number' method. Instead of a slow division instruction, it performs a multiplication by a pre-calculated magic number and a right bit shift. This technique is commonly used by compilers to speed up division operations when the divisor is a compile-time constant.

Algorithm explanation:

The function `divide_by_7_unsigned` aims to compute `dividend / 7` without using the `DIV` instruction. It leverages the property that for a constant divisor `D`, there exist a multiplier `M` and a shift amount `S` such that `N / D ≈ (N * M) >> S`. The magic number `M = 0x2A05F200674A4500` and shift `S = 3` are pre-calculated for `D = 7`. The algorithm multiplies the dividend (`RAX`) by `M`, resulting in a 128-bit product in `RDX:RAX`. The higher 64 bits (`RDX`) are then right-shifted by `S` bits. This shifted value is a good approximation of the quotient. For unsigned division, this approximation is often sufficient or can be adjusted with a few extra checks. The time complexity is O(1) as it involves a fixed number of arithmetic operations, significantly faster than the O(log N) of a typical division instruction.

Pseudocode:

FUNCTION divide_by_7_unsigned(dividend):
  magic_number = 0x2A05F200674A4500
  shift_amount = 3

  product_high, product_low = dividend * magic_number
  quotient = product_high >> shift_amount

  RETURN quotient