home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 105_01 / longcode.mac < prev    next >
Text File  |  1984-06-05  |  10KB  |  419 lines

  1. ;                        LONG
  2. ;
  3. ;     LONG is a facility to allow long integers to be
  4. ;   handled in BDS C.  A long integer is a four byte
  5. ;   array with the least significant part of the integer
  6. ;   stored in bytearray[0].  The integer is stored as a
  7. ;   2's complement number with 31 bits of precision.
  8. ;
  9. ;     Operations supported by LONG include addition,
  10. ;   subtraction, multiplication (least significant 31
  11. ;   bits returned), division, and modulus.  Other
  12. ;   operations, such as ascii to long, long to ascii,
  13. ;   etc., can be programmed efficiently in C.
  14. ;
  15. ;     Calls to LONG are normally "wrapped up" in various
  16. ;   C functions which, in turn, call the function
  17. ;
  18. ;        char *li(CODE,arg1,arg2,arg3)
  19. ;        char CODE, *arg1, *arg2, *arg3;
  20. ;
  21. ;   which returns a pointer to the result.  Arg1, arg2,
  22. ;   and arg3 must be pointers to four byte representations
  23. ;   of long integers in the format defined above.  In
  24. ;   general the operation performed is as if BDS C had
  25. ;   a data type long and
  26. ;
  27. ;        long *arg1, *arg2, *arg3;
  28. ;        *arg1 = *arg2 op *arg3;
  29. ;
  30. ;   where op is defined by the following table:
  31. ;
  32. ;         CODE     op      comment
  33. ;
  34. ;           0       +      signed 31 bit result
  35. ;           1       -      signed 31 bit result
  36. ;           2       *      signed low order 31 bit result
  37. ;           3       /      signed 31 bit quotient
  38. ;           4       %      positive 31 bit remainder
  39. ;
  40. ;   and, in each case, any overflow is both lost and not
  41. ;   noted.
  42. ;
  43.     TITLE    LONG
  44. ;
  45.     PAGE    60
  46. ;
  47. ;   BDS C is copyright (c) 1980 by Leor Zolman.
  48. ;   LONG is copyright (c) 1981 by Paul J. Gans.
  49. ;
  50. ;   A notable strangeness in the listing below is that
  51. ;   my version of this assembler REQUIRES that the op
  52. ;   code ex af,af' be CAPITOLIZED or it will not be
  53. ;   recognized...-pjg.
  54. ;
  55.     .z80
  56. ;
  57. ;     Note that the coding technique used here is basically
  58. ;   that of William C. Colley, III as reported in the BDS C
  59. ;   User's Guide Addenda, v1.32, dated May, 1980.  Note
  60. ;   that Colley's technique is simplified by using the
  61. ;   MACRO-80 pseudo-op DC to set the high order bit of
  62. ;   the last character of a string.
  63. ;
  64.     aseg
  65. ;
  66.     org    0000h
  67. ;
  68.     dc    'LI'    ; first directory entry
  69.     dw    long
  70. ;
  71.     db    80h    ; end of directory
  72.     dw    f.free    ; next free file location
  73. ;
  74.     org    0200h
  75. ;
  76.     db    0,0,0,0,0    ; always zero if no main
  77. ;
  78. long:    db    0    ; no fn's called by LONG
  79. ;
  80.     dw    f.1rel-f.1beg    ; length of LONG
  81. ;
  82.     .phase    0
  83. ;
  84. ;   At the start of this function the stack looks like:
  85. ;       arg3, arg2, arg1, CODE, return address
  86. ;   with the return address at the top of the stack.
  87. ;
  88. f.1beg:    pop    de    ; DE=returnaddress
  89.     pop    hl    ; CODE
  90.     ld    a,l    ; A=CODE
  91.     pop    hl    ; HL=arg1 (result address)
  92.     pop    ix    ; IX=arg2
  93.     pop    iy    ; IY=arg3
  94.     push    hl    ; now restore the stack length
  95.     push    hl
  96.     push    hl
  97.     push    hl
  98.     push    de    ; restore return address
  99.     push    bc    ; save BC for caller
  100.     push    hl    ; and a copy of arg1 for later
  101. ;
  102.     exx        ; goto prime register space
  103.     ld    c,(iy+0)    ; low order of args
  104.     ld    b,(iy+1)
  105.     ld    e,(ix+0)
  106.     ld    d,(ix+1)
  107.     ld    hl,0    ; clear result
  108. ;
  109.     exx        ; goto normal register space
  110.     ld    c,(iy+2)    ; high order of args
  111.     ld    b,(iy+3)
  112.     ld    e,(ix+2)
  113.     ld    d,(ix+3)
  114.     ld    hl,0    ; clear result
  115. ;
  116.     cp    0    ; check code
  117. f.1001:    jp    z,add
  118.     cp    1
  119. f.1002:    jp    z,sub
  120.     cp    2
  121. f.1003:    jp    z,mul
  122. ;
  123. ;   The division routine returns two possible values:
  124. ;   the quotient, if CODE was 3, or the modulus, if
  125. ;   CODE was 4.  As a sloppy error exit, CODEs higher
  126. ;   than 4 or lower than 0 default to 4.  I SAID it
  127. ;   was sloppy.
  128. ;
  129. ;   This routine expects a 64 bit dividend in registers
  130. ;   HLH'L'DED'E' and a 32 bit divisor in registers BCB'C'.
  131. ;   A 32 bit quotient is generated in DED'E' and a 32 bit
  132. ;   remainder is generated in HLH'L'.  For the present
  133. ;   application the high order 32 bits of the dividend
  134. ;   (registers HLH'L') are zeroed.
  135. ;
  136. ;
  137. div:    EX    AF,AF'    ; save CODE for later
  138. ;
  139. ;   Because signed divisions are a giant pain, the sign
  140. ;   of the result is computed and saved on the stack.
  141. ;   Then any negative operands are made positive via
  142. ;   calls to the proper routine.
  143. ;
  144. f.1004:    call    sign
  145. ;
  146.     ld    a,32    ; number of iterations
  147. div1:    or    a    ; reset carry flag
  148. ;
  149.     exx        ; enter prime register space
  150.     sbc    hl,bc    ; can we subtract?
  151. ;
  152.     exx        ; enter normal register space
  153.     sbc    hl,bc
  154.     jr    nc,div2    ; a carry means no
  155. ;
  156.     exx        ; enter prime register space
  157.     add    hl,bc    ; restore dividend
  158. ;
  159.     exx        ; enter normal register space
  160.     adc    hl,bc
  161. div2:    ccf        ; quotient bit
  162. ;
  163.     exx        ; enter prime register space
  164.     rl    e    ; left shift dividend, shifting
  165.     rl    d    ;   in new quotient bit as we go
  166. ;
  167.     exx        ; enter normal register space
  168.     rl    e
  169.     rl    d
  170. ;
  171.     exx        ; prime register space
  172.     adc    hl,hl    ; it's a 64 bit shift, guys
  173. ;
  174.     exx        ; normal register space
  175.     adc    hl,hl
  176.     dec    a    ; done?
  177. f.1005:    jp    p,div1    ; no
  178. ;
  179. ;   CODE must now be tested so that HL can be set up
  180. ;   properly.
  181. ;
  182.     EX    AF,AF'    ; regain CODE
  183.     cp    3
  184.     jr    nz,modu    ; it's a modulus by default
  185. ;
  186.     exx        ; prime space
  187.     ex    de,hl    ; return quotient
  188. ;
  189.     exx        ; normal space
  190.     ex    de,hl
  191.     pop    af    ; regain sign of result
  192.     or    a    ; to flags
  193. f.1006:    call    m,neg1    ; if negative
  194. f.1007:    jp    fin    ; to clean up and go home
  195. ;
  196. modu:    srl    h    ; adjust remainder for 1 bit
  197.     rr    l    ;   overshift
  198. ;
  199.     exx        ; prime space
  200.     rr    h
  201.     rr    l
  202. ;
  203.     exx        ; normal space
  204.     pop    de    ; dump saved sign, mod is pos
  205. f.1008:    jp    fin    ; to clean up and go home
  206. ;
  207. ;
  208. ;   The multiplication routine multiplies the contents
  209. ;   of registers BCB'C' by the contents of registers DED'E'
  210. ;   and returns the low order 31 bits of the result in
  211. ;   registers HLH'L'.
  212. ;
  213. ;   Multiplication is also best done on positive numbers,
  214. ;   so we go to the routine again.
  215. ;
  216. mul:    call    sign
  217. ;
  218.     ld    a,32
  219. ;
  220. mul1:    exx        ; enter prime space
  221.     sla    c    ; left shift plier 1 place
  222.     rl    b
  223. ;
  224.     exx        ; enter normal space
  225.     rl    c
  226.     rl    b
  227.     jr    nc,mul2    ; if high bit was 0
  228. ;
  229.     exx        ; prime space
  230.     add    hl,de    ; add in multiplicand
  231. ;
  232.     exx        ; normal space
  233.     adc    hl,de
  234. mul2:    dec    a    ; done?
  235.     jr    z,mul3    ; yes, clean up and go home
  236. ;
  237.     exx        ; hyperspace
  238.     add    hl,hl    ; left shift product
  239. ;
  240.     exx        ; real space
  241.     adc    hl,hl
  242.     jr    mul1    ; and repeat
  243. ;
  244. mul3:    pop    af    ; regain sign of result
  245.     or    a    ; sign to flags
  246. f.1009:    call    m,neg1    ; if negative
  247. f.100a:    jp    fin    ; and so to rest at last...
  248. ;
  249. ;   The contents of BCB'C' are added to the contents of
  250. ;   DED'E' and the results returned in HLH'L'.
  251. ;
  252. add:    exx        ; to prime
  253.     ex    de,hl
  254.     add    hl,bc
  255. ;
  256.     exx        ; to normal
  257.     ex    de,hl
  258.     adc    hl,bc
  259.     jr    fin    ; to quit
  260. ;
  261. ;   The contents of BCB'C' are subtracted from the contents
  262. ;   of DED'E' and the results returned in HLH'L'
  263. ;
  264. sub:    exx        ; to prime
  265.     or    a    ; reset carry flag
  266.     ex    de,hl
  267.     sbc    hl,bc
  268. ;
  269.     exx        ; to ~ormal
  270.     ex    de,xd
  271.     sbc    hl$bc    
  272.     jr    fin    ; to quit
  273. ?
  274. ;   T`is is the terminal section of code.  It stores the
  275. ;   result from HLH'L' into the locations specified by
  276. ;   arg1, restores BC and SP, and exits with HL containing
  277. ;   arg1.
  278. ;
  279. fin:    pop    ix    ; IX=arg1 (result address)
  280.     pop    bc    ; restore BC while we are at it
  281. ;
  282.     exx        ; to momentum space
  283.     ld    (ix+0),l
  284.     ld    (ix+1),h
  285. ;
  286.     exx        ; ÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷ result sign
  287. ;
  288.     ld    a,d    ; sign of arg2 again
  289.     or    a    ; to flags
  290. f.100b:    jp    p,sign1    ; if non-negative
  291. ;
  292. ;   Form the 2's complement of the second argument
  293. ;   (DED'E').
  294. ;
  295.     exx        ; far out space
  296.     xor    a    ; reset A and carry bit
  297.     sbc    hl,de
  298.     ex    de,hl    ; restore answer
  299.     ld    l,a    ; clean things up
  300.     ld    h,a
  301. ;
  302.     exx        ; home space
  303.     sbc    hl,de
  304.     ex    de,hl    ; more restore
  305.     ld    l,a    ; clean here too
  306.     ld    h,a
  307. ;
  308. sign1:    ld    a,b    ; sign of arg3
  309.     or     a    ; to flags
  310. f.100c:    jp    p,sign2    ; if non-negative
  311. ;
  312. ;   The two's complement of the third argument is formed
  313. ;   in place (BCB'C').
  314. ;
  315.     exx        ; prime
  316.     xor    a    ; reset A and carry
  317.     sbc    hl,bc
  318.     ld    c,l
  319.     ld    b,h
  320.     ld    l,a    ; rezero things
  321.     ld    h,a
  322. ;
  323.     exx        ; normal
  324.     sbc    hl,bc
  325.     ld    c,l
  326.     ld    b,h
  327.     ld    l,a
  328.     ld    h,a
  329. ;
  330. sign2:    jp    (ix)    ; that's all, folks!
  331. ;
  332. ;   This routine forms the 2's complement of the result
  333. ;   in HLH'L'.
  334. ;
  335. neg1:    exx        ; enter prime space
  336.     xor    a    ; zero A and carry flag
  337.     ex    de,hl
  338.     ld    l,a    ; zero HL register
  339.     ld    h,a
  340.     sbc    hl,de
  341. ;
  342.     exx        ; enter normal space
  343.     ex    de,hl
  344.     ld    l,a    ; zero HL register
  345.     ld    h,a
  346.     sbc    hl,de
  347. ;
  348.     ret
  349. ;
  350. f.1rel:    dw    (f.1end-$)/2    ; num of reloc params
  351.     dw    f.1001+1    ; relocation addresses
  352.     dw    f.1002+1
  353.     dw    f.1003+1
  354.     dw    f.1004+1
  355.     dw    f.1005+1
  356.     dw    f.1006+1
  357.     dw    f.1007+1
  358.     dw    f.1008+1
  359.     dw    mul+1
  360.     dw    f.1009+1
  361.     dw    f.100a+1
  362.     dw    f.100b+1
  363. f.1end:    dw    f.100c+1
  364. ;
  365.     .dephase
  366. ;
  367. f.free:            ; next free location
  368. ;
  369.     end
  370. 
  371.     end
  372.     end
  373.  
  374.     end
  375. cation
  376. ;
  377.     end
  378. 
  379. s routine forms the 2's complement of the third
  380. ;   argument (BCB'C').
  381. ;
  382. neg3:    exx        ; prime
  383.     xor    a    ; reset A and carry flag
  384.     sbc    hl,bc
  385.     ld    c,l
  386.     ld    b,h
  387.     ld    l,a    ; rezero things
  388.     ld    h,a
  389. ;
  390.     exx        ; normal
  391.     sbc    hl,bc
  392.     ld    c,l
  393.     ld    b,h
  394.     ld    l,a    ; clean up
  395.     ld    h,a
  396. ;
  397.     ret
  398. ;
  399. f.1rel:    dw    (f.1end-$)/2    ; num of reloc params
  400.     dw    f.1001+1    ; relocation addresses
  401.     dw    f.1002+1
  402.     dw    f.1003+1
  403.     dw    f.1004+1
  404.     dw    f.1005+1
  405.     dw    f.1006+1
  406.     dw    f.1007+1
  407.     dw    f.1008+1
  408.     dw    mul+1
  409.     dw    f.1009+1
  410.     dw    f.100a+1
  411.     dw    f.100b+1
  412. f.1end:    dw    f.100c+1
  413. ;
  414.     .dephase
  415. ;
  416. f.free:            ; next free location
  417. ;
  418.     end
  419. ═Ç╩┼à■(╩░à╒═µü╤÷└_zé│├òéz╖┬╧ï═▓ü■╩└à═ ü>Θ├⌠üOz╖>├╩ñé>═├ñé!÷î═·Ç┬≡à═îÄ■╩δà═╥ü÷└├⌠ü>╔├⌠ü!ªî═ⁿÇ┬Eå═Vü╩å╩╧ï═╜ÇG═╔ü>╙├