TPSRC2 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600
  1. OR AX,AX
  2. JZ memin5 ;:no std in file
  3. MOV stdin,#$0000 ;set handle: std in
  4. MOV.B stdinfl,#$00 ;clear flag
  5. memin5 MOV stdoutof,DI ;buffer addr std output
  6. CS:
  7. MOV AX,[SI]$12 ;set std out buffer
  8. MOV stdoutsz,AX
  9. OR AX,AX
  10. JZ memin6 ;:no std out file
  11. MOV stdout,#$0001 ;set handle: std out
  12. MOV.B stdoutfl,#$00 ;clear flag:not open
  13. memin6 ADD SI,#$14 ;set return addr
  14. PUSH SI
  15. XOR AX,AX ;0 -> ES
  16. MOV ES,AX
  17. ES: ;save div / 0 interrupt
  18. MOV AX,div0vec
  19. MOV svintv,AX
  20. ES:
  21. MOV AX,availmem ;div0vec1
  22. MOV svintv1,AX
  23. ES: ;now set own routine
  24. MOV div0vec,#div0err
  25. ES:
  26. MOV availmem,CS ;div0vec1
  27. TEST modeflg,#$0008 ;set breakpoint int ?
  28. JZ memin7 ;:no
  29. ES:
  30. MOV int3vec,#brkint
  31. ES:
  32. MOV int3vec1,CS
  33. memin7 TEST modeflg,#$0004 ;test for ^C, ^S ?
  34. JZ memin8 ;:no
  35. MOV.B cbreak,#$01 ;set flag
  36. memin8 MOV verror,#$10D0 ;set error vec
  37. XOR AX,AX
  38. MOV errpos2,AX ;clear error pos
  39. MOV ovrpnbuf,AL ;clear ovrlay pathname
  40. MOV CX,stdinsz ;open std in for read
  41. PUSH DS
  42. MOV DI,#stdin
  43. CALL xresettx
  44. MOV CX,stdoutsz ;open std out for write
  45. PUSH DS
  46. MOV DI,#stdout
  47. CALL xrewrttx
  48. MOV.B errio,#$00 ;clear flag
  49. CALL xcrtinit ;CrtInit
  50. RET ;"
  51. readvers MOV AH,#$30 ;Read Version Number
  52. CALL dos ;do MS-DOS
  53. OR.B AL,AL ;Version 0 ?
  54. JZ verserr ;yes:error
  55. RET ;'
  56. verserr MOV DX,#msgdos
  57. JMP.b writerr ;'
  58. memerr MOV DX,#msgmem
  59. writerr PUSH CS ;CS -> DS
  60. POP DS
  61. MOV AH,#$09 ;print string
  62. CALL dos ;do MS-DOS
  63. MOV DX,#msgend
  64. MOV AH,#$09 ;print string
  65. CALL dos ;MS-DOS
  66. MOV AH,#$00 ;exit program
  67. CALL dos ;"do MS-DOS
  68. msgmem B "Not enough memory$"
  69. msgdos B "Incorrect DOS version$"
  70. msgend B $0D,$0A,"Program aborted",$0D,$0A,"$" ;"
  71. progend PUSH AX ;End of program
  72. PUSH DS ;AX=0:normal
  73. MOV DI,#stdin ;close std input
  74. CALL xclosetx
  75. PUSH DS
  76. MOV DI,#stdout ;close std output
  77. CALL xclosetx
  78. XOR AX,AX ;restore div / 0 int
  79. MOV ES,AX
  80. MOV AX,svintv
  81. ES:
  82. MOV div0vec,AX
  83. MOV AX,svintv1
  84. ES:
  85. MOV availmem,AX ;div0int1
  86. POP AX ;end flag
  87. TEST modeflg,#$0001 ;direct mode ?
  88. JNZ turbort ;yes: return to Turbo
  89. MOV AH,#$4C ;end process
  90. CALL dos ;'return to MS-DOS
  91. turbort MOV AH,#$80 ;close all files
  92. CALL dos
  93. PUSH turbocs ;set return addr
  94. MOV AX,#turboret
  95. PUSH AX
  96. PUSH DS ;DS -> ES
  97. POP ES
  98. MOV DS,turbods
  99. RETF ;"return to Turbo
  100. ;Uncrunch program
  101. ;This routine makes space for overlays, which are not stored
  102. ;in the main code file. It makes use of an inline data structure:
  103. ;+ 0:length of the block to move
  104. ;+ 2:destination addr of this block
  105. ;This makes a list which continues at the end of each block.
  106. uncrunch POP BX ;return addr
  107. CS:
  108. MOV AX,[BX] ;get block length
  109. OR AX,AX ;0 ?
  110. JZ uncrdone ;yes:end of list
  111. PUSH DS ;save DS
  112. PUSH CS ;CS -> DS
  113. POP DS
  114. PUSH CS ;CS -> ES
  115. POP ES ;push list on stack
  116. XOR DX,DX ;count blocks
  117. uncrlist MOV AX,[BX] ;get word
  118. OR AX,AX ;end of list ?
  119. JZ uncrstrt ;:yes
  120. PUSH BX ;push offset
  121. ADD BX,AX ;add offset
  122. INC DX ;count entry
  123. JMP uncrlist ;'continue
  124. uncrstrt MOV CX,BX ;last ptr
  125. POP BX ;get ptr from stack
  126. MOV SI,BX ;+4 -> beginning of block
  127. ADD SI,#$04
  128. MOV DI,[BX]$02 ;get destination addr
  129. CMP SI,DI ;the same ?
  130. JZ uncrno
  131. SUB CX,SI ;block length
  132. ADD SI,CX ;ptrs to last byte in block
  133. ADD DI,CX
  134. DEC SI
  135. DEC DI
  136. STD ;move backwards
  137. REPZ
  138. MOVS.B
  139. uncrno DEC DX ;another block ?
  140. JNZ uncrstrt ;:yes
  141. MOV [BX],#$0000 ;clear the list: uncrunched
  142. POP DS ;restore DS
  143. uncrdone ADD BX,#$04 ;skip inline data
  144. JMP BX ;"return
  145. ;Overlay header. Inline parameters:
  146. ;+ 0:currently valid procedure (ptr into file)
  147. ;+ 2:name of the overlay file
  148. ;+ F:start of the procedure code
  149. rdover POP SI ;get return addr
  150. CS: ;DX = file offset of proc wanted
  151. CMP DX,[SI] ;is it already there ?
  152. JNZ ovrread ;:no
  153. ovrcall ADD SI,#$0F ;skip filename
  154. JMP SI ;'jump into procedure
  155. ovrread PUSH AX ;AX = overlay length
  156. PUSH DX ;save overlay pos
  157. PUSH SI ;save dest addr
  158. MOV DI,#ovrpnbuf ;scan overlay pathname
  159. XOR.B AL,AL ;clear char buffer
  160. ovrscan MOV.B AH,AL ;buffer:last char
  161. MOV.B AL,[DI] ;get char
  162. OR.B AL,AL ;end of name ?
  163. JZ ovrpne ;:yes
  164. INC DI ;next char
  165. JMP ovrscan ;'continue scanning
  166. ovrpne PUSH DI ;save end pos
  167. OR.B AH,AH ;test last char
  168. JZ ovrnob ;:no path specified
  169. CMP.B AH,#$3A ;: ?
  170. JZ ovrnob ;:yes
  171. CMP.B AH,#$5C ;\ ?
  172. JZ ovrnob ;:yes
  173. MOV.B [DI],#$5C ;store a \ at the end
  174. INC DI
  175. ovrnob INC SI ;set to beg of filename
  176. INC SI
  177. ovrcopy CS: ;get char from filename
  178. MOV.B AL,[SI]
  179. MOV.B [DI],AL ;store in pathname
  180. INC SI
  181. INC DI ;next char
  182. OR.B AL,AL ;end ?
  183. JNZ ovrcopy ;no: continue
  184. MOV AX,#$3D00 ;open file
  185. MOV DX,#ovrpnbuf ;pathname
  186. PUSH DS ;DS -> ES
  187. POP ES
  188. CALL dos ;do it
  189. MOV BX,AX ;file handle
  190. POP DI ;restore parms
  191. POP SI
  192. POP DX
  193. MOV.B [DI],#$00 ;restore overlay pathname
  194. JB ovrerr ;:error
  195. CS: ;store pos as current pos
  196. MOV [SI],DX ;in the overlay header
  197. MOV AX,#$4200 ;seek absolute
  198. XOR.B CH,CH ;pos = DX*256
  199. MOV.B CL,DH
  200. MOV.B DH,DL
  201. XOR.B DL,DL
  202. CALL dos ;do it
  203. POP CX ;restore length
  204. JB ovrerr ;:error
  205. MOV AH,#$3F ;read byte block
  206. LEA DX,[SI]$0F ;destination addr
  207. PUSH DS ;save DS
  208. PUSH CS ;CS -> DS
  209. POP DS
  210. CALL dos ;do it
  211. POP DS ;restore DS
  212. JB ovrerr ;:error
  213. MOV AH,#$3E ;close file
  214. CALL dos
  215. JMP ovrcall ;'jump into procedure
  216. ovrerr MOV DL,#$F0 ;error: Overlay not found
  217. PUSH SI ;return addr
  218. JMP runerrrt ;"
  219. xovrpath POP BX ;OvrPath
  220. CALL getpn ;convert string -> ASCIIZ
  221. PUSH BX ;restore ret
  222. MOV SI,#pnbuf ;copy into overlay pathname
  223. MOV DI,#ovrpnbuf
  224. PUSH DS ;DS -> ES
  225. POP ES
  226. MOV CX,#$0020 ;64 bytes
  227. CLD
  228. REPZ
  229. MOVS
  230. RET ;"
  231. xkeypres DEC SP ;KeyPressed
  232. CALL [vkbdstat] ;check status
  233. RET ;"
  234. xgotoxy POP BX ;GotoXY
  235. POP CX ;column
  236. PUSH BX ;restore ret
  237. MOV.B DL,AL ;row-1
  238. MOV.B DH,CL ;column-1
  239. DEC.B DL ;(Turbo uses origin 1,1)
  240. DEC.B DH
  241. JMP setcpos ;"set position
  242. xparmstr MOV DX,AX ;ParamStr: # wanted string
  243. OR DX,DX ;0 ?
  244. JZ prmstr1
  245. CALL prmcnt1 ;search in parm line
  246. XCHG AX,BX ;string length -> AX
  247. prmstr1 POP BX ;return addr
  248. SUB SP,AX ;allot space for string
  249. DEC SP
  250. MOV DI,SP ;string dest
  251. PUSH DS ;save DS
  252. PUSH CS ;CS -> DS
  253. POP DS
  254. PUSH SS ;SS -> ES
  255. POP ES
  256. CLD ;move string
  257. STOS.B ;store length
  258. XCHG AX,CX ;-> count
  259. REPZ ;move string
  260. MOVS.B
  261. POP DS ;restore DS
  262. JMP BX ;"return
  263. xparmcnt XOR DX,DX ;ParamCount: count string entries
  264. prmcnt1 MOV DI,#paramlin ;parameter line
  265. CS:
  266. MOV.B CL,[DI] ;length of param line
  267. XOR.B CH,CH
  268. INC DI ;beginning of string
  269. XOR BX,BX ;clear parm cnt
  270. prmcsep JCXZ prmcst ;:end of line
  271. CS: ;search char <> tab, space
  272. MOV.B AL,[DI] ;read char
  273. CMP AL,#$20 ;space ?
  274. JZ prmcsep2 ;:continue
  275. CMP AL,#$09 ;tab ?
  276. JNZ prmcst ;no:start of parm
  277. prmcsep2 INC DI ;next char
  278. DEC CX ;count length
  279. JMP prmcsep ;'continue
  280. prmcst MOV SI,DI ;start of parm string
  281. prmcstl JCXZ prmcste ;end of line
  282. CS: ;search char = tab, space
  283. MOV.B AL,[DI] ;get char
  284. CMP AL,#$20 ;space ?
  285. JZ prmcste ;yes: end of parm
  286. CMP AL,#$09 ;tab ?
  287. JZ prmcste ;yes: end of parm
  288. INC DI ;next char
  289. DEC CX ;count length
  290. JMP prmcstl ;'continue searching
  291. prmcste MOV AX,DI ;end position - beg position
  292. SUB AX,SI
  293. JZ prmcrt ;=0:forget it
  294. INC BX ;count parm
  295. DEC DX ;search another parm ?
  296. JNZ prmcsep ;:yes
  297. prmcrt XCHG AX,BX ;return count, string length
  298. RET ;"
  299. xstrint MOV.B fmtfield,CL ;Str(Integer): max length
  300. MOV fmtsdst,DI ;dest ofs
  301. POP BX ;ret addr
  302. POP fmtsdst1 ;dest seg
  303. POP CX ;format
  304. POP AX ;number
  305. PUSH BX ;restore ret
  306. PUSH CX ;save format
  307. MOV BX,#pnbuf ;dest buffer
  308. CALL intasc ;Integer -> ASCII
  309. JMP.b str1 ;'store in string
  310. xstrreal MOV.B fmtfield,CL ;Str(Real): max length
  311. MOV fmtsdst,DI ;dest ofs
  312. POP BX ;ret addr
  313. POP fmtsdst1 ;dest seg
  314. POP DX ;format 2
  315. POP AX ;format 1
  316. MOV DI,#recvbuf ;buffer for real number
  317. POP [DI] ;pop real number
  318. POP [DI]$02
  319. POP [DI]$04
  320. PUSH BX ;restore ret
  321. PUSH AX ;format 1
  322. XCHG AX,CX ;format 2 -> AX
  323. MOV BX,#pnbuf ;dest buffer
  324. CALL fmtreal ;Real -> ASCII
  325. str1 POP CX ;format
  326. LES DI,fmtsdst ;ptr to dest string
  327. PUSH DI ;save begin pos
  328. MOV.B DL,fmtfield ;max. field size
  329. XOR.B DH,DH
  330. XCHG AX,BX ;endposition - buffer pos
  331. SUB AX,#pnbuf ;-> length
  332. SUB CX,AX ;max len - len
  333. JBE strcpy0 ;:too long
  334. strpad INC DI ;pad with spaces
  335. ES:
  336. MOV.B [DI],#$20
  337. INC.B DH ;count len
  338. CMP.B DH,DL ;= max len ?
  339. JZ strdone ;yes:done
  340. LOOP strpad ;continue padding
  341. strcpy0 XCHG AX,CX ;num len -> CX
  342. MOV BX,#pnbuf ;source ptr
  343. strcopy MOV.B AL,[BX] ;get char
  344. INC BX ;ptr to next
  345. INC DI
  346. ES:
  347. MOV.B [DI],AL ;store in string
  348. INC.B DH ;pos = max len ?
  349. CMP.B DH,DL
  350. JZ strdone ;yes: end it
  351. LOOP strcopy ;continue
  352. strdone POP DI ;restore dest ptr
  353. ES:
  354. MOV.B [DI],DH ;store length
  355. RET ;"
  356. xvalint XOR.B AL,AL ;Val(Integer)
  357. JMP.b val1 ;'
  358. xvalreal MOV AL,#$01 ;Val(Real)
  359. val1 MOV fmttype,AL ;store type
  360. MOV fmtpdst,DI ;pos ofs
  361. POP BX ;ret addr
  362. POP fmtpdst1 ;pos seg
  363. POP fmtvdst ;dest ofs
  364. POP fmtvdst1 ;dest seg
  365. CALL getstz ;get string from stack
  366. PUSH BX ;restore ret
  367. XOR AX,AX ;no error
  368. MOV BX,#pnbuf
  369. CMP.B [BX],AL ;null string ?
  370. JZ valrt ;:set pos, no change to dest
  371. CMP.B fmttype,AL ;integer ?
  372. JNZ val2 ;:no
  373. CALL ascint ;ASCIIZ -> Integer
  374. JB valerr ;:error
  375. LES DI,fmtvdst ;dest ptr
  376. ES:
  377. MOV [DI],AX ;store result
  378. JMP.b valend ;'get error pos
  379. val2 MOV DI,#recvbuf ;real dest
  380. CALL ascreal ;ASCIIZ -> Real
  381. JB valerr ;:error
  382. MOV SI,DI
  383. LES DI,fmtvdst ;move real into
  384. CLD ;dest var
  385. MOVS
  386. MOVS
  387. MOVS
  388. valend XOR AX,AX ;no error
  389. CMP.B [BX],AL ;end of buffer reached ?
  390. JZ valrt ;:yes
  391. valerr XCHG AX,BX ;calculate error pos
  392. SUB AX,#pnbuf0
  393. valrt LES DI,fmtpdst ;store error pos
  394. ES:
  395. MOV [DI],AX
  396. RET ;"
  397. getpn MOV CX,#$0040 ;get string from stack
  398. JMP.b gstz1 ;'max 64 chars
  399. getstz MOV CX,#$007F ;max 127 chars
  400. gstz1 MOV DI,#pnbuf ;dest buffer (redundant!)
  401. POP AX ;ret addr
  402. MOV SI,SP ;ptr to string
  403. SS:
  404. MOV.B DL,[SI] ;get length
  405. XOR.B DH,DH
  406. CMP CX,DX ;> max length ?
  407. JBE gstz2 ;yes, limit it
  408. MOV CX,DX ;take this length
  409. gstz2 INC DX
  410. INC SI ;skip length
  411. MOV DI,#pnbuf ;dest ptr
  412. PUSH DS ;DS -> ES
  413. POP ES
  414. PUSH SS ;SS -> DS
  415. POP DS
  416. CLD
  417. REPZ ;move string into buffer
  418. MOVS.B
  419. PUSH ES ;restore DS
  420. POP DS
  421. MOV.B [DI],#$00 ;store a 0 at the end
  422. ADD SP,DX ;remove string from stack
  423. JMP AX ;"return
  424. xrndmize MOV AH,#$2C ;Randomize: Get time
  425. CALL dos
  426. MOV rndseed1,CX ;store as random seed
  427. MOV rndseed,DX
  428. RET ;"
  429. xmovevar POP BX ;Move var - CX = length
  430. MOV DX,DS ;save DS
  431. MOV SI,DI ;source ofs
  432. POP DS ;source seg
  433. POP DI ;dest ofs
  434. POP ES ;dest seg
  435. CLD ;move var
  436. REPZ
  437. MOVS.B
  438. MOV DS,DX ;restore DS
  439. JMP BX ;"return
  440. xblkparm POP BX ;Copy var -> stack
  441. MOV DX,DS ;save DS
  442. MOV SI,DI ;source ofs
  443. POP DS ;source seg
  444. SUB SP,CX ;make space - CX = len
  445. MOV DI,SP ;dest ptr
  446. PUSH SS ;SS -> ES
  447. POP ES
  448. CLD ;move it
  449. REPZ
  450. MOVS.B
  451. MOV DS,DX ;restore DS
  452. JMP BX ;"return
  453. xfillchr POP BX ;FillChar
  454. POP CX ;number of bytes
  455. POP DI ;array ofs
  456. POP ES ;array seg
  457. CLD ;fill it - char in AL
  458. REPZ
  459. STOS.B
  460. JMP BX ;"return
  461. xmove XCHG AX,CX ;Move: Count -> CX
  462. MOV DX,DS ;save DS
  463. POP BX ;ret addr
  464. POP DI ;dest ofs
  465. POP ES ;dest seg
  466. POP SI ;source ofs
  467. POP DS ;source seg
  468. CLD ;forward move
  469. CMP SI,DI ;source > dest ?
  470. JNB domove ;yes: move forward
  471. ADD SI,CX ;set ptr to end of block
  472. ADD DI,CX
  473. DEC SI
  474. DEC DI
  475. STD ;move backwards
  476. domove REPZ ;do it
  477. MOVS.B
  478. MOV DS,DX ;restore DS
  479. JMP BX ;"return
  480. xsetregs POP BX ;Get parms for MsDos, Intr
  481. POP AX ;record seg
  482. PUSH BP ;save regs
  483. PUSH DS
  484. PUSH AX ;save record addr
  485. PUSH DI
  486. PUSH BX ;restore ret
  487. MOV SI,DI ;pointer -> source
  488. MOV DS,AX ;source segment
  489. CLD
  490. LODS ;AX value -> stack
  491. PUSH AX
  492. LODS ;BX value
  493. MOV BX,AX
  494. LODS ;CX value
  495. MOV CX,AX
  496. LODS ;DX value
  497. MOV DX,AX
  498. LODS ;BP value
  499. MOV BP,AX
  500. LODS ;SI value -> stack
  501. PUSH AX
  502. LODS ;DI value
  503. MOV DI,AX
  504. LODS ;DS value
  505. PUSH AX
  506. LODS ;ES value
  507. MOV ES,AX
  508. POP DS ;get DS,SI,AX from stack
  509. POP SI
  510. POP AX
  511. RET ;"
  512. xgetregs PUSHF ;store register values
  513. PUSH ES
  514. PUSH DI
  515. PUSH BP
  516. MOV BP,SP ;stack index
  517. LES DI,[BP]$0A ;get record ptr
  518. CLD ;store AX
  519. STOS
  520. MOV AX,BX ;store BX
  521. STOS
  522. MOV AX,CX ;store CX
  523. STOS
  524. MOV AX,DX ;store DX
  525. STOS
  526. POP AX ;store BP (from stack)
  527. STOS
  528. MOV AX,SI ;store SI
  529. STOS
  530. POP AX ;store DI (from stack)
  531. STOS
  532. MOV AX,DS ;store DS
  533. STOS
  534. POP AX ;store ES (from stack)
  535. STOS
  536. POP AX ;store flags (from stack)
  537. STOS
  538. POP BX ;return addr
  539. ADD SP,#$04 ;clear stack
  540. POP DS ;restore DS,BP
  541. POP BP
  542. JMP BX ;"return
  543. xindchk CMP AX,CX ;array index check
  544. JNB chklim1 ;AX>=limit CX:error
  545. RET ;'
  546. chklim1 MOV DL,#$90 ;Index out of range
  547. JMP.b runerrrt ;"
  548. NOP ;Range check CX<=AX<=DX
  549. xrngchk CMP AX,CX
  550. JL chkrng1 ;not enough:error
  551. CMP AX,DX
  552. JG chkrng1 ;too much:error
  553. RET ;'
  554. chkrng1 MOV DL,#$91 ;Scalar or subrange
  555. JMP.b runerrrt ;"out of range
  556. NOP ;Stack check
  557. xchkstk MOV AX,SP ;CX=space required
  558. SUB AX,CX ;SP-CX
  559. JB chkstk1 ;:error
  560. CMP AX,#$0200 ;getting tight ?
  561. JB chkstk1 ;:yes
  562. MOV CL,#$04 ;convert to segment
  563. SHR AX,CL
  564. MOV CX,SS
  565. ADD AX,CX
  566. CMP AX,hptop1 ;compare with heap top
  567. JB chkstk1 ;below:error
  568. RET ;'
  569. chkstk1 MOV DL,#$FF ;heap / stack collision
  570. JMP.b runerrrt ;"
  571. NOP ;Breakpoint interrupt
  572. brkint POP BX ;return addr
  573. POP AX ;AX
  574. POPF ;Flags
  575. PUSH BX ;restore ret
  576. OR.B cbreak,#$02 ;set flag: int test
  577. DEC SP
  578. CALL kbdstat ;Key pressed ?
  579. JZ brkno ;:no
  580. DEC SP
  581. CALL kbdget ;get that key
  582. brkno AND.B cbreak,#$01 ;restore flag
  583. CMP AL,#$03 ;^C ?
  584. JZ brkbrk ;:yes
  585. RET ;'
  586. brkbrk POP errpos ;get return addr
  587. ADD errpos,#$02 ;adjust for length of INT3
  588. brkmsg MOV DX,#$0001 ;error: break
  589. JMP.b error ;"
  590. xiores XOR AX,AX ;IOResult: clear AX
  591. XCHG.B AL,errnum ;read error, clear it
  592. RET ;"
  593. xiochk CMP.B errnum,#$00 ;check for I/O-error
  594. JNZ chkioerr
  595. RET ;'
  596. chkioerr MOV.B DL,errnum ;get error number
  597. MOV DH,#$01 ;I/O-error
  598. JMP.b error ;'display message
  599. div0err POP BX ;Div/0 interrupt
  600. POP AX ;take stuff from stack
  601. POPF
  602. PUSH BX ;restore ret
  603. MOV DL,#$04 ;div / 0
  604. runerrrt POP errpos ;error pos: return addr
  605. runerr MOV DH,#$02 ;runtime error
  606. error PUSH DX ;save error number
  607. CALL reinit1 ;reinit files, I/O
  608. POP DX ;error number
  609. MOV AX,errpos
  610. SUB AX,#$0003
  611. XCHG AX,errpos2 ;store pos of call
  612. OR AX,AX ;break ?
  613. JNZ errbrk ;:yes
  614. PUSH DX ;save error number
  615. PUSH DX
  616. PUSH errpos2
  617. CALL [verror] ;error handler
  618. POP DX ;restore err number
  619. errbrk CMP.B DH,#$01 ;Break ?
  620. JNB errrunio ;:no
  621. CALL prints
  622. B "^C",$0D,$0A,"User Break",$00
  623. JMP.b errwpos ;'
  624. errrunio MOV.B errio,#$FF ;set flag: real error
  625. JA errrun ;:runtime error
  626. CALL prints
  627. B $0D,$0A,"I/O",$00
  628. JMP.b errerr ;'
  629. errrun CALL prints
  630. B $0D,$0A,"Run-time",$00
  631. errerr CALL prints
  632. B " error ",$00
  633. MOV.B AL,DL ;write error number
  634. CALL whexbyte ;(hex)
  635. errwpos CALL prints
  636. B ", PC=",$00
  637. MOV AX,errpos2 ;display error pos
  638. CALL whexword
  639. CALL prints
  640. B $0D,$0A,"Program aborted",$0D,$0A,$00
  641. MOV AL,#$01 ;Program end: error
  642. JMP progend ;"
  643. RET $0004 ;"Error handler
  644. iabs OR AX,AX ;Abs(Integer):test sign
  645. JNS iabspos ;:positive, zero
  646. NEG AX ;negate it
  647. iabspos RET ;"
  648. irandom PUSH AX ;Random(Integer):save limit
  649. CALL dorandom ;do random
  650. POP BX ;get limit
  651. SHR AX,1 ;div 2
  652. CWD
  653. DIV BX ;do modulo
  654. XCHG AX,DX ;remainder -> AX
  655. RET ;"
  656. dorandom MOV BX,rndseed1 ;do random
  657. MOV CX,rndseed ;get seed
  658. PUSH BX ;save it
  659. PUSH CX
  660. MOV.B AL,BH ;permutate it
  661. MOV.B BH,BL
  662. MOV.B BL,CH
  663. MOV.B CH,CL
  664. XOR.B CL,CL
  665. RCR.B AL,1
  666. RCR BX,1
  667. RCR CX,1
  668. POP AX ;old seed
  669. ADD CX,AX ;add it
  670. POP AX
  671. ADC BX,AX
  672. MOV AX,#$62E9 ;add constant
  673. ADD CX,AX
  674. MOV AX,#$3619
  675. ADC BX,AX
  676. MOV rndseed1,BX ;new seed
  677. MOV rndseed,CX
  678. MOV AX,BX ;result
  679. RET ;"
  680. intasc OR AX,AX ;Integer -> ASCII
  681. JNS iapos ;:positive number
  682. NEG AX ;negate it
  683. MOV.B [BX],#$2D ;store a -
  684. INC BX
  685. iapos XOR.B CH,CH ;flag for leading zeroes
  686. MOV DX,#$2710 ;digit 10000
  687. CALL iadigit
  688. MOV DX,#$03E8 ;digit 1000
  689. CALL iadigit
  690. MOV DX,#$0064 ;digit 100
  691. CALL iadigit
  692. MOV DL,#$0A ;digit 10
  693. CALL iadigit
  694. MOV.B CL,AL ;do it direct
  695. JMP.b iadput ;'last digit
  696. iadigit XOR.B CL,CL ;clear digit
  697. iadsub INC.B CL ;do successive subtraction
  698. SUB AX,DX ;(faster than DIV)
  699. JNB iadsub ;:continue
  700. ADD AX,DX ;restore remainder
  701. INC.B CH ;flag:now print zeroes
  702. DEC.B CL ;dec number
  703. JNZ iadput ;:ok, non-zero
  704. DEC.B CH ;clear flag
  705. JZ iadnoput
  706. iadput ADD.B CL,#$30 ;convert to ASCII
  707. MOV.B [BX],CL ;store
  708. INC BX
  709. iadnoput RET ;"
  710. asccard XOR AX,AX ;Read integer number:clear result
  711. CMP.B [BX],#$24 ;$ ?
  712. MOV DX,#$000A ;base 10
  713. JNZ acdec ;no:ok
  714. MOV DL,#$10 ;base 16
  715. acloop INC BX ;go to next char
  716. acdec PUSH AX ;save previous result
  717. MOV.B AL,[BX] ;get char
  718. CALL upcase
  719. MOV.B CL,AL ;save char
  720. POP AX ;restore result
  721. SUB.B CL,#$30 ;digit < 0 ?
  722. JB acend ;:yes, end of number
  723. CMP.B CL,#$0A ;> 9 ?
  724. JB acdigok ;no:ok
  725. CMP.B DL,#$10 ;base = 16 ?
  726. JNZ acend ;no:end
  727. SUB.B CL,#$07 ;adjust hex
  728. CMP.B CL,#$0A ;< A ?
  729. JB acend ;:end
  730. CMP.B CL,#$10 ;> F ?
  731. JNB acend ;:end
  732. acdigok PUSH DX ;save base
  733. MUL DX ;do multiplication
  734. POP DX ;restore base
  735. JB acret ;:overflow
  736. XOR.B CH,CH ;clear hi byte
  737. ADD AX,CX ;add digit to result
  738. JNB acloop ;:no overflow, continue
  739. JMP.b acret ;'end it - overflow
  740. acend CMP.B DL,#$10 ;base 16 ?
  741. JZ acret ;:yes
  742. MOV CX,AX ;CX:=number*2
  743. ADD CX,CX
  744. acret RET ;"
  745. ascint MOV.B CL,[BX] ;read integer:test sign
  746. CMP.B CL,#$2D ;- ?
  747. JNZ aipos ;:no
  748. INC BX ;go to next char
  749. aipos PUSH CX ;save sign
  750. CALL asccard ;read integer
  751. POP CX ;restore sign
  752. JB aichk ;:might be wrong
  753. CMP.B CL,#$2D ;- ?
  754. JNZ ainoneg ;:no
  755. NEG AX ;negate it
  756. ainoneg CLC ;no error
  757. RET ;'
  758. aichk CMP AX,#$8000 ;$8000 ?
  759. JNZ aierr ;no:really error
  760. CMP.B CL,#$2D ;negative ?
  761. JNZ aierr ;no:overflow
  762. RET ;'yes:ok
  763. aierr STC ;return error
  764. RET ;"
  765. strload POP BX ;get string var -> stack
  766. POP ES ;source seg
  767. MOV SI,DI ;source ofs
  768. ES: ;get length
  769. MOV.B CL,[SI]
  770. XOR.B CH,CH ;-> count
  771. INC CX ;copy length, too
  772. SUB SP,CX ;make space on stack
  773. MOV DI,SP ;dest: new stack top
  774. PUSH DS ;save DS
  775. PUSH ES ;ES -> DS
  776. POP DS
  777. PUSH SS ;SS -> ES
  778. POP ES
  779. CLD ;move string to stack
  780. REPZ
  781. MOVS.B
  782. POP DS ;restore DS
  783. JMP BX ;"return
  784. xstrcn POP SI ;inline string -> stack
  785. CS: ;get length
  786. MOV.B CL,[SI]
  787. XOR.B CH,CH ;-> count
  788. INC CX ;copy length, too
  789. SUB SP,CX ;make space on stack
  790. MOV DI,SP ;dest: new stack top
  791. PUSH DS ;save DS
  792. PUSH CS ;CS -> DS
  793. POP DS
  794. PUSH SS ;SS -> ES
  795. POP ES
  796. CLD ;move string to stack
  797. REPZ ;puts SI to end of string
  798. MOVS.B
  799. POP DS ;restore DS
  800. JMP SI ;"return
  801. strstore POP DX ;store string from stack
  802. MOV.B AL,CL ;max. length dest
  803. MOV BX,SP ;stack base
  804. SS: ;get length of source string
  805. MOV.B CL,[BX]
  806. XOR.B CH,CH
  807. ADD BX,CX ;add to stack base
  808. INC BX ;+1
  809. SS:
  810. LES DI,[BX] ;get dest ptr
  811. MOV SI,SP ;source ptr:stack
  812. CMP.B CL,AL ;too long ?
  813. JBE stslenok ;:yes
  814. MOV.B CL,AL ;take real length
  815. SS:
  816. MOV.B [SI],AL ;store length on stack
  817. stslenok INC CX ;count
  818. PUSH DS ;save DS
  819. PUSH SS ;SS -> DS
  820. POP DS
  821. CLD ;move string
  822. REPZ
  823. MOVS.B
  824. POP DS ;restore DS
  825. LEA SP,[BX]$04 ;remove string, ptr
  826. JMP DX ;"return
  827. xldarrch POP BX ;store string on stack
  828. POP ES ;source seg
  829. MOV SI,DI ;source ofs
  830. XOR.B CH,CH ;CL=length
  831. SUB SP,CX ;make space on stack
  832. DEC SP
  833. MOV DI,SP ;dest addr
  834. SS:
  835. MOV.B [DI],CL ;store length
  836. INC DI
  837. PUSH DS ;save DS
  838. PUSH ES ;ES -> DS
  839. POP DS
  840. PUSH SS ;SS -> ES
  841. POP ES
  842. CLD ;move to stack
  843. REPZ
  844. MOVS.B
  845. POP DS ;restore DS
  846. JMP BX ;"return
  847. xstrparm POP BX ;String insert / delete
  848. XOR.B CH,CH ;CL=length
  849. MOV SI,SP ;string pos
  850. SS:
  851. MOV.B AL,[SI] ;get length
  852. XOR.B AH,AH
  853. SUB AX,CX ;compare length
  854. MOV DI,SI ;dest ptr
  855. ADD DI,AX ;+ difference
  856. OR AX,AX ;test direction
  857. JZ strret ;:same length
  858. JNS strins ;:make it shorter
  859. MOV SP,DI ;new stack top
  860. SS: ;insert - make string longer
  861. MOV.B CL,[SI] ;get length
  862. INC CX ;+1 -> count
  863. PUSH DS ;save DS
  864. PUSH SS ;SS -> DS
  865. POP DS
  866. PUSH SS ;SS -> ES
  867. POP ES
  868. CLD ;move it
  869. REPZ
  870. MOVS.B
  871. POP DS ;restore DS
  872. JMP.b strret ;'return
  873. strins SS: ;delete - shorten string
  874. MOV.B [SI],CL ;store new length
  875. ADD DI,CX ;go to end of string
  876. ADD SI,CX
  877. INC CX ;count+1
  878. PUSH DS ;save DS
  879. PUSH SS ;SS -> DS
  880. POP DS
  881. PUSH SS ;SS -> ES
  882. POP ES
  883. STD ;move it up
  884. REPZ
  885. MOVS.B
  886. POP DS ;restore DS
  887. INC DI ;beginning of string
  888. MOV SP,DI ;= new stack top
  889. strret JMP BX ;"return
  890. csteq CALL cmpstr ;Compare strings =
  891. MOV AX,#$0001
  892. JZ csteq1 ;equal:true
  893. DEC AX ;false
  894. csteq1 OR AX,AX ;set flags
  895. RET ;"
  896. cstne CALL cmpstr ;Compare strings <>
  897. MOV AX,#$0001
  898. JNZ cstne1 ;not equal:true
  899. DEC AX
  900. cstne1 OR AX,AX
  901. RET ;"
  902. cstge CALL cmpstr ;Compare strings >=
  903. MOV AX,#$0001
  904. JNB cstge1 ;larger or equal:true
  905. DEC AX
  906. cstge1 OR AX,AX
  907. RET ;"
  908. cstle CALL cmpstr ;Compare strings <=
  909. MOV AX,#$0001
  910. JBE cstle1 ;less or equal:true
  911. DEC AX
  912. cstle1 OR AX,AX
  913. RET ;"
  914. cstg CALL cmpstr ;Compare strings >
  915. MOV AX,#$0001
  916. JA cstg1 ;larger:true
  917. DEC AX
  918. cstg1 OR AX,AX
  919. RET ;"
  920. cstl CALL cmpstr ;Compare strings <
  921. MOV AX,#$0001
  922. JB cstl1 ;less:true
  923. DEC AX
  924. cstl1 OR AX,AX
  925. RET ;"
  926. cmpstr MOV DI,SP ;Compare strings
  927. ADD DI,#$04 ;ignore 2 ret addr
  928. SS:
  929. MOV.B CL,[DI] ;get len second string
  930. XOR.B CH,CH ;clr hi byte
  931. INC DI ;ptr to beg of string
  932. MOV SI,DI ;calc pos of first string
  933. ADD SI,CX ;add len
  934. SS:
  935. MOV.B DL,[SI] ;get len first string
  936. XOR.B DH,DH ;clr hi byte
  937. INC SI
  938. MOV BX,SI ;calc end pos of string
  939. ADD BX,DX ;for removing it
  940. MOV.B AL,CL ;second len
  941. MOV.B AH,DL ;first len
  942. CMP CX,DX ;compare them
  943. JBE csshrt ;:CX already shorter
  944. XCHG CX,DX ;shorter len -> CX
  945. csshrt OR CX,CX ;null string ?
  946. JZ csnull ;:yes
  947. PUSH DS ;save DS
  948. PUSH SS ;SS -> ES
  949. POP ES
  950. PUSH SS ;SS -> DS
  951. POP DS
  952. CLD ;compare strings on stack
  953. REPZ
  954. CMPS.B
  955. POP DS ;restore DS
  956. JNZ csnoteq ;:not equal - flags are set
  957. csnull CMP.B AH,AL ;compare len
  958. csnoteq POP DX ;return addr
  959. POP CX ;return addr caller
  960. MOV SP,BX ;remove strings from stack
  961. PUSH CX ;restore ret caller
  962. JMP DX ;"return
  963. xconcat POP errpos ;Concat: get return addr
  964. MOV DI,SP ;pos second string
  965. SS:
  966. MOV.B DL,[DI] ;len2
  967. XOR.B DH,DH
  968. MOV SI,DI ;go to start of first string
  969. INC SI
  970. ADD SI,DX
  971. SS:
  972. MOV.B CL,[SI] ;len1
  973. ADD.B DL,CL ;len1+len2 too long ?
  974. JB concerr ;yes:error
  975. SS:
  976. MOV.B [SI],DL ;store new len
  977. XOR.B CH,CH ;put first string in front
  978. SUB DI,CX ;of second
  979. MOV SP,DI ;get space on stack
  980. INC CX ;len1+1; len2 will be overwritten
  981. PUSH DS ;save DS
  982. PUSH SI ;save SI
  983. PUSH SS ;SS -> ES
  984. POP ES
  985. PUSH SS ;SS -> DS
  986. POP DS
  987. CLD ;move first string
  988. REPZ
  989. MOVS.B
  990. MOV DI,SI ;end addr of string 1
  991. POP SI ;end pos of concat string
  992. DEC SI
  993. DEC DI
  994. MOV CX,DX ;resulting length + 1
  995. INC CX
  996. STD
  997. REPZ ;copy it up
  998. MOVS.B
  999. POP DS ;restore DS
  1000. INC DI
  1001. MOV SP,DI ;remove garbage from stack
  1002. JMP [errpos] ;'return
  1003. concerr MOV DL,#$10 ;String too long
  1004. JMP runerr ;"
  1005. xcopy POP errpos ;Copy: get return addr
  1006. CALL limstind ;limit index (length)
  1007. MOV CX,AX ;-> CX
  1008. POP AX ;string pos
  1009. CALL chkstind ;check string index
  1010. DEC AX ;pos in string
  1011. MOV SI,SP ;addr of string
  1012. SS:
  1013. MOV.B DL,[SI] ;get length
  1014. XOR.B DH,DH
  1015. MOV DI,SP ;pos of dest
  1016. ADD DI,DX ;+ length
  1017. SUB DX,AX ;length > pos ?
  1018. JBE copnull ;no - return null string
  1019. ADD SI,AX ;begin pos of substring
  1020. CMP DX,CX ;length > num ?
  1021. JBE copend ;:yes, sub goes to end
  1022. ADD SI,CX ;pos end of substring
  1023. MOV DX,CX ;new length
  1024. PUSH DS ;save DS
  1025. PUSH SS ;SS -> ES
  1026. POP ES
  1027. PUSH SS ;SS -> DS
  1028. POP DS
  1029. STD ;move string
  1030. REPZ
  1031. MOVS.B
  1032. POP DS ;restore DS
  1033. JMP.b copmovd ;'return result
  1034. copnull XOR DX,DX ;length = 0
  1035. copmovd XCHG SI,DI ;point to beg of new string
  1036. copend SS:
  1037. MOV.B [SI],DL ;store length
  1038. MOV SP,SI ;remove the rest
  1039. JMP [errpos] ;"return
  1040. xlength POP BX ;Length
  1041. MOV DI,SP ;pos of string
  1042. SS:
  1043. MOV.B AL,[DI] ;get length
  1044. XOR.B AH,AH ;clr hi byte
  1045. ADD SP,AX ;remove string from stack
  1046. INC SP
  1047. JMP BX ;"return
  1048. xpos POP errpos ;Pos (search substring)
  1049. MOV DI,SP ;pos of string
  1050. SS:
  1051. MOV.B DL,[DI] ;length of
  1052. XOR.B DH,DH
  1053. INC DI ;begin pos of string
  1054. MOV SI,DI ;DI:string scanned
  1055. ADD SI,DX ;go to beg of pattern str
  1056. SS:
  1057. MOV.B CL,[SI] ;get pattern len
  1058. XOR.B CH,CH
  1059. INC SI ;SI:pattern string
  1060. MOV BX,SI ;calc stack end pos
  1061. ADD BX,CX ;to remove strings
  1062. XOR AX,AX ;find position
  1063. SUB DX,CX ;DX:length difference
  1064. JB posend ;pattern too long: not found
  1065. INC AX ;pos 1
  1066. OR CX,CX ;pattern = null ?
  1067. JZ posend ;yes: found
  1068. INC DX ;number of compares
  1069. PUSH DS ;save DS
  1070. PUSH SS ;SS -> ES
  1071. POP ES
  1072. PUSH SS ;SS -> DS
  1073. POP DS
  1074. CLD ;forward compare
  1075. posloop PUSH CX ;save parms
  1076. PUSH DI
  1077. PUSH SI
  1078. REPZ ;compare it
  1079. CMPS.B
  1080. POP SI ;restore parms
  1081. POP DI
  1082. POP CX
  1083. JZ posdone ;:found
  1084. INC AX ;next pos
  1085. INC DI
  1086. DEC DX ;another search ?
  1087. JNZ posloop ;:yes
  1088. XOR AX,AX ;not found = 0
  1089. posdone POP DS ;restore DS
  1090. posend MOV SP,BX ;remove strings
  1091. JMP [errpos] ;"return
  1092. xinsert MOV.B strdstln,CL ;Insert: max. dest len
  1093. MOV strpos,AX ;pos
  1094. POP BX ;return addr
  1095. POP strtrgt ;target string ptr
  1096. POP strtrgt1
  1097. MOV strobj,SP ;object string - on stack
  1098. MOV strobj1,SS
  1099. PUSH BX ;restore ret
  1100. LES DI,strtrgt ;target string
  1101. PUSH ES ;save ptr for storing result
  1102. PUSH DI
  1103. PUSH ES ;get target string
  1104. CALL strload ;-> stack
  1105. MOV AX,#$0001 ;Copy(target,1,pos-1)
  1106. PUSH AX
  1107. MOV AX,strpos
  1108. DEC AX
  1109. CALL xcopy ;do it
  1110. LES DI,strobj ;get obj string
  1111. PUSH ES
  1112. CALL strload ;-> stack
  1113. CALL xconcat ;concat strings
  1114. LES DI,strtrgt ;get target string
  1115. PUSH ES
  1116. CALL strload ;-> stack
  1117. PUSH strpos ;Copy(target,pos,255)
  1118. MOV AX,#$00FF
  1119. CALL xcopy ;do it
  1120. CALL xconcat ;concat strings
  1121. MOV.B CL,strdstln ;max. length
  1122. CALL strstore ;store string
  1123. JMP xlength ;"remove strings
  1124. xdelete MOV strnum,AX ;Delete: number of chars
  1125. POP BX ;ret addr
  1126. POP strpos ;pos in string
  1127. POP strtrgt ;target string
  1128. POP strtrgt1
  1129. PUSH BX ;restore ret
  1130. LES DI,strtrgt ;target string
  1131. PUSH ES ;save ptr for storing result
  1132. PUSH DI
  1133. PUSH ES ;get target
  1134. CALL strload ;-> stack
  1135. MOV AX,#$0001 ;Copy(target,1,pos-1)
  1136. PUSH AX
  1137. MOV AX,strpos
  1138. DEC AX
  1139. CALL xcopy ;do it
  1140. MOV AX,strpos
  1141. ADD AX,strnum ;pos+num
  1142. OR.B AH,AH ;test it
  1143. JNZ delnorem ;too big: nothing left
  1144. LES DI,strtrgt ;get target
  1145. PUSH ES
  1146. CALL strload ;-> stack
  1147. PUSH AX ;Copy(target,pos+num,255)
  1148. MOV AX,#$00FF
  1149. CALL xcopy ;do it
  1150. CALL xconcat ;concat strings
  1151. delnorem MOV CL,#$FF ;max len - never a problem
  1152. CALL strstore ;store string
  1153. RET ;"
  1154. xstrch POP BX ;String -> char
  1155. POP AX ;get string
  1156. DEC.B AL ;test length
  1157. JNZ stcherr ;<> 1:error
  1158. XCHG.B AL,AH ;char -> AL
  1159. JMP BX ;'return
  1160. stcherr MOV errpos,BX ;store error position
  1161. MOV DL,#$10 ;String too long
  1162. JMP runerr ;"
  1163. xchstr MOV SI,SP ;string -> substring
  1164. SS: ;(1 char)
  1165. MOV.B BL,[SI]$02 ;length of string
  1166. XOR.B BH,BH
  1167. SS:
  1168. MOV AX,[BX_SI]$03 ;get char
  1169. MOV.B AH,AL ;char
  1170. MOV AL,#$01 ;length = 1
  1171. SS:
  1172. MOV [BX_SI]$03,AX ;store in string
  1173. RET ;"
  1174. POP BX ;return string as function result
  1175. ADD SP,DX ;forget DX bytes on stack
  1176. MOV SI,SP ;pos of string
  1177. SS:
  1178. MOV.B AL,[SI] ;get its length
  1179. CMP.B AL,CL ;= CL (expected length) ?
  1180. JZ retstrt ;yes: done
  1181. XOR.B AH,AH
  1182. ADD SI,AX ;ptr to end of string
  1183. MOV DI,SP ;destination (must be longer)
  1184. XOR.B CH,CH
  1185. ADD DI,CX ;end of destination
  1186. XCHG AX,CX ;real length -> count
  1187. INC CX ;copy length, too
  1188. PUSH DS ;save DS
  1189. PUSH SS ;SS -> DS
  1190. POP DS
  1191. PUSH SS ;SS -> ES
  1192. POP ES
  1193. STD ;move backwards
  1194. REPZ
  1195. MOVS.B
  1196. POP DS ;restore DS
  1197. INC DI
  1198. MOV SP,DI ;new stack top
  1199. retstrt JMP BX ;"return
  1200. chkstind OR.B AH,AH ;Check string index
  1201. JNZ stinderr ;> 255:error
  1202. OR.B AL,AL
  1203. JZ stinderr ;0:error
  1204. RET ;'
  1205. stinderr MOV DL,#$11 ;Invalid string index
  1206. JMP runerr ;"
  1207. ;Get set. CL=bytes used, CH=bytes empty at beginning
  1208. xldset POP BX ;ret addr
  1209. POP DX ;source seg
  1210. MOV SI,DI ;source ofs
  1211. SUB SP,#$20 ;make space on stack
  1212. MOV DI,SP ;dest ptr
  1213. PUSH CX ;save crunch byte
  1214. PUSH SS ;SS -> ES
  1215. POP ES
  1216. CLD ;forward
  1217. OR.B CH,CH ;empty bytes at beginning
  1218. JZ sld2 ;:none
  1219. XOR.B AL,AL ;store zeroes
  1220. sldclr1 STOS.B
  1221. DEC.B CH
  1222. JNZ sldclr1 ;:another
  1223. sld2 PUSH DS ;save DS
  1224. MOV DS,DX ;DX -> DS
  1225. REPZ
  1226. MOVS.B ;move set
  1227. POP DS ;restore DS
  1228. POP CX ;restore crunch byte
  1229. MOV AH,#$20 ;calculate empty bytes
  1230. SUB.B AH,CH ;at end
  1231. SUB.B AH,CL
  1232. JZ sld3 ;:none
  1233. XOR.B AL,AL ;store zeroes
  1234. sldclr2 STOS.B
  1235. DEC.B AH
  1236. JNZ sldclr2 ;:another one
  1237. sld3 JMP BX ;"return
  1238. sldempty POP BX ;Make empty set
  1239. SUB SP,#$20 ;32 bytes on stack
  1240. MOV DI,SP ;dest addr
  1241. PUSH SS ;SS -> ES
  1242. POP ES
  1243. MOV CX,#$0010 ;do 32 bytes
  1244. XOR AX,AX ;fill with zeroes
  1245. CLD
  1246. REPZ
  1247. STOS
  1248. JMP BX ;"return
  1249. setincl CALL setindex ;Include element: calc index
  1250. SS:
  1251. OR.B [BX],AL ;include it
  1252. RET ;"
  1253. setinrng XCHG AX,CX ;Include range in set
  1254. POP BX ;ret addr
  1255. POP AX ;lower; upper is in CX
  1256. PUSH BX ;restore ret
  1257. SUB.B CL,AL ;upper < lower ?
  1258. JB srngnil
  1259. XOR.B CH,CH ;upper-lower -> count
  1260. INC CX
  1261. MOV.B AH,CL ;save count
  1262. CALL setindex ;calc set index (lower)
  1263. MOV.B CL,AH ;restore count
  1264. srngloop SS: ;include element in set
  1265. OR.B [BX],AL
  1266. SHL.B AL,1 ;for next bit
  1267. JNB srngbit ;:ok
  1268. INC BX ;go to next byte
  1269. MOV AL,#$01
  1270. srngbit LOOP srngloop ;:another element
  1271. srngnil RET ;"
  1272. setsto MOV SI,SP ;store set. CX as with load
  1273. INC SI
  1274. INC SI ;source addr
  1275. SS:
  1276. MOV DI,[SI]$20 ;get dest ofs
  1277. SS:
  1278. MOV ES,[SI]$22 ;dest seg
  1279. MOV.B DL,CH ;# empty bytes
  1280. XOR.B DH,DH
  1281. ADD SI,DX ;add to source addr
  1282. XOR.B CH,CH ;CL = # bytes used
  1283. PUSH DS ;save DS
  1284. PUSH SS ;SS -> DS
  1285. POP DS
  1286. CLD ;move used bytes
  1287. REPZ
  1288. MOVS.B
  1289. POP DS ;restore DS
  1290. RET $0024 ;"remove set, pointer
  1291. xsetparm POP BX ;Put set as procedure parm
  1292. MOV.B DL,CH ;bytes empty at beg
  1293. XOR.B DH,DH
  1294. XOR.B CH,CH ;bytes used
  1295. MOV SI,SP ;source addr
  1296. ADD SI,DX ;calc end pos
  1297. ADD SI,CX
  1298. MOV DI,SP ;dest addr
  1299. ADD DI,#$20
  1300. CMP SI,DI ;= end pos ?
  1301. JZ putsetrt
  1302. DEC SI ;go back one byte
  1303. DEC DI
  1304. PUSH DS ;save DS
  1305. PUSH SS ;SS -> ES
  1306. POP ES
  1307. PUSH SS ;SS -> DS
  1308. POP DS ;set is stored as compressed
  1309. STD ;local var
  1310. REPZ
  1311. MOVS.B ;do move it
  1312. POP DS ;restore DS
  1313. INC DI
  1314. MOV SP,DI ;remove empty space
  1315. putsetrt JMP BX ;"return
  1316. seteq MOV AX,#$0001 ;Set comparison =
  1317. JMP.b setcmp ;'
  1318. setne XOR AX,AX ;Set comparison <>
  1319. setcmp CALL setptrs ;set parms
  1320. REPZ ;compare sets
  1321. CMPS
  1322. MOV DS,DX ;restore DS
  1323. JZ setceq ;:equal
  1324. XOR AX,#$0001 ;invert result
  1325. setceq OR AX,AX ;test result
  1326. RET $0040 ;"remove sets from stack
  1327. setge XOR AX,AX ;Set comparison >=
  1328. JMP.b setcmp2 ;'
  1329. setle MOV AX,#$0001 ;Set comparison <=
  1330. setcmp2 CALL setptrs ;set parms
  1331. DEC AX ;'test type of comparison
  1332. JNZ setc2l ;:<=
  1333. XCHG DI,SI ;swap set1, set2
  1334. setc2l LODS ;get byte from set2
  1335. OR AX,[DI] ;include set1
  1336. SCAS ;compare with set1
  1337. JNZ setc2g ;:not the same
  1338. LOOP setc2l ;:continue
  1339. MOV AX,#$0001 ;true
  1340. JMP.b setc2rt ;'end it
  1341. setc2g XOR AX,AX ;false
  1342. setc2rt MOV DS,DX ;restore DS
  1343. OR AX,AX ;test result
  1344. RET $0040 ;"remove sets from stack
  1345. sunion CALL setptrs ;Set union: set parms
  1346. sunion1 LODS ;get byte set 2
  1347. OR AX,[DI] ;include set 1
  1348. STOS ;store in set 1
  1349. LOOP sunion1 ;:continue
  1350. MOV DS,DX ;restore DS
  1351. RET $0020 ;"remove set 2 from stack
  1352. sdiff CALL setptrs ;Set difference: set parms
  1353. sdiff1 LODS ;get byte set 2
  1354. NOT AX ;invert it
  1355. AND AX,[DI] ;take it from set 1
  1356. STOS ;store in set 1
  1357. LOOP sdiff1 ;:continue
  1358. MOV DS,DX ;restore DS
  1359. RET $0020 ;"remove set 2 from stack
  1360. sinter CALL setptrs ;Set intersection: set parms
  1361. sinter1 LODS ;get byte set 2
  1362. AND AX,[DI] ;intersect set 1
  1363. STOS ;store in set 1
  1364. LOOP sinter1 ;:continue
  1365. MOV DS,DX ;restore DS
  1366. RET $0020 ;"remove set 2 from stack
  1367. xsetin MOV BX,SP ;Set IN operation
  1368. SS: ;pos of set
  1369. MOV AX,[BX]$22 ;get parm
  1370. OR.B AH,AH ;> 255 ?
  1371. JZ setintst ;no: ok
  1372. XOR AX,AX ;false
  1373. JMP.b setnotin ;'return result
  1374. setintst CALL setindex ;calc set index
  1375. SS:
  1376. AND.B AL,[BX] ;test set element
  1377. MOV AX,#$0000 ;false
  1378. JZ setnotin ;not set: false
  1379. INC AX ;true
  1380. setnotin OR AX,AX ;test result
  1381. RET $0022 ;"remove set, parm
  1382. setindex MOV.B BL,AL ;Calculate set index, mask
  1383. XOR.B BH,BH ;BX = bit number
  1384. MOV CL,#$03 ;bit number DIV 8
  1385. SHR BX,CL
  1386. ADD BX,#$04 ;+SP+4 -> set ptr
  1387. ADD BX,SP
  1388. MOV.B CL,AL ;bit number MOD 8
  1389. AND.B CL,#$07
  1390. MOV AL,#$01 ;create bit mask
  1391. SHL.B AL,CL
  1392. RET ;"
  1393. setptrs MOV SI,SP ;Set parms for set ops
  1394. ADD SI,#$04 ;ptr set 2
  1395. MOV DI,SP ;skip two ret addrs
  1396. ADD DI,#$24 ;ptr set 1
  1397. MOV DX,DS ;save DS
  1398. PUSH SS ;SS -> ES
  1399. POP ES
  1400. PUSH SS ;SS -> DS
  1401. POP DS
  1402. MOV CX,#$0010 ;count: 32 bytes
  1403. CLD
  1404. RET ;"
  1405. ptreq CMP AX,BX ;Compare pointers DX:AX = CX:BX
  1406. MOV AX,#$0000 ;false
  1407. JNZ ptreqno ;:not equal
  1408. CMP DX,CX
  1409. JNZ ptreqno ;:not equal
  1410. INC AX ;true
  1411. ptreqno OR AX,AX ;set flags
  1412. RET ;"
  1413. ptrne CMP AX,BX ;Compare pointers <>
  1414. MOV AX,#$0001 ;true
  1415. JNZ ptrne1 ;not equal: true
  1416. CMP DX,CX
  1417. JNZ ptrne1 ;not equal: true
  1418. DEC AX ;false
  1419. ptrne1 OR AX,AX ;set flags
  1420. RET ;"
  1421. ;*** Real Operations ***
  1422. ;#1 #2 register usage
  1423. ;AX CX LSB, exponent
  1424. ;BX SI mantissa
  1425. ;DX DI MSB, sign
  1426. resub MOV resign,#$8000 ;Do real subtraction
  1427. JMP.b ra1 ;'
  1428. readd MOV resign,#$0000 ;Do real addition
  1429. ra1 OR.B CL,CL ;second = 0 ?
  1430. JZ raret ;:yes, done
  1431. XOR DI,resign ;change sign2, if sub
  1432. OR.B AL,AL ;first = 0 ?
  1433. JNZ ranotriv ;:no
  1434. raretn2 MOV AX,CX ;second -> result
  1435. MOV BX,SI
  1436. MOV DX,DI
  1437. raret RET ;'
  1438. ranotriv CMP.B AL,CL ;compare exponents
  1439. JBE ranoswap ;AL <= CL !
  1440. XCHG AX,CX ;otherwhise swap numbers
  1441. XCHG BX,SI
  1442. XCHG DX,DI
  1443. ranoswap MOV.B cvdecexp,CL ;save exp2
  1444. SUB.B CL,AL ;exponent difference
  1445. CMP.B CL,#$28 ;first number too small ?
  1446. JB ranoundr ;:no
  1447. MOV.B CL,cvdecexp ;restore exp2
  1448. JMP raretn2 ;'second -> result
  1449. ranoundr MOV resign,DI ;save MSB 2
  1450. AND.B resave,#$80 ;mask out mantissa
  1451. MOV remant,DI ;save MSB 2
  1452. XOR.B remant1,DH
  1453. OR DI,#$8000 ;remove sign
  1454. OR.B DH,#$80 ;remove sign
  1455. raadj16l CMP.B CL,#$10 ;shift first in 16-bit-steps
  1456. JB raadj8 ;:done
  1457. MOV.B AH,BH ;do it.
  1458. MOV BX,DX ;first num is shifted to make
  1459. XOR DX,DX ;exp1 = exp2
  1460. SUB.B CL,#$10
  1461. JMP raadj16l ;'try again
  1462. raadj8 CMP.B CL,#$08 ;shift first in 8-bit-steps
  1463. JB raadj8l ;:done
  1464. MOV.B AH,BL ;do it
  1465. MOV.B BL,BH
  1466. MOV.B BH,DL
  1467. MOV.B DL,DH
  1468. XOR.B DH,DH
  1469. SUB.B CL,#$08 ;count down difference
  1470. raadj8l OR.B CL,CL ;test difference
  1471. JZ raadjend ;:adjustment done
  1472. raadj1l SHR DX,1 ;shift right in 1-bit-steps
  1473. RCR BX,1
  1474. RCR.B AH,1
  1475. DEC.B CL
  1476. JNZ raadj1l ;:continue
  1477. raadjend MOV AL,cvdecexp ;get exp2
  1478. TEST.B remant1,#$80 ;test sign
  1479. JNZ radosub ;:negative
  1480. ADD.B AH,CH ;add mantissa
  1481. ADC BX,SI
  1482. ADC DX,DI
  1483. JNB rasign ;:ok
  1484. RCR DX,1 ;do normalization
  1485. RCR BX,1
  1486. RCR.B AH,1
  1487. INC.B AL ;inc exponent
  1488. JNZ rasign ;:ok
  1489. STC ;overflow error
  1490. RET ;'
  1491. radosub XCHG.B AH,CH ;exchange numbers
  1492. XCHG BX,SI
  1493. XCHG DX,DI
  1494. SUB.B AH,CH ;subtract numbers
  1495. SBB BX,SI
  1496. SBB DX,DI
  1497. JNB ranoneg ;:no underflow
  1498. XOR.B resave,#$80 ;change sign
  1499. NOT.B AH ;negate mantissa
  1500. NOT BX ;= inverted mantissa + 1
  1501. NOT DX
  1502. ADD.B AH,#$01
  1503. ADC BX,#$00
  1504. ADC DX,#$00
  1505. ranoneg MOV CL,#$05 ;normalize number
  1506. ranrm8l OR.B DH,DH ;upper byte empty ?
  1507. JNZ ranrm1l ;:no
  1508. MOV.B DH,DL ;shift left 8 bits
  1509. MOV.B DL,BH
  1510. MOV.B BH,BL
  1511. MOV.B BL,AH
  1512. XOR.B AH,AH
  1513. SUB AL,#$08 ;sub 8 from exp
  1514. JB razero ;:underflow, return 0
  1515. DEC.B CL ;count down bytes
  1516. JNZ ranrm8l ;:another one
  1517. JMP.b razero ;'underflow
  1518. ranrm1l TEST.B DH,#$80 ;Mantissa MSB must be 1
  1519. JNZ rasign ;:yes, done
  1520. SHL.B AH,1 ;shift left 1 bit
  1521. RCL BX,1
  1522. RCL DX,1
  1523. DEC.B AL ;sub 1 from exp
  1524. JNZ ranrm1l ;:ok
  1525. razero XOR AX,AX ;underflow, return zero
  1526. XOR BX,BX
  1527. XOR DX,DX
  1528. RET ;'
  1529. rasign AND.B DH,#$7F ;clear MSB mantissa
  1530. XOR.B DH,resave ;set correct sign
  1531. RET ;"
  1532. remult OR.B CL,CL ;Real multiplication: second=0 ?
  1533. JZ rmzero ;yes: return zero
  1534. OR.B AL,AL ;first=0 ?
  1535. JZ rmret ;yes: done
  1536. ADD.B AL,CL ;add exponents
  1537. CALL testexp ;test exponent
  1538. MOV remul11,AX ;save first number
  1539. MOV remul12,BX
  1540. MOV remul13,DX
  1541. XOR.B AH,AH ;clear result
  1542. XOR BX,BX
  1543. XOR DX,DX
  1544. MOV DI,#remul21 ;ptr to second mantissa
  1545. MOV CL,#$05 ;do 5 bytes
  1546. rmbyt INC DI ;get byte from second mantissa
  1547. MOV.B CH,[DI]
  1548. OR.B CH,CH ;0 ?
  1549. JNZ rmdomul ;no: do multiplication
  1550. MOV.B AH,BL ;just shift result
  1551. MOV.B BL,BH ;8 bits right
  1552. MOV.B BH,DL
  1553. MOV.B DL,DH
  1554. XOR.B DH,DH
  1555. JMP.b rmnxtbyt ;'next step
  1556. rmdomul MOV SI,#$0008 ;do 8 bits
  1557. rmmul RCR.B CH,1 ;get bit
  1558. JNB rmbit0 ;:not set
  1559. ADD.B AH,remul11a ;add mantissa 1 to result
  1560. ADC BX,remul12
  1561. ADC DX,remul13
  1562. rmbit0 RCR DX,1 ;shift result 1 bit right
  1563. RCR BX,1
  1564. RCR.B AH,1
  1565. DEC SI ;another bit ?
  1566. JNZ rmmul ;:yes
  1567. rmnxtbyt DEC.B CL ;another byte ?
  1568. JNZ rmbyt ;:yes
  1569. XCHG AX,CX ;save AX, CL
  1570. LAHF ;save flags
  1571. TEST.B DH,#$80 ;already normalized ?
  1572. JNZ rmnoadj ;:yes
  1573. SAHF ;restore flags
  1574. RCL.B CH,1 ;shift 1 bit left
  1575. RCL BX,1
  1576. RCL DX,1
  1577. OR.B CL,CL ;check exp
  1578. JZ rmnoadj ;:underflow
  1579. DEC.B CL ;sub 1 from exp
  1580. rmnoadj XCHG AX,CX ;restore AX, CL
  1581. XOR.B DH,resave ;set sign
  1582. OR.B AL,AL ;test exponent
  1583. JNZ rmret ;:ok
  1584. rmzero XOR AX,AX ;return zero
  1585. XOR BX,BX
  1586. XOR DX,DX
  1587. rmret RET ;"
  1588. rediv OR.B AL,AL ;Real division
  1589. JZ rmret ;first=0:done
  1590. SUB.B AL,CL ;sub exponents
  1591. CMC
  1592. CALL testexp ;test exponent
  1593. MOV remul11,AL ;save exponent
  1594. MOV DI,#remul21b ;ptr to dest
  1595. MOV CL,#$05 ;5 bytes
  1596. MOV SI,#$0008 ;8 bits
  1597. rdloop CMP DX,remul23 ;compare with num2
  1598. JNZ rdcmp
  1599. CMP BX,remul22
  1600. JNZ rdcmp