askvity

What is Modulo in Assembly?

Published in Assembly Arithmetic 4 mins read

In assembly language, "modulo" refers to the operation of finding the remainder after performing integer division. It's a fundamental arithmetic concept utilized for various tasks.

Modulo, as an operation, is defined as follows: The modulo operator divides the value of operand1 by the value of operand2 and returns the remainder after the division. Both operands must be absolute. The result is absolute.

Unlike many high-level programming languages which might have a dedicated modulo operator (like % in C/C++ or Java), assembly languages typically calculate the remainder as a byproduct of their standard integer division instructions.

How Modulo Works in Assembly

Assembly language instructions for division usually compute both the quotient (the result of the division) and the remainder. The remainder is the value you are interested in when performing a modulo operation.

For example, in x86 assembly:

  • Integer division instructions like DIV (unsigned division) or IDIV (signed division) operate on specific registers.
  • Before division, the dividend is placed in one or more registers (e.g., AX for 16-bit, DX:AX for 32-bit/16-bit, EAX for 32-bit, EDX:EAX for 64-bit/32-bit).
  • The divisor is specified as an operand to the instruction (e.g., another register or memory location).
  • After the division, the quotient is stored in one register (e.g., AL/AX/EAX), and the remainder is stored in another register (e.g., AH/DX/EDX).

The value found in the remainder register after a division operation is the result of the modulo operation.

Illustrating Division and Remainder

Consider the operation 17 modulo 5.
In division form: 17 / 5.

Dividend Divisor Quotient Remainder Modulo Result
17 5 3 2 2

In assembly, after performing the division of 17 by 5, the register holding the remainder would contain the value 2.

Practical Uses of Modulo in Assembly

Modulo operations are surprisingly useful in low-level programming:

  • Checking Parity: Determining if a number is even or odd by checking if number modulo 2 is 0 or 1.
  • Cyclic Operations: Implementing operations that wrap around, like indexing circular buffers or managing fixed-size queues. For instance, index = (index + 1) modulo buffer_size.
  • Hashing: Used in hash functions to map data to indices within a fixed-size array or hash table.
  • Number Base Conversion: Extracting digits when converting a number to a different base (e.g., binary, hexadecimal).

Example Snippet (Conceptual x86)

This is a conceptual example to illustrate how remainder is obtained; actual register usage depends on size (8-bit, 16-bit, 32-bit, 64-bit).

; Assume we want to calculate 17 modulo 5
; Using 16-bit registers for simplicity (dividend in AX, remainder in DX)

mov ax, 17   ; Load dividend into AX
mov bl, 5    ; Load divisor into BL (lower 8 bits of BX)
mov dx, 0    ; Clear DX (required for 32-bit dividend in DX:AX, good practice)

div bl       ; Divide AX by BL.
             ; Quotient stored in AL (AX's lower 8 bits)
             ; Remainder stored in AH (AX's upper 8 bits)

; The remainder is now in AH.
; If using 32-bit division (IDIV ebx), remainder would be in EDX.

In this 16-bit example using div bl, the quotient (3) would be in AL, and the remainder (2) would be in AH. If using a larger division like div bx (AX / BX -> AL=quotient, AH=remainder) or div ebx (EDX:EAX / EBX -> EAX=quotient, EDX=remainder), the remainder would end up in a different register according to the architecture's specification.

Essentially, to get the modulo result in assembly, you perform a division and then retrieve the value from the designated remainder register.

Related Articles