home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / asmutl / bluebook.arc / MULTIDGT.ASM < prev    next >
Assembly Source File  |  1986-05-11  |  8KB  |  301 lines

  1.                                       COMMENT ~
  2. MULTIDGT.ASM -- Multidigit Arithmetic Procedures
  3.  
  4.    From `BLUEBOOK of ASSEMBLY ROUTINES for the IBM PC & XT'
  5.          by Christopher L. Morgan
  6.          Copyright (C) 1984 by The Waite Group, Inc.
  7.  
  8.    Purpose: These routines perform addition, subtraction, multiplication, 
  9.      and division upon multidigit integers (16-bit).
  10.  
  11.    Contents:
  12.    ---------
  13.    MBINADD --  Multidigit binary addition
  14.    MBINDIV --  Multidigit binary division
  15.    MBINMUL --  Multidigit binary multiplication
  16.    MBINSUB --  Multidigit binary subtraction
  17.  
  18.     >>>> See MULTIDGT.DOC for complete descriptions of these routines. <<<<< 
  19. _____________________________________________________________________________
  20.                                                                               ~
  21. EXTRN    STDIN:FAR,STDOUT:FAR
  22. ;______________________________________________________________________________
  23. ;        
  24. ; Needs a constant named ISIZE
  25. DATAS    SEGMENT    PUBLIC
  26.     TBUFF    DB    5 DUP(?)
  27. DATAS    ENDS 
  28. ;______________________________________________________________________________
  29. ;        
  30. CODES    SEGMENT
  31.  
  32.     PUBLIC MBINADD,MBINSUB,MBINMUL,MBINDIV
  33.  
  34. ASSUME CS:CODES,DS:DATAS
  35. ;____________________________I/O ROUTINES______________________________________
  36. ;          
  37. MBINADD
  38. ;Routine to add multidigit binary numbers
  39. ;
  40. MBINADD    PROC    FAR
  41.     PUSH    SI                ;Save registers
  42.     PUSH    DI
  43.     PUSH    BX
  44.     PUSH    CX
  45.     PUSH    AX
  46.     MOV    CX,ISIZE            ;Get the # of 16-bit "digits"
  47.     CLC                    ;Clear the carry in
  48. MBINADD1:
  49.     MOV    AX,[SI]                ;Get "digit" from first number
  50.     INC    SI                ;Point to next "digit"
  51.     INC    SI
  52.     ADC    AX,[DI]                ;Add "digit" from second num
  53.     INC    DI                ;Point to next "digit"
  54.     INC    DI                ;Move resulting
  55.     MOV    [BX],AX                ; "digit" into place
  56.     INC    BX                ;Point to next "digit"
  57.     INC    BX
  58.     LOOP    MBINADD1            ;Loop through all "digits"
  59.     POP    AX                ;Restore registers
  60.     POP    CX
  61.     POP    BX
  62.     POP    DI
  63.     POP    SI
  64.     RET
  65.     
  66. MBINADD    ENDP
  67. ;______________________________________________________________________________
  68. ;Routine to subtract multidigit binary numbers
  69. ;
  70. MBINSUB    PROC    FAR
  71.     PUSH    SI                ;Save registers
  72.     PUSH    DI
  73.     PUSH    BX
  74.     PUSH    CX
  75.     PUSH    AX
  76.     MOV    CX,ISIZE            ;Get the # of 16-bit "digits"
  77.     CLC                    ;Clear the carry in
  78. MBINSUB1:
  79.     MOV    AX,[DI]                ;Get "digit" from second num
  80.     INC    DI                ;Point to next "digit"
  81.     INC    DI
  82.     SBB    AX,[SI]                ;Subtract "digit" of first num
  83.     INC    SI                ;Point to next "digit"
  84.     INC    SI                ;Move resulting
  85.     MOV    [BX],AX                ; "digit" into place
  86.     INC    BX                ;Point to next "digit"
  87.     INC    BX
  88.     LOOP    MBINADD1            ;Loop through all "digits"
  89.     POP    AX                ;Restore registers
  90.     POP    CX
  91.     POP    BX
  92.     POP    DI
  93.     POP    SI
  94.     RET
  95. MBINSUB    ENDP
  96. ;______________________________________________________________________________
  97. ;Routine to multiply multidigit binary numbers
  98. ;
  99. MBINMUL    PROC    FAR
  100.     PUSH    SI                ;Save registers
  101.     PUSH    DI
  102.     PUSH    BX
  103.     PUSH    CX
  104.     PUSH    AX
  105. ;
  106. ;Clear result buffer
  107.     PUSH    BX                ;Save result pointer BX
  108.     MOV    AX,0                ;Get a zero
  109.     MOV    CX,2*ISIZE            ;Double precision for this num
  110.     CLD                    ;Forward direction
  111. MBINMUL1:
  112.     MOV    [BX],AX                ;Clear the "digit"
  113.     INC    BX                ;Point to next "digit"
  114.     INC    BX
  115.     LOOP    MBINMUL1            ;Loop through all "digits"
  116.     POP    BX                ;Restore result pointer BX
  117.     MOV    CX,ISIZE            ;Get the num of 16-bit "digits"
  118. MBINMUL2:
  119.     PUSH    CX                ;Save outer loop count
  120.     MOV    DX,[SI]                ;Get "digit" from first number
  121.     INC    SI                ;Point to next "digit"
  122.     INC    SI
  123.     PUSH    BX                ;Save regs during inner loop
  124.     PUSH    DI
  125.     MOV    CX,ISIZE            ;Get the num of 16-bit "digits"
  126. MBINMUL3:
  127.     PUSH    CX                ;Save inner loop count
  128.     PUSH    DX                ;Save multiplier "digit"
  129.     MOV    AX,[DI]                ;Get "digit" from second num
  130.     INC    DI                ;Point to next "digit"
  131.     INC    DI
  132.     MUL    DX                ;Multiply
  133.     ADD    [BX],AX                ;Add lower "digit" to result
  134.     INC    BX                ;Point to next "digit"
  135.     INC    BX                
  136.     ADC    [BX],DX                ;Add upper part to result
  137.     POP    DX                ;Restore multiplier
  138.     POP    CX                ;Restore inner loop count
  139.     LOOP    MBINMUL3            ;Loop through all "digits" of 
  140.                         ; second
  141.     POP    DI                ;Restore registers
  142.     POP    BX
  143.     INC    BX                ;Shift by one "digit"
  144.     INC    BX
  145.     POP    CX                ;Restore outer loop count
  146.     LOOP    MBINMUL3            ;Loop through all "digits" of
  147.                         ; first
  148.     POP    AX                ;Restore registers
  149.     POP    CX
  150.     POP    BX
  151.     POP    DI
  152.     POP    SI
  153.     RET
  154. MBINMUL    ENDP
  155. ;______________________________________________________________________________
  156. ;Routine to divide multidigit binary numbers
  157. ;  This routine uses 4 local subroutines: DIVCMP,DIVSAL,DIVSLR,DIVSUB,QUOTSHL
  158. ;
  159. ;---------------------------LOCAL SUBROUTINES----------------------------------
  160. ;Local subroutine to compare divisor against dividend
  161. ;
  162. DIVCMP    PROC    NEAR
  163.     PUSH    SI                ;Save registers
  164.     PUSH    DI    
  165.     PUSH    CX
  166.     STD                    ;Backward direction
  167.     ADD    SI,4*ISIZE-2            ;Point to end of temp divisor
  168.     ADD    DI,4*ISIZE-2            ;Point to end of quotient
  169.     MOV    CX,2*ISIZE            ;Count for double precision
  170.     REPZ    CMPSW                ;Compare "digit" by "digit"
  171.     POP    CX                ;Restore registers
  172.     POP    DI    
  173.     POP    SI
  174.     RET
  175. DIVCMP    ENDP
  176. ;------------------------------------------------------------------------------
  177. ;Local subroutine to arithmetically shift divisor left
  178. ;
  179. DIVSAL    PROC    NEAR
  180.     PUSH    SI                ;Save registers
  181.     PUSH    CX
  182.     MOV    CX,2*ISIZE            ;Set counter
  183.     CLC                    ;Clear carry in
  184. DIVSAL1:
  185.     RCL    WORD PTR [SI],1            ;Shift one word by one bit
  186.     INC    SI                ;Point to next word
  187.     INC    SI
  188.     LOOP    DIVSAL1                ;Loop through entire divisor
  189.     POP    CX                ;Restore registers
  190.     POP    SI
  191.     RET
  192. DIVSAL    ENDP
  193. ;------------------------------------------------------------------------------
  194. ;Local subroutine to logically shift divisor right
  195. ;
  196. DIVSLR    PROC    NEAR
  197.     PUSH    SI                ;Save registers
  198.     PUSH    CX
  199.     ADD    SI,4*ISIZE-2            ;Point to end of temp divisor
  200.     MOV    CX,2*ISIZE            ;Count for double precision
  201.     CLC                    ;Clear carry in
  202. DIVSLR1:
  203.     RCR    WORD PTR [SI],1            ;Rotate one word by one bit
  204.     DEC    SI                ;Point to next word
  205.     DEC    SI
  206.     LOOP    DIVSLR1                ;Loop through entire divisor
  207.     POP    CX                ;Restore registers
  208.     POP    SI
  209.     RET
  210. DIVSLR    ENDP
  211. ;------------------------------------------------------------------------------
  212. ;Local subroutine to subtract shifted divisor from divident
  213. ;
  214. DIVSUB    PROC    NEAR
  215.     PUSH    SI                ;Save registers
  216.     PUSH    DI
  217.     PUSH    CX
  218.     CLC                    ;Cleary carry in
  219.     MOV    CX,2*ISIZE            ;Set count for double precision
  220. DIVSUB1:
  221.     MOV    AX,[SI]                ;Get word from shifted divisor
  222.     INC    SI                ;Point to next word
  223.     INC    SI    
  224.     SBB    [DI],AX                ;Subtract from word of dividend
  225.     INC    DI                ;Point to next word
  226.     INC    DI
  227.     LOOP    DIVSUB1                ;Loop through all words
  228.     POP    CX                ;Restore registers
  229.     POP    DI
  230.     POP    SI
  231.     RET
  232. DIVSUB    ENDP
  233. ;------------------------------------------------------------------------------
  234. ;Local subroutine to shift quotient left
  235. ;
  236. QUOTSHL    PROC    NEAR
  237.     PUSH    BX                ;Save registers
  238.     PUSH    CX
  239.     MOV    CX,ISIZE            ;Count for single precision
  240. QUOTSHL1:
  241.     RCL    WORD PTR [BX],1            ;Shift wrd of quotnt left once
  242.     INC    BX                ;Point to next word
  243.     INC    BX
  244.     LOOP    QUOTSHL1            ;Loop through entire quotient
  245.     POP    CX                ;Restore registers
  246.     POP    BX
  247.     RET
  248.  
  249. DIVSHL    ENDP
  250. ;------------------------------------------------------------------------------
  251. ; >>>>> End of Local Subroutines
  252. ;
  253. ;Routine to divide multidigit binary numbers
  254. ;
  255. MBINDIV    PROC    FAR
  256.     PUSH    SI                ;Save registers
  257.     PUSH    DI
  258.     PUSH    BX
  259.     PUSH    CX
  260.     PUSH    AX
  261. ;
  262. ;Put single precision divisor into double precision location
  263.     PUSH    DI                ;Save dividend pointer
  264.     LEA    DI,TEMPDIV            ;Point SI to temporary divisor
  265.     MOV    CX,1                ;Initialize shift count to 1
  266. ;
  267. ;Normalize divisor
  268. MBINDIV1:
  269.     TEST    MSBDIV,8000H            ;Test MSB of divisor
  270.     JNZ    MBINDIV2            ;Exit if normalized
  271.     CALL    DIVSAL                ;Arith shift left, if not
  272.     INC    CX                ;Count the shift
  273.     JMP    MBINDIV1            ;Keep looping till normalized
  274. ;
  275. ;Compare, subtract, shift loop
  276. MBINDIV2:
  277.     CALL    DIVCMP                ;Compare divisor with dividend
  278.     JA    MBINDIV3            ;Skip if too large
  279.     CALL    DIVSUB                ;Else subtract
  280.     STC                    ;New bit of quotient is in 1
  281.     JMP    MBINDIV4            ;Jump to end of loop
  282. MBINDIV3:
  283.     CLC                    ;New bit of quotient is in 0
  284. MBINDIV4:
  285.     CALL    QUOTSHL                ;Shift bit into the quotient
  286.     CALL    DIVSLR                ;Logic shift divisor right once
  287.     LOOP    MBINDIV2            ;Loop for next digit
  288.     POP    AX                ;Restore registers
  289.     POP    CX
  290.     POP    BX
  291.     POP    DI
  292.     POP    SI
  293.     RET
  294. MBINDIV    ENDP
  295. ;______________________________________________________________________________
  296. CODES    ENDS
  297. ;
  298.     END
  299. ;______________________________________________________________________________
  300. ;>>>>> Physical EOF MULTIDGT.ASM <<<<<
  301.