The MASM Forum

General => The Campus => Topic started by: Farmek on April 12, 2013, 06:33:11 AM

Title: modulo
Post by: Farmek on April 12, 2013, 06:33:11 AM
Hello, i need to know how to use modulo in assembly. I need to be able to see if the number is a odd number or a even number. It would be nice if a could get an example of that too :)
Title: Re: modulo
Post by: qWord on April 12, 2013, 06:38:14 AM
Quote from: Farmek on April 12, 2013, 06:33:11 AMI need to be able to see if the number is a odd number or a even number.
assuming integers, you need only to test the least significant bit:
mov eax,value
test eax,1
jz @even
jnz @odd

;---

;MASM's HLL construct:
.if value & 1
    ; odd
.else
    ; even
.endif
Title: Re: modulo
Post by: Gunther on April 12, 2013, 06:50:15 AM
Hi Farmek,

first things first: Welcome to the forum.

I think qWord gave the right answer. Another way is to use the normal division. From the Intel® 64 and IA-32 Architectures Software Developer's Manual Volume 2A: Instruction Set Reference, A-L, p. 278:
Quote
Operand Size                 Dividend   Divisor  Quotient  Remainder  Maximum Quotient
Quadword/doubleword     EDX:EAX    r/m32   EAX         EDX            232 − 1

Gunther
Title: Re: modulo
Post by: FORTRANS on April 12, 2013, 07:38:55 AM
Quote from: Farmek on April 12, 2013, 06:33:11 AM
Hello, i need to know how to use modulo in assembly. I need to be able to see if the number is a odd number or a even number. It would be nice if a could get an example of that too :)

Hi,

   qWord showed the normal way to do it.  If I take your
statement literally, then you would test a number for odd or
even by dividing by two, and checking for a remainder.  The
remainder is the number modulo the divisor.  That is more
work though.


OddNum  DD      4321
EvenNum DD      1234
Two     DD      2

        MOV     EDX,0
        MOV     EAX,[OddNum]    ; Or EvenNum...
        DIV     [Two]
        TEST    EDX,0FFFFH      ; Or 1 will work just as well.
        JNZ     ODD
; Else even.


HTH,

Steve N.
Title: Re: modulo
Post by: dedndave on April 12, 2013, 11:33:34 AM
the DIV instruction is often said to calculate a "quotient"  and a "remainder" from a "dividend" and a "divisor"
in fact, it calculates a "quotient" (sometimes called a "partial quotient") and a "modulus"
the actual "remainder" would be the modulus divided by the divisor

dividend/divisor = quotient = partial quotient + remainder = partial quotient + modulus/divisor

one interesting use of a modulus function might be to calculate the day of the week   :P
Title: Re: modulo
Post by: guga on May 14, 2020, 01:02:48 AM
Old Topic, but how to implement a modulo in MMX and SSE ?

Say, how to compute modulo 2 of something ?

Ex:

((x/2^n) mod 2) as described here: https://en.wikipedia.org/wiki/Bitwise_operation
Title: Re: modulo
Post by: raymond on May 14, 2020, 03:32:53 AM
Quote from: Farmek on April 12, 2013, 06:33:11 AM
Hello, i need to know how to use modulo in assembly. I need to be able to see if the number is a odd number or a even number. It would be nice if a could get an example of that too :)

Welcome to this forum Farmek.

qWord's answer to your odd/even question (testing the least significant bit) is the most used and fastest way to do it without destroying any data. If the number to be tested would be of no further value (or its half value could be used), another option would be:
  mov eax,value
  shr eax,1  ;transfers the least significant bit to the CARRY flag
             ;and leaves the half value in eax
  jc odd
  jnc even

odd:
  ...

even:
  ...


The "modulo" is not as straight forward. Its meaning in most (if not all) programming languages is the residue of dividing an integer by another integer. For example, dividing 20 by 11 would give a quotient of  1 and a remainder of 9; thus, 20 mod 11 = 9.

The problem with HLLs  is that the compiler never considers how much larger the original number may be compared to the modulus, and would automatically generate code to perform a division whenever the programmer calls for a mod operation. Unfortunately, the programmer himself may never consider any other option!!

As you can see with the above example, the same answer could be obtained using a simple subtraction. If you only have one of those to do, the timing required to perform the operation would not matter. However, if you have billions of them to do in a loop, it could matter.

According to available data, a division instruction would require 40 clock cycles while a compare or subtraction instruction only needs 1 clock cycle (if no fetching of data from memory is required).

But, if you don't know the extent of the number to be "mod'ed", you don't really have any option but to perform a division (much faster than 100's or more subtractions). And, here again, several precautions need to be taken in assembly to prevent your algo from crashing when coding a division. If you are not familiar with the requirements of assembly instructions, I would recommend reading instructional material.

As a side note, I recently came across a problem where integers resulting from the sum of at most three integers already lower than the modulus needed to be processed. Using subtractions, I could run a loop containing three of those operations 500,000,000 times in about 10 seconds on my old desktop.

Title: Re: modulo
Post by: mineiro on May 14, 2020, 06:09:21 AM
If the divisor is a multiple of 2 (4,8,16,32,64,...), masks can be used:
and reg,1  ;(1h)
jz even
odd:
You are looking for the rightmost bit whether zero or one if dividing by 2.

If it's the remainder of the division by 4, then the mask will be:
and reg,11b  ;(3h)
;reg = remainder of number divided by 4

remainder of the division by 8 the mask will be 111b  ;(7h)
remainder of the division by 16 the mask will be 1111b  ;(15h)
Usually the mask is a multiple of 2 minus 1, if and only if the divisor is a multiple of 2.