; this one adapted from elks, http://elks.sourceforge.net ; multiply cx:bx * dx:ax, result in dx:ax %macro LMULU 0 push si push cx mov si, ax ; save _ax in si mov ax, bx ; cx:ax = _cx:_bx mul dx ; dx:ax = _bx*_dx (forget dx) xchg cx, ax ; cx = low(_dx*_bx) mul si ; dx:ax = _cx*_ax (forget dx) add cx, ax ; cx = low(_cx*_ax + _dx*_bx) mov ax, si ; restore _ax mul bx ; dx:ax = _bx*_ax add dx, cx ; dx = high(_bx*_ax)+low(_cx*_ax + _dx*_bx) pop cx pop si ret %endmacro ; divide dx:ax / cx:bx, quotient in dx:ax, remainder in cx:bx %macro LDIVMODU 0 ; this one is adapted from an assembly gem: ; gem writer: Norbert Juffa, norbert.juffa@amd.com ; Dividing 64-bit unsigned integers Assembler / 80386 ; Here is a division routine for dividing two 64-bit unsigned integers. ; I derived it by modifying some old ; 16-bit code for dividing 32-bit integers that I did several years ago for a ; Turbo-Pascal replacement library. ; If a 64-bit signed integer division is needed, appropriate shell code for ; this routine can easily be written. ; ; (adapted back to 32-bit by Bart Oldeman ;-)) ; ; __U4D divides two unsigned long numbers, the dividend and the divisor ; resulting in a quotient and a remainder. ; ; input: ; dx:ax = dividend ; cx:bx = divisor ; ; output: ; dx:ax = quotient of division of dividend by divisor ; cx:bx = remainder of division of dividend by divisor ; ; destroys: ; flags ; test cx, cx ; divisor > 2^32-1 ? jnz %%big_divisor ; yes, divisor > 32^32-1 cmp dx, bx ; only one division needed ? (ecx = 0) jb %%one_div ; yes, one division sufficient xchg cx, ax ; save dividend-lo in cx, ax=0 xchg ax, dx ; get dividend-hi in ax, dx=0 div bx ; quotient-hi in eax xchg ax, cx ; cx = quotient-hi, ax =dividend-lo %%one_div: div bx ; ax = quotient-lo mov bx, dx ; bx = remainder-lo mov dx, cx ; dx = quotient-hi(quotient in dx:ax) xor cx, cx ; cx = remainder-hi (rem. in cx:bx) ret %%big_divisor: push si ; save temp push di ; variables push dx ; save push ax ; dividend mov si, bx ; divisor now in mov di, cx ; di:bx and cx:si %%shift_loop: shr dx, 1 ; shift both rcr ax, 1 ; divisor and shr di, 1 ; and dividend rcr bx, 1 ; right by 1 bit jnz %%shift_loop ; loop if di non-zero (rcr does not touch ZF) mov di, cx ; restore original divisor (di:si) div bx ; compute quotient pop bx ; get dividend lo-word mov cx, ax ; save quotient mul di ; quotient * divisor hi-word (low only) push di ; save divisor hi-word xchg ax, di ; save in di mov ax, cx ; ax=quotient mul si ; quotient * divisor lo-word add dx, di ; dx:ax = quotient * divisor pop di ; restore divisor hi-word sub bx, ax ; dividend-lo - (quot.*divisor)-lo mov ax, cx ; get quotient pop cx ; restore dividend hi-word sbb cx, dx ; subtract divisor * quot. from dividend sbb dx, dx ; 0 if remainder > 0, else FFFFFFFFh and si, dx ; nothing to add and di, dx ; back if remainder positive add bx, si ; correct remaider adc cx, di ; and quotient if add ax, dx ; necessary xor dx, dx ; clear hi-word of quot (ax<=FFFFFFFFh) pop di ; restore temp pop si ; variables ret %endmacro