TPSRC3 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600
  1. CMP.B AH,remul21a
  2. rdcmp JB rdshft ;below:no subtraction
  3. SUB.B AH,remul21a ;do subtraction
  4. SBB BX,remul22
  5. SBB DX,remul23
  6. rdshft CMC ;invert carry
  7. RCL.B CH,1 ;shift into result
  8. DEC SI ;another bit ?
  9. JNZ rdbit ;:yes
  10. MOV.B [DI],CH ;store result byte
  11. DEC.B CL ;another byte ?
  12. JZ rdlast ;:no
  13. DEC DI ;next one
  14. MOV SI,#$0008 ;8 bits again
  15. rdbit SHL.B AH,1 ;shift left mantissa
  16. RCL BX,1
  17. RCL DX,1
  18. JNB rdloop ;:normal step
  19. SUB.B AH,remul21a ;carry: no comparison necessary
  20. SBB BX,remul22 ;do subtraction
  21. SBB DX,remul23
  22. CLC
  23. JMP rdshft ;'shift in result
  24. rdlast SHL.B AH,1 ;do last shift
  25. RCL BX,1
  26. RCL DX,1
  27. JB rdshft2 ;:ok
  28. CMP DX,remul23 ;test last step
  29. JNZ rdcmp2
  30. CMP BX,remul22
  31. JNZ rdcmp2
  32. CMP.B AH,remul21a
  33. rdcmp2 CMC
  34. rdshft2 MOV CX,remul11 ;get result
  35. MOV BX,remul12
  36. MOV DX,remul13
  37. LAHF ;save flags
  38. TEST.B DH,#$80 ;normalized ?
  39. JNZ rdnrm ;:yes
  40. SAHF ;get flags
  41. RCL.B CH,1 ;shift left mantissa
  42. RCL BX,1
  43. RCL DX,1
  44. JMP.b rdok ;'get sign, test exponent
  45. rdnrm INC.B CL ;inc exponent
  46. JNZ rdok ;:ok
  47. STC ;overflow error
  48. RET ;'
  49. rdok JMP rmnoadj ;"set sign, test exponent
  50. testexp JB texovr ;test exponent: overflow ?
  51. ADD AL,#$80 ;set offset again
  52. JB texok ;:ok
  53. POP BX ;forget return addr
  54. XOR AX,AX ;return zero: underflow
  55. XOR BX,BX
  56. XOR DX,DX
  57. RET ;'
  58. texovr ADD AL,#$80 ;set offset again
  59. JNB texok ;:no error
  60. POP BX ;forget return addr
  61. STC ;overflow error
  62. RET ;'
  63. texok MOV remul21,CX ;save LSB2
  64. MOV CX,DX ;get sign
  65. XOR CX,DI
  66. NOT.B CH ;invert it
  67. AND.B CH,#$80 ;mask sign
  68. MOV.B resave,CH ;save sign
  69. OR.B DH,#$80 ;set mantissa MSB
  70. OR DI,#$8000
  71. MOV remul22,SI ;store mantissa 2
  72. MOV remul23,DI
  73. RET ;"
  74. readd2 PUSH DI ;add, keep second number
  75. PUSH SI
  76. PUSH CX
  77. CALL readd ;do addition
  78. POP CX
  79. POP SI
  80. POP DI
  81. RET ;"
  82. resub2 PUSH DI ;subtract, keep second number
  83. PUSH SI
  84. PUSH CX
  85. CALL resub ;do subtraction
  86. POP CX
  87. POP SI
  88. POP DI
  89. RET ;"
  90. remult2 PUSH DI ;multiply, keep second number
  91. PUSH SI
  92. PUSH CX
  93. CALL remult ;do multiplication
  94. POP CX
  95. POP SI
  96. POP DI
  97. RET ;"
  98. rediv2 PUSH DI ;divide, keep second number
  99. PUSH SI
  100. PUSH CX
  101. CALL rediv ;do division
  102. POP CX
  103. POP SI
  104. POP DI
  105. RET ;"
  106. recmp PUSH DX ;Real comparison
  107. XOR DX,DI ;compare signs
  108. POP DX ;restore
  109. JNS rcsign ;:signs are the same
  110. PUSH DX ;different signs: get flag
  111. RCL DX,1
  112. POP DX
  113. RET ;'
  114. rcsign TEST.B DH,#$80 ;sign ?
  115. JZ rcnum ;:positive
  116. CALL rcnum ;compare
  117. JZ rcdiff ;equal: don't invert
  118. CMC ;invert flags
  119. RET ;'
  120. rcnum CMP.B AL,CL ;compare exponents
  121. JNZ rcdiff
  122. OR.B AL,AL ;zero ?
  123. JZ rcdiff ;yes:equal
  124. CMP DX,DI ;compare mantissa MSB
  125. JNZ rcdiff
  126. CMP BX,SI
  127. JNZ rcdiff
  128. CMP.B AH,CH ;compare mantissa LSB
  129. rcdiff RET ;"
  130. intreal OR AX,AX ;Int(Integer) -> Real
  131. JNZ irnot0 ;:not zero
  132. XOR BX,BX ;return zero
  133. XOR DX,DX
  134. RET ;'
  135. irnot0 MOV.B BH,AH ;put sign
  136. MOV DX,AX
  137. OR DX,DX ;test sign
  138. JNS irpos ;:positive
  139. NEG DX ;negate number
  140. irpos MOV AX,#$0090 ;exp, cleared LSB mantissa
  141. OR.B DH,DH ;test high byte
  142. JNZ ir16bits ;:not zero
  143. MOV AL,#$88 ;speed it up...
  144. XCHG.B DL,DH ;shift 8 bits
  145. ir16bits OR DX,DX ;test mantissa MSB
  146. JS irdone ;:ok, normalized
  147. irnrm DEC.B AL ;count down exponent
  148. SHL DX,1 ;shift it left
  149. JNS irnrm ;:continue
  150. irdone OR.B BH,BH ;negative ?
  151. JS irpos2 ;:yes
  152. AND.B DH,#$7F ;set positive flag
  153. irpos2 XOR BX,BX ;clear rest of mantissa
  154. RET ;"
  155. reint CMP AL,#$A8 ;Int(Real) - inefficient !
  156. JNB riret ;exponent too big - done
  157. MOV CX,AX ;save number
  158. MOV SI,BX
  159. MOV DI,DX
  160. XOR.B AH,AH ;clear mask
  161. XOR BX,BX
  162. XOR DX,DX
  163. SUB.B CL,#$80 ;exponent-offset
  164. JBE rizero ;:underflow, return zero
  165. rim16l CMP.B CL,#$10 ;shift 16 bit ?
  166. JB rim8 ;:done
  167. MOV.B AH,BH ;shift right 16 bit
  168. MOV BX,DX
  169. MOV DX,#$FFFF ;put into mask
  170. SUB.B CL,#$10 ;count down
  171. JMP rim16l ;'try again
  172. rim8 CMP.B CL,#$08 ;shift 8 bit ?
  173. JB rim1 ;:done
  174. MOV.B AH,BL ;shift right 8 bit
  175. MOV.B BL,BH
  176. MOV.B BH,DL
  177. MOV.B DL,DH
  178. MOV DH,#$FF ;put into mask
  179. SUB.B CL,#$08 ;count down
  180. rim1 OR.B CL,CL ;shift single bits ?
  181. JZ riand ;:done
  182. rim1l STC ;shift in a 1
  183. RCR DX,1 ;shift right 1 bit
  184. RCR BX,1
  185. RCR.B AH,1
  186. DEC.B CL ;count down
  187. JNZ rim1l ;:continue shifting
  188. riand AND DX,DI ;get result:
  189. AND BX,SI ;mask away the fraction
  190. AND.B AH,CH
  191. riret RET ;'
  192. rizero XOR.B AL,AL ;return zero
  193. RET ;"
  194. refrac PUSH DX ;Frac - inefficient !
  195. PUSH BX ;save original number
  196. PUSH AX
  197. CALL reint ;Int
  198. MOV CX,AX ;result -> second number
  199. MOV SI,BX
  200. MOV DI,DX
  201. POP AX ;restore number
  202. POP BX
  203. POP DX
  204. JMP resub ;"do subtraction
  205. xldreal POP BX ;Load real number onto stack
  206. POP ES ;ptr
  207. ES:
  208. PUSH [DI]$04 ;push that number
  209. ES:
  210. PUSH [DI]$02
  211. ES:
  212. PUSH [DI]
  213. JMP BX ;"return
  214. xrealcn POP BX ;Get real constant (inline)
  215. CS: ;get return addr
  216. PUSH [BX]$04 ;push that number
  217. CS:
  218. PUSH [BX]$02
  219. CS:
  220. PUSH [BX]
  221. ADD BX,#$06 ;skip constant
  222. JMP BX ;"return
  223. xstoreal POP BX ;Store real number
  224. POP AX ;get number
  225. POP CX
  226. POP DX
  227. POP DI ;get dest ptr
  228. POP ES
  229. ES: ;store number
  230. MOV [DI],AX
  231. ES:
  232. MOV [DI]$02,CX
  233. ES:
  234. MOV [DI]$04,DX
  235. JMP BX ;"return
  236. xadd POP errpos ;Add real numbers
  237. POP CX ;second number
  238. POP SI
  239. POP DI
  240. POP AX ;first number
  241. POP BX
  242. POP DX
  243. CALL readd ;do addition
  244. retest JB reovrerr ;:error
  245. repush PUSH DX ;store result on stack
  246. PUSH BX
  247. PUSH AX
  248. JMP [errpos] ;'return
  249. reovrerr MOV DL,#$01 ;Floating point overflow
  250. JMP runerr ;"
  251. xsub POP errpos ;Subtract real numbers
  252. POP CX ;second number
  253. POP SI
  254. POP DI
  255. POP AX ;first number
  256. POP BX
  257. POP DX
  258. CALL resub ;do subtraction
  259. JMP retest ;"put result, return
  260. xmul POP errpos ;Multiply real numbers
  261. POP CX ;second number
  262. POP SI
  263. POP DI
  264. POP AX ;first number
  265. POP BX
  266. POP DX
  267. xmul2 CALL remult ;do multiplication
  268. JMP retest ;"put result, return
  269. xdiv POP errpos ;Divide real numbers
  270. POP CX ;second number
  271. POP SI
  272. POP DI
  273. POP AX ;first number
  274. POP BX
  275. POP DX
  276. OR.B CL,CL ;second = 0 ?
  277. JZ xdiverr ;yes: div / 0 error
  278. CALL rediv ;divide
  279. JMP retest ;'put result, return
  280. xdiverr MOV DL,#$02 ;Division by zero attempted
  281. JMP runerr ;"
  282. xneg MOV BX,SP ;Neg real: get addr of number
  283. SS:
  284. CMP.B [BX]$02,#$00 ;zero ?
  285. JZ xnegzer ;:don't negate
  286. SS:
  287. XOR.B [BX]$07,#$80 ;invert sign
  288. xnegzer RET ;"
  289. xabs MOV BX,SP ;Abs real: get addr of number
  290. SS:
  291. AND.B [BX]$07,#$7F ;make positive
  292. RET ;"
  293. realeq POP errpos ;Real =
  294. POP CX ;second number
  295. POP SI
  296. POP DI
  297. POP AX ;first number
  298. POP BX
  299. POP DX
  300. CALL recmp ;compare real
  301. PUSH errpos ;restore ret
  302. MOV AX,#$0001 ;true
  303. JZ realeq1 ;equal: true
  304. DEC AX ;false
  305. realeq1 OR AX,AX ;set flags
  306. RET ;"
  307. realne POP errpos ;Real <>
  308. POP CX ;second number
  309. POP SI
  310. POP DI
  311. POP AX ;first number
  312. POP BX
  313. POP DX
  314. CALL recmp ;compare real
  315. PUSH errpos ;restore ret
  316. MOV AX,#$0001 ;true
  317. JNZ realne1 ;not equal: true
  318. DEC AX ;false
  319. realne1 OR AX,AX ;set flags
  320. RET ;"
  321. realge POP errpos ;Real >=
  322. POP CX ;second number
  323. POP SI
  324. POP DI
  325. POP AX ;first number
  326. POP BX
  327. POP DX
  328. CALL recmp ;compare real
  329. PUSH errpos ;restore ret
  330. MOV AX,#$0001 ;true
  331. JNB realge1 ;larger or equal: true
  332. DEC AX ;false
  333. realge1 OR AX,AX ;set flags
  334. RET ;"
  335. realle POP errpos ;Real <=
  336. POP CX ;second number
  337. POP SI
  338. POP DI
  339. POP AX ;first number
  340. POP BX
  341. POP DX
  342. CALL recmp ;compare real
  343. PUSH errpos ;restore ret
  344. MOV AX,#$0001 ;true
  345. JBE realle1 ;smaller or equal: true
  346. DEC AX ;false
  347. realle1 OR AX,AX ;set flags
  348. RET ;"
  349. realg POP errpos ;Real >
  350. POP CX ;second number
  351. POP SI
  352. POP DI
  353. POP AX ;first number
  354. POP BX
  355. POP DX
  356. CALL recmp ;compare real
  357. PUSH errpos ;restore ret
  358. MOV AX,#$0001 ;true
  359. JA realg1 ;larger: true
  360. DEC AX ;false
  361. realg1 OR AX,AX ;set flags
  362. RET ;"
  363. reall POP errpos ;Real <
  364. POP CX ;second number
  365. POP SI
  366. POP DI
  367. POP AX ;first number
  368. POP BX
  369. POP DX
  370. CALL recmp ;compare real
  371. PUSH errpos ;restore ret
  372. MOV AX,#$0001 ;true
  373. JB reall1 ;smaller: true
  374. DEC AX ;false
  375. reall1 OR AX,AX ;set flags
  376. RET ;"
  377. xsqr POP errpos ;Sqr real: save ret addr
  378. POP AX ;get number
  379. POP BX
  380. POP DX
  381. MOV CX,AX ;-> second number
  382. MOV SI,BX
  383. MOV DI,DX
  384. JMP xmul2 ;"do real multiplication
  385. xint POP errpos ;Int real: save ret addr
  386. POP AX ;get number
  387. POP BX
  388. POP DX
  389. CALL reint ;do Int
  390. JMP repush ;"push result
  391. xfrac POP errpos ;Frac real: save ret addr
  392. POP AX ;get number
  393. POP BX
  394. POP DX
  395. CALL refrac ;do Frac
  396. JMP repush ;"push result
  397. xrandom CALL dorandom ;Random real
  398. MOV DX,#$0080 ;original exponent
  399. MOV AL,#$20 ;max. count
  400. rrndnrm TEST.B BH,#$80 ;normalized ?
  401. JNZ rrndok ;:yes
  402. SHL CX,1 ;shift left 1 bit
  403. RCL BX,1
  404. DEC.B DL ;count down exponent
  405. DEC.B AL ;another bit ?
  406. JNZ rrndnrm ;:yes
  407. XOR.B DL,DL ;return zero
  408. rrndok AND.B BH,#$7F ;clear mantissa MSB
  409. POP AX ;ret addr
  410. PUSH BX ;push result
  411. PUSH CX
  412. PUSH DX
  413. JMP AX ;"return
  414. xround MOV CH,#$FF ;Round
  415. JMP.b trunc1 ;'
  416. xtrunc XOR.B CH,CH ;Trunc
  417. trunc1 POP BX ;ret addr
  418. POP AX ;get number
  419. POP DX
  420. POP DX
  421. PUSH BX ;restore ret
  422. trunc2 XCHG AX,DX ;put exp
  423. MOV CL,#$8F ;subtract exponent
  424. SUB.B CL,DL ;too big ?
  425. JB truncerr ;:overflow error
  426. CMP.B CL,#$0F ;too many shifts ?
  427. JA trunczer ;yes: 0
  428. INC.B CL
  429. MOV.B BH,AH ;save sign
  430. OR.B AH,#$80 ;set mantissa MSB
  431. SHR AX,CL ;shift right
  432. JNB trunc3 ;:nothing to round
  433. OR.B CH,CH ;round up ?
  434. JZ trunc3 ;:no
  435. INC AX ;round it up
  436. JS truncerr ;overflow: error
  437. trunc3 TEST.B BH,#$80 ;sign ?
  438. JZ truncrt ;:no
  439. NEG AX ;negate it
  440. truncrt RET ;'
  441. trunczer XOR AX,AX ;return 0
  442. RET ;'
  443. truncerr MOV DL,#$92 ;Out of integer range
  444. JMP runerrrt ;"
  445. xintreal CALL intreal ;Integer -> Real
  446. POP CX ;get ret
  447. PUSH DX ;push number
  448. PUSH BX
  449. PUSH AX
  450. JMP CX ;"return
  451. xintre2 POP errpos ;Int -> Real
  452. POP CX ;keep second number
  453. POP SI
  454. POP DI
  455. POP AX ;integer number
  456. CALL intreal ;do conversion
  457. PUSH DX ;push result
  458. PUSH BX
  459. PUSH AX
  460. PUSH DI ;push second number
  461. PUSH SI
  462. PUSH CX
  463. JMP [errpos] ;"return
  464. ;Square root. Algorithm: Newton
  465. ;x[n+1]:=0.5*(x[n]+c/x[n]) -> Sqrt(c)
  466. xsqrt POP errpos ;Sqrt: save ret addr
  467. POP AX ;get number
  468. POP BX
  469. POP DX
  470. MOV CX,AX ;-> second number
  471. MOV SI,BX
  472. MOV DI,DX
  473. OR.B AL,AL ;zero ?
  474. JZ sqrtdone ;yes: return
  475. TEST.B DH,#$80 ;test sign
  476. JNZ sqrterr ;negative: error
  477. MOV retrc1,AX ;store number
  478. MOV retrc2,BX
  479. MOV retrc3,DX
  480. ADD.B CL,#$80 ;make a guess for the
  481. SAR.B CL,1 ;exponent
  482. ADD.B CL,#$80
  483. MOV.B AL,CL
  484. SUB AL,#$14 ;end condition: difference
  485. MOV cvexpcnt,AL ;smaller than this
  486. sqrtloop MOV AX,retrc1 ;get original number
  487. MOV BX,retrc2
  488. MOV DX,retrc3
  489. CALL rediv2 ;real division /x[n]
  490. CALL readd2 ;real addition +x[n]
  491. DEC.B AL ;* 0.5 = dec exponent
  492. PUSH DX ;save x[n+1]
  493. PUSH BX
  494. PUSH AX ;test: end reached ?
  495. CALL resub ;real subtraction
  496. CMP.B AL,cvexpcnt ;test exponent
  497. POP CX ;restore x[n+1]
  498. POP SI
  499. POP DI
  500. JNB sqrtloop ;:not yet done
  501. sqrtdone PUSH DI ;return result
  502. PUSH SI
  503. PUSH CX
  504. JMP [errpos] ;'return
  505. sqrterr MOV DL,#$03 ;Sqrt argument error
  506. JMP runerr ;"
  507. ;*** Transcendental functions ***
  508. ;The algorithms used can be looked up in any formulary (!!!)
  509. xcos POP errpos ;Cos: save ret addr
  510. POP CX ;get number
  511. POP SI
  512. POP DI
  513. MOV AX,#$2181 ;-pi/2
  514. MOV BX,#$DAA2
  515. MOV DX,#$490F
  516. CALL resub ;real subtraction
  517. JMP.b sin1 ;'
  518. xsin POP errpos ;Sin: save ret addr
  519. POP AX ;get number
  520. POP BX
  521. POP DX
  522. sin1 CMP AL,#$6C ;small number ?
  523. JB sinpush ;yes: return immediately
  524. MOV CX,#$2183 ;2*pi
  525. MOV SI,#$DAA2 ;bring into range 0..2*pi
  526. MOV DI,#$490F
  527. PUSH DX ;save sign
  528. AND.B DH,#$7F ;make positive
  529. CALL recmp ;real comparison
  530. POP DX ;restore sign
  531. JB sinl2pi ;:ok
  532. CALL rediv2 ;real division, keep 2*pi
  533. PUSH DI ;save 2*pi
  534. PUSH SI
  535. PUSH CX
  536. CALL refrac ;Frac
  537. POP CX ;restore 2*pi
  538. POP SI
  539. POP DI
  540. CALL remult2 ;real mult, keep 2*pi
  541. sinl2pi TEST.B DH,#$80 ;negative ?
  542. JZ sinpos ;:no
  543. CALL readd2 ;add 2*pi
  544. sinpos DEC.B CL ;change to pi
  545. CALL recmp ;real comparison
  546. PUSHF ;save result
  547. JB sinlpi ;:below
  548. CALL resub2 ;subtract pi
  549. sinlpi DEC.B CL ;change to pi/2
  550. CALL recmp ;real comparison
  551. JB sinlpi2 ;:less
  552. INC.B CL
  553. OR.B DH,#$80 ;add -pi
  554. CALL readd
  555. sinlpi2 CMP AL,#$6C ;small number ?
  556. JB sinsmall ;yes:return
  557. MOV DI,#fltsin ;pointer to constants
  558. MOV CX,#$0007 ;7 numbers
  559. CALL poly1 ;do polynome
  560. sinsmall POPF ;flag: >pi
  561. JB sinpush ;:ok
  562. OR.B AL,AL ;neg, if not zero
  563. JZ sinpush ;:zero
  564. XOR.B DH,#$80 ;negate
  565. sinpush JMP repush ;"push result
  566. fltsin W $9D58,$9F39,$D73F ;-7.6471637318E-13 ;-1/15! constants for sin,cos
  567. W $4360,$309D,$3092 ; 1.6059043837E-10 ; 1/13!
  568. W $AA67,$283F,$D732 ;-2.5052103056E-08 ;-1/11!
  569. W $B66E,$1D2A,$38EF ; 2.7557319224E-06 ; 1/ 9!
  570. W $0D74,$00D0,$D00D ;-1.9841269841E-04 ;-1/ 7!
  571. W $887A,$8888,$0888 ; 8.3333333333E-03 ; 1/ 5!
  572. W $AB7E,$AAAA,$AAAA ;-1.6666666667E-01 ;"-1/ 3!
  573. xln POP errpos ;Ln (Logarithm)
  574. POP AX ;get number
  575. POP BX
  576. POP DX
  577. OR.B AL,AL ;zero ?
  578. JZ lnerr ;yes:error
  579. TEST.B DH,#$80 ;negative ?
  580. JZ lnok ;:no
  581. lnerr MOV DL,#$04 ;Ln argument error
  582. JMP runerr ;'
  583. lnok MOV.B CH,AH ;sign, LSB
  584. MOV CL,#$81 ;bring into range 1..2
  585. SUB.B AL,CL ;modify exponent
  586. CBW
  587. PUSH AX ;integer: exponent
  588. XCHG AX,CX ;set new exponent
  589. MOV CX,#$FB80 ;multiply *Sqrt(2)/2
  590. MOV SI,#$F333
  591. MOV DI,#$3504
  592. CALL remult ;multiplication
  593. MOV CX,AX ;first -> second number
  594. MOV SI,BX
  595. MOV DI,DX
  596. MOV AX,#$0081 ;first number = 1
  597. XOR BX,BX
  598. XOR DX,DX
  599. CALL readd2 ;addition +1
  600. PUSH DX ;save result
  601. PUSH BX
  602. PUSH AX
  603. MOV AX,#$0081 ;first = -1
  604. XOR BX,BX
  605. MOV DX,#$8000
  606. CALL readd ;addition -1
  607. POP CX ;restore result
  608. POP SI
  609. POP DI
  610. CALL rediv ;division (c-1)/(c+1)
  611. MOV DI,#fltln ;pointer to constants
  612. MOV CX,#$0006 ;6 numbers
  613. CALL poly1 ;do polynome
  614. INC.B AL ;result *2
  615. MOV CX,#$D27F ;+ ln(sqrt(2))
  616. MOV SI,#$17F7
  617. MOV DI,#$3172
  618. CALL readd ;addition
  619. POP CX ;get int exponent
  620. PUSH DX ;save result
  621. PUSH BX
  622. PUSH AX
  623. XCHG AX,CX ;exponent
  624. CALL intreal ;-> real
  625. MOV CX,#$D280 ;* ln(2)
  626. MOV SI,#$17F7
  627. MOV DI,#$3172
  628. CALL remult ;multiplication
  629. POP CX ;restore result
  630. POP SI
  631. POP DI
  632. CALL readd ;add
  633. CMP AL,#$67 ;do a cosmetic round-off (!!!)
  634. JNB lnround ;:no
  635. XOR AX,AX ;return zero
  636. XOR BX,BX
  637. XOR DX,DX
  638. lnround JMP repush ;"push result
  639. fltln W $8A7D,$D89D,$1D89 ; 7.6923076923E-02 ;1/13 Constants for Ln
  640. W $E97D,$8BA2,$3A2E ; 9.0909090909E-02 ;1/11
  641. W $8E7D,$38E3,$638E ; 1.1111111111E-01 ;1/ 9
  642. W $497E,$2492,$1249 ; 1.4285714286E-01 ;1/ 7
  643. W $CD7E,$CCCC,$4CCC ; 2.0000000000E-01 ;1/ 5
  644. W $AB7F,$AAAA,$2AAA ; 3.3333333333E-01 ;"1/ 3
  645. xexp POP errpos ;Exp: get return addr
  646. POP AX ;get number
  647. POP BX
  648. POP DX
  649. TEST.B DH,#$80 ;negative ?
  650. PUSHF ;remember flag
  651. AND.B DH,#$7F ;make it positive
  652. MOV CX,#$D280 ;/ln(2)
  653. MOV SI,#$17F7
  654. MOV DI,#$3172 ;(would be faster to use mult !)
  655. CALL rediv ;division
  656. CMP AL,#$88 ;too much ?
  657. JNB experr ;:yes, overflow
  658. PUSH DX ;save number
  659. PUSH BX
  660. PUSH AX
  661. INC.B AL ;* 2
  662. MOV CH,#$FF
  663. CALL trunc2 ;do Round
  664. POP CX ;restore number
  665. POP SI
  666. POP DI
  667. PUSH AX ;save integer part
  668. CALL intreal ;convert -> real
  669. OR.B AL,AL ;zero ?
  670. JZ expzer ;:yes
  671. DEC.B AL ;/ 2
  672. expzer XCHG AX,CX ;swap them
  673. XCHG BX,SI
  674. XCHG DX,DI
  675. CALL resub ;subtraction -> frac
  676. MOV DI,#fltexp ;ptr to constants
  677. MOV CX,#$0008 ;8 numbers
  678. CALL poly2 ;do polynome
  679. POP CX ;get exponent
  680. SHR CX,1 ;/ 2
  681. JNB expeven ;:even
  682. PUSH CX ;save it
  683. MOV CX,#$FB81 ;* Sqrt(2)
  684. MOV SI,#$F333
  685. MOV DI,#$3504
  686. CALL remult ;multiplication
  687. POP CX ;restore exponent
  688. expeven ADD.B AL,CL ;add exponents
  689. JB experr ;:overflow error
  690. POPF ;restore sign
  691. JZ exppush ;pos: store result
  692. MOV CX,AX ;negative: do 1/x -> x
  693. MOV SI,BX ;first -> second
  694. MOV DI,DX
  695. MOV AX,#$0081 ;first = 1
  696. XOR BX,BX
  697. XOR DX,DX
  698. CALL rediv ;division
  699. exppush JMP repush ;'push result
  700. experr POP AX ;clear stack
  701. MOV DL,#$01 ;Floating point overflow
  702. JMP runerr ;"
  703. fltexp W $2E6D,$111D,$3160 ; 1.3215486790E-06 ;ln(2)**8/8! Constants for Exp
  704. W $4670,$FE2C,$7FE5 ; 1.5252733804E-05 ;ln(2)**7/7!
  705. W $3674,$897C,$2184 ; 1.5403530393E-04 ;ln(2)**6/6!
  706. W $5377,$FF3C,$2EC3 ; 1.3333558146E-03 ;ln(2)**5/5!
  707. W $D27A,$5B7D,$1D95 ; 9.6181291076E-03 ;ln(2)**4/4!
  708. W $257C,$46B8,$6358 ; 5.5504108665E-02 ;ln(2)**3/3!
  709. W $167E,$EFFC,$75FD ; 2.4022650696E-01 ;ln(2)**2/2!
  710. W $D280,$17F7,$3172 ; 6.9314718056E-01 ;"ln(2)
  711. xarctan POP errpos ;ArcTan: get ret addr
  712. POP AX ;get number
  713. POP BX
  714. POP DX
  715. OR.B AL,AL ;zero ?
  716. JZ exppush ;yes: return
  717. XOR CX,CX ;clear neg flag
  718. TEST.B DH,#$80 ;negative ?
  719. JZ atnpos ;:no
  720. INC CX ;set neg flag
  721. AND.B DH,#$7F ;make positive
  722. atnpos PUSH CX ;save neg flag
  723. MOV CX,#$0081 ;second = 1
  724. XOR SI,SI
  725. XOR DI,DI
  726. CALL recmp ;real comparison
  727. JB atnsmall ;:x < 1
  728. XCHG AX,CX ;swap numbers
  729. XCHG BX,SI
  730. XCHG DX,DI
  731. CALL rediv ;division x -> 1/x
  732. POP CX ;restore neg flag
  733. INC CX ;set bits: large number
  734. INC CX
  735. PUSH CX ;push it again
  736. atnsmall MOV CX,#$4A7E ;> 0.1371 ?
  737. MOV SI,#$E98E
  738. MOV DI,#$0C6F
  739. CALL recmp ;real comparison
  740. JNB atnrng ;:yes
  741. CALL atnpoly ;do polynome
  742. JMP.b atndone ;'complete result
  743. atnrng MOV DI,#fltatnrg ;pointer into table
  744. MOV CX,#$0002
  745. atnrlp PUSH CX ;save index
  746. PUSH DI ;save ptr
  747. CS: ;test different ranges
  748. MOV CX,[DI] ;get table entry
  749. CS:
  750. MOV SI,[DI]$02
  751. CS:
  752. MOV DI,[DI]$04
  753. CALL recmp ;real comparison
  754. POP DI ;restore
  755. POP CX
  756. JB atnrfnd ;:smaller than that
  757. ADD DI,#$12 ;go to next entry
  758. LOOP atnrlp ;:another one
  759. SUB DI,#$06 ;save space in table
  760. atnrfnd ADD DI,#$06 ;go to associated number
  761. MOV retrc1,AX ;save number
  762. MOV retrc2,BX
  763. MOV retrc3,DX
  764. PUSH DI ;save ptr
  765. CS: ;get number from table
  766. MOV CX,[DI]
  767. CS:
  768. MOV SI,[DI]$02
  769. CS:
  770. MOV DI,[DI]$04
  771. CALL resub2 ;subtraction x-t
  772. PUSH DX ;save number
  773. PUSH BX
  774. PUSH AX
  775. MOV AX,retrc1 ;restore x
  776. MOV BX,retrc2
  777. MOV DX,retrc3
  778. CALL remult ;x*t
  779. MOV CX,#$0081 ;second = 1
  780. XOR SI,SI
  781. XOR DI,DI
  782. CALL readd ;addition
  783. MOV CX,AX ;first -> second
  784. MOV SI,BX
  785. MOV DI,DX
  786. POP AX ;restore x-t
  787. POP BX
  788. POP DX
  789. CALL rediv ;division -> (x-t)/(x*t+1)
  790. CALL atnpoly ;do polynome
  791. POP DI ;restore ptr
  792. ADD DI,#$06
  793. CS:
  794. MOV CX,[DI] ;get number
  795. CS:
  796. MOV SI,[DI]$02
  797. CS:
  798. MOV DI,[DI]$04
  799. CALL readd ;add it
  800. atndone POP CX ;get flag
  801. TEST.B CL,#$02 ;done 1/x ?
  802. JZ atnnorcp ;:no
  803. PUSH CX ;save flag
  804. MOV CX,AX ;first -> second
  805. MOV SI,BX
  806. MOV DI,DX
  807. MOV AX,#$2181 ;first = pi/2
  808. MOV BX,#$DAA2
  809. MOV DX,#$490F
  810. CALL resub ;subtraction pi/2-y
  811. POP CX ;restore flag
  812. atnnorcp TEST.B CL,#$01 ;negative ?
  813. JZ atnpos2 ;:no
  814. OR.B DH,#$80 ;set sign
  815. atnpos2 JMP repush ;"push result
  816. fltatnrg W $E77F,$CCCF,$5413 ; 4.1421356237E-01 ;1. tan(22.5) range table
  817. W $F67F,$A2F4,$0930 ; 2.6794919243E-01 ; tan(15) for ArcTan
  818. W $6A7F,$91C1,$060A ; 2.6179938780E-01 ; 15
  819. W $B580,$8A9E,$446F ; 7.6732698798E-01 ;2. tan(37.5)
  820. W $8280,$3A2C,$13CD ; 5.7735026919E-01 ; tan(30)
  821. W $6A80,$91C1,$060A ; 5.2359877560E-01 ; 30
  822. W $0081,$0000,$0000 ; 1.0000000000E+00 ;3. tan(45)
  823. W $2180,$DAA2,$490F ; 7.8539816340E-01 ;" 45
  824. fltatn W $E87D,$8BA2,$BA2E ;-9.0909090909E-02 ;-1/11 constants for ArcTan
  825. W $8E7D,$38E3,$638E ; 1.1111111111E-01 ; 1/ 9
  826. W $497E,$2492,$9249 ;-1.4285714286E-01 ;-1/ 7
  827. W $CD7E,$CCCC,$4CCC ; 2.0000000000E-01 ; 1/ 5
  828. W $AB7F,$AAAA,$AAAA ;-3.3333333333E-01 ;" 1/ 3
  829. atnpoly MOV DI,#fltatn ;ptr to ArcTan constants
  830. MOV CX,#$0005 ;5 of them
  831. poly1 PUSH DX ;do polynome: store number
  832. PUSH BX ;y:=x+c*x**3+b*x**5+a*x**7...
  833. PUSH AX
  834. PUSH CX ;save cnt
  835. PUSH DI ;save ptr
  836. MOV CX,AX ;first -> second
  837. MOV SI,BX
  838. MOV DI,DX
  839. CALL remult ;multiplication -> square
  840. POP DI ;restore cnt,ptr
  841. POP CX
  842. CALL poly2 ;do polynome 2
  843. POP CX ;get number -> second
  844. POP SI
  845. POP DI
  846. JMP remult ;"multiplication
  847. poly2 MOV retrc1,AX ;do polynome 2: store number
  848. MOV retrc2,BX ;y:=1+c*x+b*x**2+a*x**3...
  849. MOV retrc3,DX
  850. CS: ;get number from table
  851. MOV AX,[DI]
  852. CS:
  853. MOV BX,[DI]$02
  854. CS:
  855. MOV DX,[DI]$04
  856. PUSH CX ;save ptr, cnt
  857. PUSH DI
  858. JMP.b polystrt ;'start it
  859. polyloop PUSH CX ;save ptr, cnt
  860. PUSH DI
  861. CS:
  862. MOV CX,[DI] ;get number from table
  863. CS:
  864. MOV SI,[DI]$02
  865. CS:
  866. MOV DI,[DI]$04
  867. CALL readd ;add it
  868. polystrt MOV CX,retrc1 ;get x -> second
  869. MOV SI,retrc2
  870. MOV DI,retrc3
  871. CALL remult ;multiplication *x
  872. POP DI ;restore ptr, cnt
  873. POP CX
  874. ADD DI,#$06 ;go to next number
  875. LOOP polyloop ;:another one
  876. MOV CX,#$0081 ;second = 1
  877. XOR SI,SI
  878. XOR DI,DI
  879. JMP readd ;"add 1
  880. fmtreal PUSH BX ;Format real number
  881. CMP DX,#$19 ;number of fraction chars
  882. JB frnolim2 ;< 25:ok
  883. MOV AX,CX ;field width
  884. CALL limstind ;limit it
  885. MOV DL,#$07
  886. TEST.B [DI]$05,#$80 ;negative (DI:ptr to num)
  887. JZ frpos ;:no
  888. INC.B DL ;one char more
  889. frpos SUB.B AL,DL
  890. JNB frnound ;:no underflow
  891. XOR.B AL,AL ;negative: make zero
  892. frnound CMP AL,#$09 ;limit to 9
  893. JB frnolim
  894. MOV AL,#$09
  895. frnolim INC.B AL ;-> number of fraction chars
  896. MOV.B DL,AL
  897. MOV.B DH,AL
  898. frnolim2 PUSH DX ;save # fraction chars
  899. CALL realdec ;convert to decimal
  900. POP DX ;restore
  901. MOV.B AL,DL
  902. INC.B AL ;number of mantissa chars
  903. OR.B DH,DH
  904. JNZ frround
  905. ADD.B AL,CL
  906. JNS frlimprc
  907. MOV.B cvoutbuf,#$00 ;mark end of buffer
  908. JMP.b frfmtit ;'
  909. frlimprc CMP AL,#$0C ;max 11 digits shown
  910. JB frround ;:ok
  911. MOV AL,#$0B ;limit it
  912. frround CALL decround ;round up number
  913. frfmtit POP BX ;dest ptr
  914. MOV SI,#cvoutbuf ;source: dec buffer
  915. TEST.B CH,#$80 ;test sign
  916. JZ frpos2 ;:no
  917. MOV AL,#$2D ;put a -
  918. CALL frdigsto
  919. frpos2 MOV.B CH,CL ;exponent: number of int digs
  920. OR.B DH,DH ;size of number
  921. JZ frzer ;:zero
  922. MOV CH,#$00
  923. frzer OR.B CH,CH ;neg exponent ?
  924. JNS frint ;:no
  925. CALL frdig0 ;store 0 - no int part
  926. JMP.b frfrac0 ;'do fraction part
  927. frint CALL frdig ;put char from source
  928. DEC.B CH ;another one ?
  929. JNS frint ;:yes
  930. frfrac0 OR.B DL,DL ;test fraction len
  931. JZ frexp ;:nothing
  932. MOV AL,#$2E ;put a .
  933. CALL frdigsto
  934. frfill0 INC.B CH ;put zeroes as necessary
  935. JZ frfrac ;:exponent ok
  936. CALL frdig0 ;put a 0
  937. DEC.B DL ;field filled ?
  938. JNZ frfill0 ;:no
  939. frfrac DEC.B DL ;another fraction digit ?
  940. JS frexp ;:no
  941. CALL frdig ;do digit
  942. JMP frfrac ;'next one
  943. frexp OR.B DH,DH ;do exponent ?
  944. JNZ frputexp ;:yes
  945. RET ;'
  946. frputexp MOV AL,#$45 ;put an E
  947. CALL frdigsto
  948. MOV AL,#$2B ;+
  949. OR.B CL,CL ;test sign
  950. JNS frposexp ;:positive
  951. NEG.B CL ;negate exponent
  952. MOV AL,#$2D ;-
  953. frposexp CALL frdigsto ;store sign
  954. MOV AL,#$2F ;do DIV 10 / MOD 10
  955. frexpsub INC.B AL ;count up digit
  956. SUB.B CL,#$0A ;successive subtraction
  957. JNB frexpsub ;:continue
  958. CALL frdigsto ;put digit
  959. ADD.B CL,#$3A ;restore second digit
  960. MOV.B AL,CL ;put digit
  961. JMP.b frdigsto ;"
  962. frdig MOV.B AL,[SI] ;get digit from source
  963. OR.B AL,AL ;end ?
  964. JZ frdig0 ;:yes
  965. INC SI ;ptr to next char
  966. JMP.b frdigsto ;'store digit
  967. frdig0 MOV AL,#$30 ;store a 0
  968. frdigsto MOV.B [BX],AL ;store digit
  969. INC BX ;ptr to next dest char
  970. RET ;"
  971. realdec MOV AX,[DI] ;Real -> Decimal
  972. MOV BX,[DI]$02 ;get real number (in CS !)
  973. MOV DX,[DI]$04
  974. OR.B AL,AL ;zero ?
  975. JNZ rdno0 ;:no
  976. MOV SI,#cvoutbuf ;fill buffer with zeroes
  977. rdfill MOV [SI],#$3030
  978. INC SI
  979. INC SI
  980. CMP SI,#currfil ;end reached ?
  981. JNZ rdfill ;:no
  982. MOV CX,#$0000 ;exponent 0
  983. RET ;'
  984. rdno0 MOV.B CH,DH ;get sign
  985. AND.B DH,#$7F ;clear sign in mantissa
  986. PUSH AX ;save exp
  987. PUSH DX ;save mantissa
  988. SUB AL,#$80 ;exponent
  989. CBW
  990. MOV DX,#$004D ;* 77
  991. IMUL DX ;77/256 is about ln(2)/ln(10) !
  992. ADD AX,#$0005 ;+5
  993. MOV.B CL,AH ;this is approx. dec exponent
  994. POP DX ;restore
  995. POP AX
  996. CMP.B CL,#$D9 ;correct error
  997. JNZ rdnocomp ;:ok
  998. INC.B CL
  999. rdnocomp PUSH CX ;save exponent, sign
  1000. NEG.B CL ;negate exponent
  1001. CALL realrang ;bring into range
  1002. POP CX ;restore
  1003. CMP AL,#$81 ;exp ok ?
  1004. JNB rdnoadj ;:yes
  1005. CALL mult10 ;mult * 10
  1006. DEC.B CL ;count down dec exp
  1007. rdnoadj PUSH CX ;save exp, sign
  1008. OR.B DH,#$80 ;set mantissa MSB
  1009. MOV CL,#$84 ;offset for exponent
  1010. SUB.B CL,AL
  1011. MOV AL,#$00 ;LSB = 0
  1012. JZ rdnosh ;:no shift
  1013. rdshift SHR DX,1 ;convert to 6-byte-card
  1014. RCR BX,1
  1015. RCR AX,1
  1016. DEC.B CL ;shift again ?
  1017. JNZ rdshift ;:yes
  1018. rdnosh MOV SI,#cvoutbuf ;ptr to output buffer
  1019. rdconv MOV.B CH,DH ;get upper 4 bits
  1020. MOV CL,#$04
  1021. SHR.B CH,CL
  1022. ADD.B CH,#$30 ;-> digit
  1023. MOV.B [SI],CH ;store digit
  1024. AND.B DH,#$0F ;clear that digit
  1025. PUSH DX ;card * 10 -> card
  1026. PUSH BX ;save number
  1027. PUSH AX
  1028. SHL AX,1 ;card * 4
  1029. RCL BX,1
  1030. RCL DX,1
  1031. SHL AX,1
  1032. RCL BX,1
  1033. RCL DX,1
  1034. POP CX ;+ card
  1035. ADD AX,CX
  1036. POP CX
  1037. ADC BX,CX
  1038. POP CX
  1039. ADC DX,CX
  1040. SHL AX,1 ;* 2 = card * 10
  1041. RCL BX,1
  1042. RCL DX,1
  1043. INC SI ;next buffer pos
  1044. CMP SI,#currfil ;done ?
  1045. JNZ rdconv ;:no
  1046. POP CX ;restore exp, sign
  1047. RET ;"
  1048. decround XOR.B AH,AH ;Round up decimal number
  1049. MOV BX,#cvoutbuf ;ptr to buffer
  1050. ADD BX,AX ;add digit index
  1051. CMP.B [BX],#$35 ;5 ?
  1052. MOV.B [BX],#$00 ;store 0: end mark
  1053. JB drdone ;below: no round up
  1054. drloop DEC.B AL ;go back one digit
  1055. JS drincexp ;:beg of buffer reached
  1056. DEC BX ;go back one pos
  1057. INC.B [BX] ;inc that digit
  1058. CMP.B [BX],#$3A ;carry ?
  1059. JB drdone ;no: done
  1060. MOV.B [BX],#$00 ;mark as end
  1061. JMP drloop ;'continue
  1062. drincexp MOV.B [BX],#$31 ;store a 1
  1063. MOV.B [BX]$01,#$00 ;end mark
  1064. INC.B CL ;inc exponent
  1065. drdone RET ;"
  1066. ascreal MOV.B CL,[BX] ;String -> Real
  1067. CMP.B CL,#$2D ;- ?
  1068. JNZ arpos ;:no
  1069. INC BX ;next char
  1070. arpos PUSH CX ;save sign
  1071. CALL ascreal2 ;convert unsigned real
  1072. POP CX ;restore sign
  1073. JB arerr ;:error
  1074. CMP.B CL,#$2D ;- ?
  1075. JNZ arpos1 ;:no
  1076. CMP.B [DI],#$00 ;result = 0 ?
  1077. JZ arpos1
  1078. XOR.B [DI]$05,#$80 ;negate it
  1079. arpos1 CLC ;no error
  1080. arerr RET ;"
  1081. ascreal2 MOV SI,BX ;source ptr
  1082. XOR AX,AX ;ASCII -> unsigned real
  1083. XOR BX,BX ;clear result
  1084. XOR DX,DX
  1085. XOR CX,CX
  1086. MOV.B cvexpcnt,#$00 ;exponent
  1087. arloop MOV.B CL,[SI] ;get char
  1088. CMP.B CL,#$61 ;lower case ?
  1089. JB arupc ;:no
  1090. CMP.B CL,#$7A
  1091. JA arupc ;:no
  1092. SUB.B CL,#$20 ;convert to upper case
  1093. arupc CALL ardigit2 ;do a digit
  1094. JB arnodig ;:no digit
  1095. CALL mult10 ;result * 10
  1096. JB arover ;:overflow
  1097. PUSH DI ;save ptrs
  1098. PUSH SI
  1099. PUSH CX
  1100. PUSH DX ;save result
  1101. PUSH BX
  1102. PUSH AX
  1103. MOV.B AL,CL ;get digit
  1104. XOR.B AH,AH ;clear hi byte
  1105. CALL intreal ;convert to real
  1106. POP CX ;restore result
  1107. POP SI
  1108. POP DI
  1109. CALL readd ;add digit to result
  1110. POP CX ;restore ptrs
  1111. POP SI
  1112. POP DI
  1113. TEST.B CH,#$40 ;after decimal point ?
  1114. JZ arnext ;:yes
  1115. DEC.B cvexpcnt ;count down exponent
  1116. JMP.b arnext ;'next digit
  1117. arnodig CMP.B CL,#$2E ;decimal point ?
  1118. JNZ arexp ;:no, test exponent
  1119. TEST.B CH,#$40 ;. already done ?
  1120. STC ;error
  1121. JNZ arover ;yes: error
  1122. OR.B CH,#$40 ;set flag
  1123. arnext INC SI ;next char
  1124. JMP arloop ;'continue
  1125. arover MOV BX,SI ;pointer: end pos
  1126. RET ;'
  1127. arexp CMP.B CL,#$45 ;E ?
  1128. MOV.B CL,cvexpcnt ;exponent
  1129. JNZ arexp3 ;:no
  1130. CALL realrng ;bring into range
  1131. JB arover ;:error
  1132. INC SI ;go to next char
  1133. MOV.B CL,[SI] ;get it
  1134. CMP.B CL,#$2B ;+ ?
  1135. JZ arposexp ;:yes
  1136. CMP.B CL,#$2D ;- ?
  1137. JNZ arexp2 ;no: digit
  1138. OR.B CH,#$20 ;set flag: neg exponent
  1139. arposexp INC SI ;next char
  1140. arexp2 CALL ardigit ;do digit
  1141. JB arover ;:error
  1142. PUSH AX ;save
  1143. MOV.B AL,CL ;first digit
  1144. INC SI ;next char
  1145. CALL ardigit ;do digit
  1146. JB aronedig ;:no second digit
  1147. MOV.B AH,AL ;AL*10 -> AL
  1148. SHL.B AL,1
  1149. SHL.B AL,1
  1150. ADD.B AL,AH
  1151. SHL.B AL,1
  1152. ADD.B AL,CL
  1153. INC SI ;next char
  1154. aronedig MOV.B CL,AL ;new exponent
  1155. POP AX ;restore
  1156. TEST.B CH,#$20 ;negative exponent ?
  1157. JZ arexp3 ;:no
  1158. NEG.B CL ;negate it
  1159. arexp3 CALL realrng ;real number*10**exp
  1160. MOV [DI],AX ;store the result
  1161. MOV [DI]$02,BX
  1162. MOV [DI]$04,DX
  1163. JMP arover ;"set pointer to end
  1164. realrng CMP.B CL,#$DA ;outside a reasonable range ?
  1165. JL rrerr ;:yes
  1166. CMP.B CL,#$26
  1167. JG rrerr ;:yes
  1168. PUSH CX ;save pointers
  1169. PUSH SI
  1170. PUSH DI
  1171. CALL realrang ;bring into range
  1172. POP DI
  1173. POP SI
  1174. POP CX
  1175. RET ;'
  1176. rrerr STC ;error
  1177. RET ;"
  1178. ardigit MOV.B CL,[SI] ;get digit
  1179. ardigit2 CMP.B CL,#$30 ;< 0 ?
  1180. JB ardret ;:yes
  1181. CMP.B CL,#$3A ;> 9 ?
  1182. CMC ;change to error flag
  1183. JB ardret ;:yes
  1184. SUB.B CL,#$30 ;convert to number
  1185. ardret RET ;"
  1186. realrang PUSH DX ;bring into range:
  1187. PUSH BX ;number*10**CL
  1188. PUSH AX ;save number
  1189. MOV.B cvdecexp,CL ;save exponent
  1190. OR.B CL,CL ;negative ?
  1191. JNS rrpos ;:no
  1192. NEG.B CL ;make it positive
  1193. rrpos MOV.B BL,CL ;(exponent DIV 4)*6
  1194. AND.B BL,#$FC
  1195. MOV.B BH,BL
  1196. SHR.B BL,1
  1197. ADD.B BL,BH ;-> pointer into table
  1198. XOR.B BH,BH ;clear hi
  1199. LEA DI,[BX]fltdec ;factor table
  1200. CS:
  1201. MOV AX,[DI] ;get factor
  1202. CS:
  1203. MOV BX,[DI]$02
  1204. CS:
  1205. MOV DX,[DI]$04
  1206. AND.B CL,#$03 ;exponent MOD 4
  1207. JZ rrdone ;:ok
  1208. rrmul CALL mult10 ;do successive multiplications
  1209. DEC.B CL ;another ?
  1210. JNZ rrmul ;:yes
  1211. rrdone MOV CX,AX ;factor -> second
  1212. MOV SI,BX
  1213. MOV DI,DX
  1214. POP AX ;restore number
  1215. POP BX
  1216. POP DX
  1217. TEST.B cvdecexp,#$80 ;positive exponent ?
  1218. JNZ rrdiv ;:no
  1219. JMP remult ;'multiply num*factor
  1220. rrdiv JMP rediv ;"divide num/factor
  1221. fltdec W $0081,$0000,$0000 ; 1.0000000000E+00 ;decimal factor table
  1222. W $008E,$0000,$1C40 ; 1.0000000000E+04
  1223. W $009B,$2000,$3EBC ; 1.0000000000E+08
  1224. W $00A8,$A510,$68D4 ; 1.0000000000E+12
  1225. W $04B6,$C9BF,$0E1B ; 1.0000000000E+16
  1226. W $ACC3,$EBC5,$2D78 ; 1.0000000000E+20
  1227. W $CDD0,$1BCE,$53C2 ; 1.0000000000E+24
  1228. W $F9DE,$3978,$013F ; 1.0000000000E+28
  1229. W $2BEB,$ADA8,$1DC5 ; 1.0000000000E+32
  1230. W $C9F8,$CE7B,$4097 ; 1.0000000000E+36 ;"
  1231. mult10 OR.B AL,AL ;Real multiplication * 10
  1232. JNZ m10not0 ;:not zero
  1233. RET ;'zero - return
  1234. m10not0 OR.B DH,#$80 ;set mantissa MSB
  1235. PUSH CX ;save CX
  1236. PUSH DX ;save number
  1237. PUSH BX
  1238. PUSH AX
  1239. SHR DX,1 ;mantissa / 4
  1240. RCR BX,1
  1241. RCR.B AH,1
  1242. SHR DX,1
  1243. RCR BX,1
  1244. RCR.B AH,1
  1245. POP CX ;add mantissa
  1246. ADD.B AH,CH ;why no ADC (rounding !) ?
  1247. POP CX
  1248. ADC BX,CX
  1249. POP CX
  1250. ADC DX,CX
  1251. POP CX ;restore CX
  1252. JNB m10nrm
  1253. RCR DX,1 ;shift right
  1254. RCR BX,1
  1255. RCR.B AH,1
  1256. INC.B AL ;exponent+1
  1257. JNZ m10nrm ;:ok
  1258. STC ;overflow...
  1259. RET ;'
  1260. m10nrm AND.B DH,#$7F ;make positive
  1261. ADD AL,#$03 ;exponent+3
  1262. RET ;"
  1263. realcard POP SI ;Real -> long cardinal
  1264. POP DI ;2 ret addrs
  1265. POP DX ;get real
  1266. POP CX
  1267. POP BX
  1268. PUSH DI ;restore rets
  1269. PUSH SI
  1270. TEST.B BH,#$80 ;negative ?
  1271. JNZ rczero ;yes:return zero
  1272. OR.B BH,#$80 ;set mantissa MSB
  1273. MOV AL,#$A0 ;exponent offset
  1274. SUB.B AL,DL ;calc number of shifts
  1275. JB rcover ;:too much
  1276. CMP AL,#$20 ;too small ?
  1277. JNB rczero ;:return zero
  1278. rcdenorm OR.B AL,AL ;another shift ?
  1279. JZ rcdone ;:done
  1280. SHR BX,1 ;shift right: denormalize
  1281. RCR CX,1
  1282. DEC.B AL
  1283. JMP rcdenorm ;'next one
  1284. rcdone MOV AX,CX ;return number in DX:AX
  1285. MOV DX,BX
  1286. RET ;'
  1287. rczero XOR AX,AX ;return zero
  1288. XOR DX,DX
  1289. RET ;'
  1290. rcover MOV AX,#$FFFF ;return maxcard
  1291. MOV DX,#$FFFF
  1292. RET ;"
  1293. cardreal MOV BX,DX ;long cardinal -> real
  1294. MOV CX,AX
  1295. OR AX,DX ;0 ?
  1296. JZ crzero ;yes: return 0
  1297. MOV DX,#$00A0 ;exponent, LSB mantissa
  1298. crnorm TEST.B BH,#$80 ;normalized ?
  1299. JNZ crstore ;:yes
  1300. SHL CX,1 ;shift left
  1301. RCL BX,1
  1302. DEC.B DL ;count down exponent
  1303. JMP crnorm ;'continue
  1304. crstore AND.B BH,#$7F ;make positive
  1305. crzero POP AX ;return addr
  1306. PUSH BX ;push result
  1307. PUSH CX
  1308. PUSH DX
  1309. JMP AX ;"return
  1310. xassgntx MOV AL,#$01 ;text file
  1311. doassign MOV filfunc,AL ;do assign: store func code
  1312. POP BX ;ret addr
  1313. CALL getpn ;string -> ASCIIZ
  1314. POP DI ;ptr to file var
  1315. POP ES
  1316. PUSH BX ;restore ret
  1317. MOV AX,ES ;file var in DS ?
  1318. MOV DX,DS
  1319. CMP AX,DX
  1320. JNZ asnostd
  1321. CMP DI,#stdout ;std in / out file ?
  1322. JBE asgnerr ;:yes, error
  1323. asnostd PUSH DI ;save var ofs
  1324. MOV SI,#pnbuf ;path name buffer
  1325. LEA DI,[DI]$0C ;path name in file var
  1326. MOV CX,#$0020 ;copy 64 chars
  1327. CLD
  1328. REPZ
  1329. MOVS ;do it
  1330. POP DI ;restore file var ofs
  1331. CALL devtest ;test if device
  1332. JNB asnodev ;:yes
  1333. MOV AL,#$00 ;flag: not open
  1334. MOV BX,#$FFFF ;no handle
  1335. asnodev ES:
  1336. MOV [DI],BX ;store file handle
  1337. CMP.B filfunc,#$00 ;text file ?
  1338. JZ asnotxt ;:no
  1339. ES:
  1340. MOV.B [DI]$02,AL ;set file flag
  1341. LEA AX,[DI]$4C ;set buffer ofs
  1342. ES:
  1343. MOV [DI]$04,AX ;store in file var
  1344. RET ;'
  1345. asnotxt ES: ;set file var:
  1346. MOV [DI]$02,#$0000 ;record length
  1347. RET ;'
  1348. asgnerr MOV.B errnum,#$22 ;Assign to std files
  1349. RET ;"not allowed
  1350. xresettx XOR.B AL,AL ;Reset text file
  1351. JMP.b opentxt ;'
  1352. xrewrttx MOV AL,#$01 ;Rewrite text file
  1353. JMP.b opentxt ;'
  1354. xappndtx MOV AL,#$02 ;Append text file
  1355. opentxt MOV filfunc,AL ;store function code
  1356. POP errpos ;get ret addr
  1357. POP ES ;file var ptr
  1358. PUSH errpos ;restore ret
  1359. ES:
  1360. MOV.B AL,[DI]$02 ;test flag
  1361. AND AL,#$0F ;device ?
  1362. JZ otnodev ;:no
  1363. ES:
  1364. AND.B [DI]$02,#$DF ;clear flag: char preread
  1365. otret RET ;'
  1366. otnodev ES:
  1367. MOV [DI]$06,CX ;store buffer size
  1368. CALL close1 ;close file
  1369. CMP.B errnum,#$00 ;error ?
  1370. JNZ otret ;yes:ret
  1371. CALL openfile ;do open file
  1372. CMP.B errnum,#$00 ;error ?
  1373. JNZ otret ;yes:ret
  1374. TEST modeflg,#$0002 ;do device checking ?
  1375. JZ otnodev2 ;:no
  1376. MOV AX,#$4400 ;test device status
  1377. ES:
  1378. MOV BX,[DI] ;get file handle
  1379. CALL dos ;do it
  1380. TEST DX,#$0080 ;device ?
  1381. JZ otnodev2 ;:no
  1382. ES:
  1383. MOV [DI]$06,#$0001 ;buffer len: 1 char
  1384. otnodev2 CMP.B filfunc,#$01 ;read ?
  1385. JNB otappend ;:no
  1386. ES:
  1387. MOV.B [DI]$02,#$80 ;open for input
  1388. ES:
  1389. MOV BX,[DI]$04 ;buffer pos
  1390. ES:
  1391. MOV [DI]$08,BX ;-> buffer ptr
  1392. ES:
  1393. MOV [DI]$0A,BX ;-> buffer end
  1394. RET ;'
  1395. otappend JZ prepout ;write: prepare for output
  1396. MOV AX,#$4202 ;seek relative to EOF
  1397. ES:
  1398. MOV BX,[DI] ;file handle
  1399. XOR CX,CX ;offset 0
  1400. XOR DX,DX
  1401. CALL dos ;do it: get file length
  1402. ES:
  1403. MOV CX,[DI]$06 ;buffer size
  1404. CMP CX,#$0080 ;< 128 ?
  1405. JB otsmall ;yes: ok
  1406. MOV CX,#$0080 ;go back up to 128 bytes
  1407. otsmall SUB AX,CX ;sub from file pos
  1408. SBB DX,#$00
  1409. JNB otnotbeg ;:ok
  1410. ADD AX,CX ;beyond beg of file -
  1411. MOV CX,AX ;go to beg of file
  1412. XOR AX,AX
  1413. XOR DX,DX
  1414. otnotbeg PUSH CX ;save char count
  1415. MOV CX,DX ;dest pos
  1416. MOV DX,AX
  1417. MOV AX,#$4200 ;seek absolute
  1418. ES:
  1419. MOV BX,[DI] ;file handle
  1420. CALL dos ;do seek
  1421. CALL gbrdbuf ;read from buffer
  1422. POP DX ;counter
  1423. NEG DX
  1424. ES:
  1425. MOV SI,[DI]$08 ;buffer ptr
  1426. otsearch ES:
  1427. CMP.B [SI],#$1A ;search ^Z
  1428. JZ oteof ;:found
  1429. INC SI ;next char
  1430. INC DX
  1431. JNZ otsearch ;:continue
  1432. JMP.b prepout ;'EOF not found
  1433. oteof MOV AX,#$4202 ;seek from end
  1434. ES: ;DX = offset from end
  1435. MOV BX,[DI] ;file handle
  1436. MOV CX,#$FFFF ;backwards
  1437. CALL dos ;do seek
  1438. prepout ES: ;prepare for subsequent output
  1439. MOV.B [DI]$02,#$40 ;open for output
  1440. ES:
  1441. MOV AX,[DI]$04 ;buffer offset
  1442. ES:
  1443. MOV [DI]$08,AX ;-> buffer ptr
  1444. ES:
  1445. ADD AX,[DI]$06 ;+ buffer size
  1446. ES:
  1447. MOV [DI]$0A,AX ;-> buffer end
  1448. poret RET ;"
  1449. xtrunctx POP errpos ;Truncate text file
  1450. POP ES ;file var ptr
  1451. PUSH errpos ;restore ret
  1452. ES:
  1453. CMP.B [DI]$02,#$80 ;open for input ?
  1454. JNZ poret ;:no - ret
  1455. ES:
  1456. MOV DX,[DI]$08 ;buffer ptr
  1457. ES:
  1458. SUB DX,[DI]$0A ;- buffer end
  1459. JZ trend ;equal: ok
  1460. MOV AX,#$4201 ;seek relative
  1461. ES:
  1462. MOV BX,[DI] ;file handle
  1463. MOV CX,#$FFFF ;backwards
  1464. CALL dos ;do it
  1465. trend MOV AH,#$40 ;write
  1466. ES:
  1467. MOV BX,[DI] ;file handle
  1468. XOR CX,CX ;len = 0 -> truncate
  1469. CALL dos ;do it
  1470. JMP prepout ;"prepare for output
  1471. xflush POP errpos ;Flush
  1472. POP ES ;file var ptr
  1473. PUSH errpos ;restore ret
  1474. flush ES:
  1475. CMP.B [DI]$02,#$40 ;output file ?
  1476. JNZ flushret ;no: ret
  1477. JMP pbflush ;'flush buffer
  1478. flushret RET ;"
  1479. xclosetx POP errpos ;Close text file
  1480. POP ES ;get file var pt
  1481. PUSH errpos ;restore ret
  1482. close1 ES:
  1483. MOV.B AL,[DI]$02 ;get flags
  1484. AND AL,#$0F ;device ?
  1485. JNZ closeret ;yes: ret
  1486. CALL flush ;flush the buffer
  1487. ES:
  1488. MOV.B [DI]$02,#$00 ;clear flag
  1489. close2 ES:
  1490. MOV BX,[DI] ;file handle
  1491. CMP BX,#$02 ;standard file ?
  1492. JBE closeret ;:ret
  1493. CMP BX,#-$01 ;not open ?
  1494. JZ closeret ;yes:ret
  1495. ES:
  1496. MOV [DI],#$FFFF ;clear file handle
  1497. MOV AH,#$3E ;close file
  1498. CALL dos ;do it
  1499. JNB closeret ;:ok, no error
  1500. MOV.B errnum,#$FF ;file disappeared
  1501. closeret RET ;"
  1502. devtest MOV CX,#$0009 ;Test filename for device
  1503. MOV BX,#devtable
  1504. devloop PUSH CX ;save cnt, ptr
  1505. PUSH BX
  1506. MOV SI,#pnbuf ;file name
  1507. MOV CX,#$0003 ;3 chars
  1508. devcloop MOV.B AL,[SI] ;get char
  1509. CALL upcase ;ignore upper / lower
  1510. CS:
  1511. CMP.B AL,[BX] ;compare
  1512. JZ devnextc ;:ok
  1513. POP BX ;restore cnt, ptr
  1514. POP CX
  1515. ADD BX,#$06 ;next device
  1516. LOOP devloop ;another one ?
  1517. devnone STC ;not found
  1518. RET ;'
  1519. devnextc INC SI ;next char
  1520. INC BX
  1521. LOOP devcloop ;:another char
  1522. POP CX ;remove
  1523. POP CX
  1524. CMP.B [SI],#$3A ;next char = : ?
  1525. JNZ devnone ;:no device
  1526. CS:
  1527. MOV.B AL,[BX] ;get flag
  1528. CS:
  1529. MOV BX,[BX]$01 ;get file handle
  1530. RET ;"
  1531. devtable B "CON" ;Device table
  1532. B $C1,$FF,$FF ;input, output, dev 1
  1533. B "TRM"
  1534. B $C1,$FF,$FF ;input, output, dev 1
  1535. B "KBD"
  1536. B $82,$FF,$FF ;input, dev 2
  1537. B "LST"
  1538. B $43,$FF,$FF ;output, dev 3
  1539. B "AUX"
  1540. B $C4,$FF,$FF ;input, output, dev 4
  1541. B "USR"
  1542. B $C5,$FF,$FF ;input, output, dev 5
  1543. B "INP" ;std MS-DOS input-file
  1544. B $00,$00,$00 ;not open, handle 0
  1545. B "OUT" ;std MS-DOS output-file
  1546. B $00,$01,$00 ;not open, handle 1
  1547. B "ERR" ;std MS-DOS error file
  1548. B $00,$02,$00 ;"not open, handle 2
  1549. openfile ES: ;do open file
  1550. CMP [DI],#-$01 ;handle <> $ffff ?
  1551. JNZ opret ;yes: already open
  1552. MOV AX,#$3D02 ;open for input / output
  1553. MOV DL,#$01 ;error number
  1554. TEST.B filfunc,#$01 ;create file ?
  1555. JZ opnotnew ;:no
  1556. MOV AH,#$3C ;create
  1557. XOR CX,CX ;clear attribute
  1558. MOV DL,#$F1 ;error (dir full)
  1559. opnotnew PUSH DX ;save error number
  1560. LEA DX,[DI]$0C ;ptr to path name
  1561. CALL dos ;do it
  1562. POP DX ;restore error number
  1563. JB operr ;:error
  1564. ES:
  1565. MOV [DI],AX ;store file handle
  1566. RET ;'
  1567. operr MOV.B errnum,DL ;store error number
  1568. CMP AL,#$04 ;too many open files ?
  1569. JNZ opret ;:no
  1570. MOV.B errnum,#$F3 ;set that error
  1571. opret RET ;"
  1572. xstdin POP errpos ;Set standard input
  1573. MOV currfil,#stdin ;ptr to file var
  1574. MOV currfil1,DS
  1575. JMP [errpos] ;"return - error pos set
  1576. xrdfil POP errpos ;prepare for read
  1577. POP ES ;get file var ptr
  1578. MOV currfil,DI ;-> current file
  1579. MOV currfil1,ES
  1580. ES:
  1581. TEST.B [DI]$02,#$80 ;open for input ?
  1582. JNZ prret ;:yes
  1583. MOV.B errnum,#$02 ;error: not open for input
  1584. prret JMP [errpos] ;"return
  1585. xstdout POP errpos ;Set standard output
  1586. MOV currfil,#stdout ;ptr to file var
  1587. MOV currfil1,DS
  1588. JMP [errpos] ;"return
  1589. xwrfil POP errpos ;prepare for write
  1590. POP ES ;get file var ptr
  1591. MOV currfil,DI ;-> current file
  1592. MOV currfil1,ES
  1593. ES:
  1594. TEST.B [DI]$02,#$40 ;open for output ?
  1595. JNZ pwret ;:no
  1596. MOV.B errnum,#$03 ;error: not open for output
  1597. pwret JMP [errpos] ;"return
  1598. xrd MOV AL,#$FF ;Readln string
  1599. JMP.b readst ;'
  1600. xrdln XOR.B AL,AL ;Read string