home *** CD-ROM | disk | FTP | other *** search
- ; Long Integer Package - Assembly Code Portion
- ;
- ; Rob Shostak 7/82
- ;
- ; This is the assembly language portion of a BDS-C library package
- ; to enable the manipulation of long integers (which we also call
- ; "quads", since they occupy 4 bytes) in the same spirit as Bob
- ; Mathias' floating point package. See long.c and long.doc
- ;
-
- INCLUDE "bds.lib"
-
- FUNCTION long
-
- ; temporary storage is allocated in the
- ; "args" area of the run-time environment
-
- u equ args ;temporary quad storage (4 bytes)
- uh equ u ;high word of u
- ul equ u+2 ;low word of u
- mq equ u+4 ;temporary quad storage used by
- ;multiplication and division routines
- temp equ mq+4 ;temporary storage byte used by div'n routine
-
-
- ; long is main routine which dispatches to the various functions
- ; of the package according to the value of its first argument
-
- long: push b ;save for benefit of caller
- call ma2toh ;get 1st arg (function code) into HL and A
- mov d,h
- mov e,l
- dad h
- dad d ;HL now has triple the function code
- lxi d,jtab ;base of jump table
- dad d
- pchl ;dispatch to appropriate function
-
- jtab: jmp lmake ;jump table for quad functions
- jmp lcomp
- jmp ladd
- jmp lsub
- jmp lmul
- jmp ldiv
- jmp lmod
-
-
- ; lmake converts integer (arg3) to a long (arg2)
-
- lmake: call ma4toh ;get arg3 into HL
- mov a,h ;look at sign first
- ora a
- push psw ;save it
- cm cmh ;take abs value
- xchg ;into (DE)
- lxi b,0 ;zero out high word
- pop psw
- cm qneg ;complement if necessary
- jmp putarg ;copy result into arg2 and return
-
- ;all other routines copy their arguments into the quad register (BCDE)
- ;and the temporary quad storage location u (note that temporary storage
- ;must be used to keep the routines from clobbering the user's arguments)
-
-
- ;lcomp compares arg2 with arg3, returns -1, 0, 1 for <, =, >, resp
-
- lcomp: call ma3toh ;get pointer to arg2
- call qld
- lxi h,u
- call qst ;arg2 now in u
- call ma4toh ;get pointer to arg3
- call qld ;arg3 now in (BCDE)
- lxi h,-1 ;presume <
- call qsub
- call qtst
- pop b ;restore bc for caller
- rm
- inx h
- rz
- inx h
- ret
-
- ; long addition
-
- ladd: call getargs ;get args into (BCDE) and u
- call qadd ;do the addition
- jmp putarg ;copy result into arg2 and return
-
- lsub: call getargs
- call qsub
- jmp putarg
-
- lmul: call getargs
- call qmul
- jmp putarg
-
- ldiv: call getargs
- call qdiv
- jmp putarg
-
- lmod: call getargs
- call qmod
- jmp putarg
-
- ;getargs gets arg3 into u, arg4 into (BCDE)
-
- getargs:
- call ma5toh ;get ptr to arg3 (note use ma5 cause of
- ;return addr on stack)
- call qld ;arg3 now in (BCDE)
- lxi h,u
- call qst ;now in u
- call ma6toh ;get ptr to arg4
- jmp qld ;arg4 now in (BCDE)
-
-
- ; putarg copies (BCDE) into result arg (arg2) and cleans up
-
- putarg: call ma3toh ;get pointer to arg2
- call qst ;copy (BCDE) into it
- pop b ;restore BC for caller
- ret
-
-
-
- ; quad subtraction u - (BCDE) -> (BCDE)
-
- qsub: call qneg ;complement (BCDE) and fall thru to add
-
- ; quad addition u + (BCDE) -> (BCDE)
-
- qadd: push h
- lxi h,u+3 ;tenSHUN
- mov a,m ;hup
- add e ;two
- mov e,a ;three
- dcx h ;four
- mov a,m ;hup
- adc d ;two
- mov d,a ;three
- dcx h ;four
- mov a,m ;hup
- adc c ;two
- mov c,a ;three
- dcx h ;four
- mov a,m ;hup
- adc b ;two
- mov b,a ;three
- pop h ;four
- ret ;at ease
-
-
- ; two's complement (BCDE)
-
- qneg: push h
- xra a
- mov l,a
- sbb e
- mov e,a
- mov a,l
- sbb d
- mov d,a
- mov a,l
- sbb c
- mov c,a
- mov a,l
- sbb b
- mov b,a
- pop h
- ret
-
-
- qneghl: push b
- push d
- call qld
- call qneg
- call qst
- pop d
- pop b
- ret
-
- ; signed quad multiplication
- ; u * (BCDE) --> (BCDE)
-
- qmul: call csign ;take abs values and compute signs
- push psw ;save result sign
- call uqmul ;compute product
- qmul1: pop psw
- jm qneg ;complement product if needed
- ret
-
- ; csign takes abs vals of u, (BCDE), and computes product of their signs
-
- csign: mov a,b ;look at (BCDE) first
- ora a
- push psw ;save flags
- cm qneg ;complement if needed
- lxi h,u ;now look at u
- mov a,m
- ora a
- jp csign1
- call qneghl
- pop psw
- xri 80h ;flip sign
- ret
- csign1: pop psw
- ret
-
- ; unsigned quad multiplication
- ; u * (BCDE) --> (BCDE) (expects ptr. to u in (HL)
-
- uqmul: lxi h,u
- push h ;put pointer to u on stack
- lxi h,mq
- call qst ;(BCDE) -> mq
- lxi b,0 ;init product to 0
- lxi d,0
- uqmul1: call qtsthl ;test if mq is 0
- jz uqmul2 ;if so, done
- xra a ;clear carry
- call qrarhl ;shift mq over
- cc qadd ;add u to (BCDE) if lsb=1
- xthl ;get pointer to u
- xra a ;clear carry
- call qralhl ;double u
- xthl ;get back pointer to mq
- jmp uqmul1
- uqmul2: pop h ;restore stack
- ret
-
- ; signed division u / (BCDE) --> (BCDE)
-
- qdiv: call qtst ;first test for zero divisor
- rz
- call csign ;take care of signs
- push psw ;save quotient sign
- call uqdiv
- call qld ;get quotient in (BCDE)
- jmp qmul1 ;adjust sign of result
-
- ; signed remainder u mod (BCDE) --> (BCDE)
-
- qmod: call qtst ;test for zero modulus
- rz
- lda u ;sign of u is that of result
- ora a
- push psw ;save flags
- call csign ;get abs val of args
- call uqdiv ;remainder in (BCDE)
- jmp qmul1
-
-
- ; unsigned division u / (BCDE) --> mq, remainder in (BCDE)
-
-
-
- uqdiv: lxi h,mq ;mq will contain quotient
- call qclrhl ;clear it
- push h ;save it on the stack
-
- mvi l,1 ;now normalize divisor
- uqdiv1: mov a,b ;look at most signif non-sign bit
- ani 40h
- jnz uqdiv2
- call qral ;if not 1, shift left
- inr l
- jmp uqdiv1
- uqdiv2: mov a,l
- sta temp ;save normalization count
- lxi h,u
- call qxchg ;want divid in (BCDE), divisor in u
- xthl ;pointer to mq in (HL), u on stack
-
- ;main loop
-
- uqdiv3: call trial ;trial subtraction of divisor
- call qralhl ;shift in the carry
- lda temp ;get the count
- dcr a
- jz uqdiv4 ;done
- sta temp ;save count again
- xthl ;divisor in (HL)
- xra a
- call qrarhl ;shift it right one
- xthl ;quotient in (HL)
- jmp uqdiv3
-
- uqdiv4: inx sp
- inx sp ;clean off top of stack
- ret
-
-
- trial: call qsub ;subtract divid from divisor
- call qneg ;actually want divisor from divid
- stc ;assume was positive
- rp
- call qadd ;else must restore dividend
- xra a ;clear carry
- ret
-
-
- ;
- ; routines to manipulate quads
- ;
- ; qld loads the quad pointed to by (HL) into (BCDE)
-
- qld: push h
- mov b,m
- inx h
- mov c,m
- inx h
- mov d,m
- inx h
- mov e,m
- pop h
- ret
-
- ; qst is inverse of qld
-
- qst: push h
- mov m,b
- inx h
- mov m,c
- inx h
- mov m,d
- inx h
- mov m,e
- pop h
- ret
-
-
-
- ; rotate (BCDE) right thru carry
-
- qrar: mov a,b
- rar
- mov b,a
- mov a,c
- rar
- mov c,a
- mov a,d
- rar
- mov d,a
- mov a,e
- rar
- mov e,a
- ret
-
- ; same for quad pointed to by (HL)
-
- qrarhl: push h
- mov a,m
- rar
- mov m,a
- inx h
- mov a,m
- rar
- mov m,a
- inx h
- mov a,m
- rar
- mov m,a
- inx h
- mov a,m
- rar
- mov m,a
- pop h
- ret
-
-
- ; rotate (BCDE) left thru carry
-
- qral: mov a,e
- ral
- mov e,a
- mov a,d
- ral
- mov d,a
- mov a,c
- ral
- mov c,a
- mov a,b
- ral
- mov b,a
- ret
-
- ; qralhl does it for quad pointed to by (HL)
-
- qralhl: inx h
- inx h
- inx h ;get to rightmost byte
- mov a,m
- ral
- mov m,a
- dcx h
- mov a,m
- ral
- mov m,a
- dcx h
- mov a,m
- ral
- mov m,a
- dcx h
- mov a,m
- ral
- mov m,a
- ret
-
-
- ;qclrhl clears quad pointed to by (HL)
-
- qclrhl: push h
- xra a
- mov m,a
- inx h
- mov m,a
- inx h
- mov m,a
- inx h
- mov m,a
- pop h
- ret
-
-
- ; qtst tests sign of (BCDE), setting the usual flags
-
- qtst: mov a,b ;look at most signif byte
- ora a
- rnz
- ora c ;test for zero
- ora d
- ora e
- qtst1: rp
- mvi a,1
- ora a
- ret
-
- qtsthl: mov a,m
- ora a
- rnz
- push h
- inx h
- ora m
- inx h
- ora m
- inx h
- ora m
- pop h
- jmp qtst1
-
- ; swap (BCDE) with thing pointed to by HL
-
- qxchg: push h
- mov a,m
- mov m,b
- mov b,a
- inx h
- mov a,m
- mov m,c
- mov c,a
- inx h
- mov a,m
- mov m,d
- mov d,a
- inx h
- mov a,m
- mov m,e
- mov e,a
- pop h
- ret
-
-
- ENDFUNCTION
-
-
-