Assembly Language Help (alang.hlp) (Table of Contents; Topic list)
Important Notice
The pages on this site contain documentation for very old MS-DOS software, purely for historical purposes. If you're looking for up-to-date documentation, particularly for programming, you should not rely on the information found here, as it will be woefully out of date.
IMulLong
 Map                                       Up Contents Index Back
────────────────────────────────────────────────────────────────────────────
 
;* ImulLong - Multiplies two signed double-word integers. Because the imul
;* instruction (illustrated here) treats each word as a signed number, its
;* use is impractical when multiplying multi-word values. Thus the technique
;* used in the MulLong procedure can't be adopted here. Instead, ImulLong
;* is broken into three sections arranged in ascending order of computational
;* overhead. The procedure tests the values of the two integers and selects
;* the section that involves the minimum required effort to multiply them.
;*
;* Shows:   Instruction - imul
;*
;* Params:  Long1 - First integer (multiplicand)
;*          Long2 - Second integer (multiplier)
;*
;* Return:  Result as long integer
 
ImulLong PROC USES si,
        Long1:SDWORD, Long2:SDWORD
 
; Section 1 tests for integers in the range of 0 to 65,535. If both
; numbers are within these limits, they're treated as unsigned short
; integers.
 
        mov     ax, WORD PTR Long2[0]   ; AX = low word of long2
        mov     dx, WORD PTR Long2[2]   ; DX = high word of long2
        mov     bx, WORD PTR Long1[0]   ; BX = low word of long1
        mov     cx, WORD PTR Long1[2]   ; CX = high word of long1
        .IF     (dx == 0) && (cx == 0)  ; If both high words are zero:
        mul     bx                      ;   Multiply the low words
        jmp     exit                    ;   and exit section 1
        .ENDIF
 
; Section 2 tests for integers in the range of -32,768 to 32,767. If
; both numbers are within these limits, they're treated as signed short
; integers.
 
        push    ax                      ; Save long2 low word
        push    bx                      ; Save long1 low word
        or      dx, dx                  ; High word of long2 = 0?
        jnz     notzhi2                 ; No?  Test for negative
        test    ah, 80h                 ; Low word of long2 in range?
        jz      notnlo2                 ; Yes?  long2 ok, so test long1
        jmp     sect3                   ; No?  Go to section 3
notzhi2:
        cmp     dx, 0FFFFh              ; Empty with sign flag set?
        jne     sect3                   ; No?  Go to section 3
        test    ah, 80h                 ; High bit set in low word?
        jz      sect3                   ; No?  Low word is too high
notnlo2:
        or      cx, cx                  ; High word of long1 = 0?
        jnz     notzhi1                 ; No?  Test for negative
        test    bh, 80h                 ; Low word of long1 in range?
        jz      notnlo1                 ; Yes?  long1 ok, so use sect 2
        jmp     sect3                   ; No?  Go to section 3
notzhi1:
        cmp     cx, 0FFFFh              ; Empty with sign flag set?
        jne     sect3                   ; No?  Go to section 3
        test    bh, 80h                 ; High bit set in low word?
        jz      sect3                   ; No?  Low word is too high
notnlo1:
        imul    bx                      ; Multiply low words
        pop     bx                      ; Clean stack
        pop     bx
        jmp     exit                    ; Exit section 2
 
; Section 3 involves the most computational overhead. It treats the two
; numbers as signed long (double-word) integers.
 
sect3:
        pop     bx                      ; Recover long1 low word
        pop     ax                      ; Recover long2 low word
        mov     si, dx                  ; SI = long2 high word
        push    ax                      ; Save long2 low word
        mul     cx                      ; long1 high word x long2 low word
        mov     cx, ax                  ; Accumulate products in CX
        mov     ax, bx                  ; AX = low word of long1
        mul     si                      ; Multiply by long2 high word
        add     cx, ax                  ; Add to previous product
        pop     ax                      ; Recover long2 low word
        mul     bx                      ; Multiply by long1 low word
        add     dx, cx                  ; Add to product high word
exit:
        ret                             ; Return result as DX:AX
 
ImulLong ENDP
                                    -♦-