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
-♦-