home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / ASMUTL / CHEAPASM.ZIP / CHASM.BAS (.txt) next >
Encoding:
GW-BASIC  |  1987-01-11  |  35.0 KB  |  1,170 lines

  1. 10000  '***********************************
  2. 10010  '* PROGRAM CHASM      Version 1.9  *
  3. 10020  '*                                 *
  4. 10030  '* CHeap ASseMbler for the IBM PC. *
  5. 10040  '*                                 *
  6. 10050  '* Begun 6/15/82 by Dave Whitman   *
  7. 10060  '***********************************
  8. 10070  '
  9. 10080  'main program
  10. 10090     GOSUB 50000   'initialize
  11. 10100    'wipe out transient code
  12. 10110    CHAIN MERGE "chasm.ovl",10120,ALL,DELETE 50000-51570
  13. 10120    GOSUB 19950   'set up sym table
  14. 10130    GOSUB 10170   'pass 1: build sym table
  15. 10140    GOSUB 10380   'pass 2: generate obj code & listing
  16. 10150    GOSUB 19490   'clean up
  17. 10160  SYSTEM
  18. 10170  '*******************************************
  19. 10180  '* SUBROUTINE PASSONE                      *
  20. 10190  '* Adds user-defined symbols to sym table. *
  21. 10200  '*******************************************
  22. 10210  '
  23. 10220  PASS = 1
  24. 10230  LOCTR = 256   '0-255 reserved for p.s. prefix
  25. 10240  LINENUM = 0
  26. 10250  WHILE NOT EOF(1)
  27. 10260   'get source line, initialize
  28. 10270     GOSUB 10620   'getline
  29. 10280   'parse it
  30. 10290     GOSUB 10730  'parse
  31. 10300   'if label, enter in sym table
  32. 10310     IF LABEL$ <> "" THEN GOSUB 11640  'newentry
  33. 10320   'if op, decode, & update loctr
  34. 10330     IF OP$ <> "" THEN GOSUB 12480   'update_loctr
  35. 10340   'progress report
  36. 10350     GOSUB 19850
  37. 10360   WEND
  38. 10370  RETURN
  39. 10380  '*********************************
  40. 10390  '* SUBROUTINE PASSTWO            *
  41. 10400  '* Generates obj code & listing. *
  42. 10410  '*********************************
  43. 10420  '
  44. 10430  GOSUB 19370  'pass2_init
  45. 10440  '
  46. 10450  WHILE NOT EOF(1)
  47. 10460   'get source line, initialize
  48. 10470     GOSUB 10620   'getline
  49. 10480   'parse line
  50. 10490     GOSUB 10730   'parse
  51. 10500   'phase error?
  52. 10510     IF LABEL$ <> "" THEN GOSUB 11910  'check_phase
  53. 10520   'if op, update loctr, generate obj. code
  54. 10530     IF OP$ <> "" THEN GOSUB 12480   'update_loctr
  55. 10540   'output obj. code & listing line
  56. 10550     GOSUB 19020  'output
  57. 10560   'progess report
  58. 10570     GOSUB 19850
  59. 10580   WEND
  60. 10590  'wipe out msg
  61. 10600    X = POS(0): Y = CSRLIN: LOCATE 25,1: PRINT TAB(79): LOCATE Y,X
  62. 10610  RETURN
  63. 10620  '********************************************
  64. 10630  '* SUBROUTINE GETLINE                       *
  65. 10640  '* Gets line of source code for processing. *
  66. 10650  '* and initializes for new iteration.       *
  67. 10660  '********************************************
  68. 10670  '
  69. 10680  LINE INPUT#1, INPLINE$
  70. 10690  LINENUM = LINENUM + 1
  71. 10700  NEEDOFFSET = NONE: DSFLAG = FALSE
  72. 10710  OBJLEN = 0
  73. 10720  RETURN
  74. 10730  '*****************************************************
  75. 10740  '* SUBROUTINE PARSE                                  *
  76. 10750  '* Parses input line for any label, op, or operands. *
  77. 10760  '*****************************************************
  78. 10770  '
  79. 10780  LINEPTR = 1: LINEPTR2 = 1
  80. 10790  LABEL$ = "": OP$ = "": SOURCE$ = "": DEST$ = ""
  81. 10800  '
  82. 10810  'set endptr to end of code
  83. 10820    ENDPTR = INSTR(INPLINE$,";") - 1            'just before comment
  84. 10830    IF ENDPTR = -1 THEN ENDPTR = LEN(INPLINE$)  'no comment, set to eol
  85. 10840  '
  86. 10850  'no code? (return)
  87. 10860    IF ENDPTR = 0 THEN 11120
  88. 10870  '
  89. 10880  'convert to all caps
  90. 10890    GOSUB 11140
  91. 10900  '
  92. 10910  'label (if any)
  93. 10920    IF LEFT$(INPLINE$,1) = " " THEN 10960
  94. 10930      GOSUB 11280  'getfield
  95. 10940      LABEL$ = FLD$
  96. 10950  '
  97. 10960  'op-code
  98. 10970    GOSUB 11280  'getfield
  99. 10980    IF NOT FOUND THEN 11120
  100. 10990      OP$ = FLD$
  101. 11000  'save ptr to start of operands
  102. 11010    OPDPTR = LINEPTR
  103. 11020  '
  104. 11030  'destination operand (if any)
  105. 11040    GOSUB 11280  'getfield
  106. 11050    IF NOT FOUND THEN 11120
  107. 11060    DEST$ = FLD$
  108. 11070  '
  109. 11080  'source operand (if any)
  110. 11090    GOSUB 11280  'getfield
  111. 11100    IF NOT FOUND THEN 11120
  112. 11110    SOURCE$ = FLD$
  113. 11120  RETURN
  114. 11130  '
  115. 11140  'internal subroutine caps
  116. 11150  'Scans inpline$ up to comment field,
  117. 11160  'converting l.c. chars. to u.c.. Skips over strings.
  118. 11170  FOR I = 1 TO ENDPTR
  119. 11180    C$ = MID$(INPLINE$,I,1)
  120. 11190    'skip strings
  121. 11200      IF C$ <> "'" THEN 11240
  122. 11210        STRGEND = INSTR(I+1,INPLINE$,C$)
  123. 11220        IF STRGEND > 0 THEN I = STRGEND: GOTO 11250
  124. 11230    'convert
  125. 11240      IF ASC(C$) => 97 AND ASC(C$) <= 122 THEN C$ = CHR$(ASC(C$) - 32):                  MID$(INPLINE$,I,1) = C$
  126. 11250    NEXT I
  127. 11260  RETURN
  128. 11270  '***********************************************************
  129. 11280  '* SUBROUTINE GETFIELD                                     *
  130. 11290  '* Starting at lineptr, trys to return next field in FLD$. *
  131. 11300  '* Sets found if sucessful. Moves lineptr past field.      *
  132. 11310  '***********************************************************
  133. 11320  '
  134. 11330  'find next non-delimiter or run off end
  135. 11340   WHILE LINEPTR <= ENDPTR
  136. 11350     IF INSTR(" ,",MID$(INPLINE$,LINEPTR,1)) = 0 THEN 11380
  137. 11360     LINEPTR = LINEPTR + 1
  138. 11370     WEND
  139. 11380  'if past end, not found
  140. 11390   IF LINEPTR <= ENDPTR  THEN 11420
  141. 11400     FOUND = FALSE
  142. 11410     RETURN
  143. 11420  '
  144. 11430  'strings terminated by '
  145. 11440   IF MID$(INPLINE$,LINEPTR,1) <> "'" THEN 11500
  146. 11450     STRGEND = INSTR(LINEPTR+1,INPLINE$,"'")
  147. 11460     IF STRGEND = 0 THEN 11500
  148. 11470       LINEPTR2 = STRGEND + 1
  149. 11480       GOTO 11570
  150. 11490  '
  151. 11500  'otherwise, find next delimter or go 1 past end
  152. 11510   LINEPTR2 = LINEPTR
  153. 11520   WHILE LINEPTR2 <= ENDPTR
  154. 11530     IF INSTR(" ,",MID$(INPLINE$,LINEPTR2,1)) > 0 THEN 11570
  155. 11540     LINEPTR2 = LINEPTR2 + 1
  156. 11550     WEND
  157. 11560  '
  158. 11570  'copy field
  159. 11580   FLD$ = MID$(INPLINE$,LINEPTR,LINEPTR2-LINEPTR)
  160. 11590  '
  161. 11600  'move lineptr past field, set found & return
  162. 11610   LINEPTR = LINEPTR2
  163. 11620   FOUND = TRUE
  164. 11630   RETURN
  165. 11640  '**********************************************
  166. 11650  '* SUBROUTINE NEWENTRY                        *
  167. 11660  '* Adds new symbol to sym table with default  *
  168. 11670  '* attributes. (may be changed by pseudo-ops) *
  169. 11680  '**********************************************
  170. 11690  '
  171. 11700  'already in table? (error)
  172. 11710    TARGET$ = LABEL$
  173. 11720   GOSUB 12030     'operand_lookup
  174. 11730   IF NOT FOUND THEN 11780
  175. 11740     ERRS = ERRS + 1
  176. 11750     PRINT#2,"****Error: Duplicate definition of ";LABEL$;" in ";LINENUM
  177. 11760     RETURN
  178. 11770  '
  179. 11780  'table full? (error)
  180. 11790   IF NUMSYM < MAXSYM THEN 11840
  181. 11800     ERRS = ERRS + 1
  182. 11810     PRINT#2, "****Error: Too many user symbols in "; LINENUM
  183. 11820     RETURN
  184. 11830  '
  185. 11840  'else make new entry
  186. 11850   NUMSYM = NUMSYM + 1
  187. 11860   SYM$(NUMSYM) = LABEL$
  188. 11870   VAL1(NUMSYM) = LOCTR
  189. 11880   SYMTYPE(NUMSYM) = NEAR
  190. 11890  '
  191. 11900  RETURN
  192. 11910  '*********************************
  193. 11920  '* SUBROUTINE CHECK_PHASE        *
  194. 11930  '* Label value same both passes? *
  195. 11940  '*********************************
  196. 11950  IF OP$ = "EQU" THEN 12020
  197. 11960  TARGET$ = LABEL$
  198. 11970  GOSUB 12030  'operand_lookup
  199. 11980  '
  200. 11990  IF (SYMTYPE(TABLEPTR) AND (NEAR OR MEM)) = FALSE THEN 12020
  201. 12000    IF VAL1(TABLEPTR) = LOCTR THEN 12020
  202. 12010      ERRS = ERRS + 1: PRINT#2, "****Phase Error"
  203. 12020  RETURN
  204. 12030  '*************************************************
  205. 12040  '* SUBROUTINE OPERAND_LOOKUP                     *
  206. 12050  '* Trys to find TARGET$ in sym table.  If there, *
  207. 12060  '* sets FOUND true, & TABLEPTR to its'position.  *
  208. 12070  '*************************************************
  209. 12080  'scan table for symbol
  210. 12090    FOR TABLEPTR = 1 TO NUMSYM
  211. 12100      IF SYM$(TABLEPTR) = TARGET$ THEN 12160 'found
  212. 12110      NEXT TABLEPTR
  213. 12120  '
  214. 12130  'failure exit point
  215. 12140    FOUND = FALSE
  216. 12150    RETURN
  217. 12160  'sucess exit point
  218. 12170    FOUND = TRUE
  219. 12180    RETURN
  220. 12190  '*********************************************************
  221. 12200  '* SUBROUTINE LOOKUP_OP                                  *
  222. 12210  '* Given op-code in op$, & operand types in dtype &      *
  223. 12220  '* stype, trys to find op in opcode table. If sucessful, *
  224. 12230  '* sets found true, & opptr to its' position.            *
  225. 12240  '*********************************************************
  226. 12250  'binary search for good starting pt.
  227. 12260   MOVE = NUMOP: ST = MOVE/2
  228. 12270   WHILE MOVE >= 2
  229. 12280     MOVE = MOVE/2
  230. 12290     IF OP$ > OPCODE$(ST) THEN ST = ST + MOVE ELSE ST = ST - MOVE
  231. 12300     IF ST < 1 THEN ST = 1
  232. 12310     IF ST > NUMOP THEN ST = NUMOP
  233. 12320     WEND
  234. 12330  '
  235. 12340  'scan for entry matching all 3 fields
  236. 12350   FOR OPPTR = ST TO NUMOP
  237. 12360     IF OPCODE$(OPPTR) > OP$ THEN 12420   'failed
  238. 12370     IF OPCODE$(OPPTR) <> OP$ THEN 12410
  239. 12380     IF (SRCTYPE(OPPTR) AND STYPE) = FALSE THEN 12410
  240. 12390     IF (DSTTYPE(OPPTR) AND DTYPE) = FALSE THEN 12410
  241. 12400     GOTO 12450 'found!
  242. 12410     NEXT OPPTR
  243. 12420  'failure exit
  244. 12430   FOUND = FALSE
  245. 12440   RETURN
  246. 12450  'successful exit
  247. 12460   FOUND = TRUE
  248. 12470   RETURN
  249. 12480  '***************************************
  250. 12490  '* SUBROUTINE UPDATE_LOCTR             *
  251. 12500  '* Decodes operation & advances loctr. *
  252. 12510  '* On pass 2, generates obj. code.     *
  253. 12520  '***************************************
  254. 12530  '
  255. 12540  'set operand types & values
  256. 12550    'destination operand
  257. 12560     TARGET$ = DEST$: GOSUB 12860   'type_operand
  258. 12570     DTYPE = TARGTYPE
  259. 12580     DVAL1 = TARGVAL1
  260. 12590     DVAL2 = TARGVAL2
  261. 12600    'source operand
  262. 12610      'special case: RET op
  263. 12620       IF OP$ = "RET" THEN STYPE = PROCTYPE(STKTOP): GOTO 12690
  264. 12630      'normal source
  265. 12640       TARGET$ = SOURCE$: GOSUB 12860   'type_operand
  266. 12650       STYPE = TARGTYPE
  267. 12660       SVAL1 = TARGVAL1
  268. 12670       SVAL2 = TARGVAL2
  269. 12680  '
  270. 12690  'find op in op table (not there: error)
  271. 12700   TARGET$ = OP$
  272. 12710   GOSUB 12190   'lookup_op
  273. 12720   IF FOUND THEN 12810
  274. 12730     IF PASS = 1 THEN RETURN
  275. 12740     ERRS = ERRS + 1: PRINT#2,"****Syntax Error: ";OP$;DTYPE;STYPE
  276. 12750     IF ((ACUM8 OR ACUM16 OR REG8 OR REG16 OR SEG OR CS)                                AND (DTYPE OR STYPE)) THEN 12800
  277. 12760       IF (STYPE AND (NONE OR IMMED8 OR IMMED16)) = FALSE THEN 12800
  278. 12770         IF INSTR("BW",RIGHT$(OP$,1)) <> 0 THEN 12800
  279. 12780           DIAG = DIAG + 1
  280. 12790           PRINT#2,"****Diagnostic: Specify word or byte operation"
  281. 12800     RETURN
  282. 12810   FLAG = OFLAG(OPPTR)
  283. 12820  '
  284. 12830  'branch for mach ops & pseudo-ops to update loctr
  285. 12840   IF FLAG AND MACHOP THEN GOSUB 15160 ELSE GOSUB 15970
  286. 12850  RETURN
  287. 12860  '*********************************************************
  288. 12870  '* SUBROUTINE TYPE_OPERAND                               *
  289. 12880  '* Sets TARGTYPE to reflect TARGET$'s type.  Sets        *
  290. 12890  '* TARGVAL1 to its' value. If the operand is a register, *
  291. 12900  '* sets TARVAL2 to its' val2. If an offset appears,      *
  292. 12910  '* NEEDOFFSET gets the its' type, and OFFSET its' value. *
  293. 12920  '*********************************************************
  294. 12930  '
  295. 12940  'any operand?
  296. 12950   IF LEN(TARGET$) > 0 THEN 12980
  297. 12960     TARGTYPE = NONE
  298. 12970     RETURN
  299. 12980  'in sym table?
  300. 12990   GOSUB 12030   'operand_lookup
  301. 13000   IF NOT FOUND THEN 13050
  302. 13010     TARGTYPE = SYMTYPE(TABLEPTR)
  303. 13020     TARGVAL1 = VAL1(TABLEPTR)
  304. 13030     IF TABLEPTR <= PREDEF THEN TARGVAL2 = VAL2(TABLEPTR)
  305. 13040     RETURN
  306. 13050  'number?
  307. 13060   GOSUB 13440   'test_number
  308. 13070   IF NOT FOUND THEN 13110
  309. 13080     TARGTYPE = NUMTYPE
  310. 13090     TARGVAL1 = NUMVAL
  311. 13100     RETURN
  312. 13110  'direct mem. ref.?
  313. 13120   GOSUB 13820   'memref
  314. 13130   IF NOT FOUND THEN 13170
  315. 13140     TARGTYPE = MEM
  316. 13150     TARGVAL1 = MEMADDR
  317. 13160     RETURN
  318. 13170  'offset off register?
  319. 13180   GOSUB 14180   'parse_disp_off_reg
  320. 13190   IF NOT FOUND THEN 13240
  321. 13200     TARGTYPE = MEMREG
  322. 13210     TARGVAL1 = REGVAL
  323. 13220     RETURN
  324. 13230  'offset?
  325. 13240   GOSUB 14750 'offset
  326. 13250   IF NOT FOUND THEN 13290
  327. 13260     TARGTYPE = OFFSETYPE
  328. 13270     TARGVAL1 = OFFSETVAL
  329. 13280     RETURN
  330. 13290  'charactor?
  331. 13300   GOSUB 15050
  332. 13310   IF NOT FOUND THEN 13350
  333. 13320      TARGTYPE = IMMED8 OR IMMED16
  334. 13330      TARGVAL1 = CHARVAL
  335. 13340      RETURN
  336. 13350  'string?
  337. 13360   IF LEFT$(TARGET$,1) <> "'" THEN 13400
  338. 13370     TARGTYPE = STRING
  339. 13380     RETURN
  340. 13390  '
  341. 13400  'not found? assume near label or mem ref. (error on pass 2)
  342. 13410   IF PASS = 2 THEN PRINT#2,"****Error: Undefined symbol ";TARGET$:                  ERRS = ERRS + 1
  343. 13420   TARGTYPE = NEAR OR MEM
  344. 13430  RETURN
  345. 13440  '*******************************************
  346. 13450  '* SUBROUTINE TEST_NUMBER                  *
  347. 13460  '* Trys to interpret TARGET$ as a number.  *
  348. 13470  '* If sucessful, sets FOUND true, NUMVAL   *
  349. 13480  '* to its' value and NUMTYPE to its' type. *
  350. 13490  '*******************************************
  351. 13500  '
  352. 13510  FOUND = FALSE
  353. 13520  TN$ = TARGET$  'working copy
  354. 13530  '
  355. 13540  'hex number?
  356. 13550   IF RIGHT$(TN$,1) <> "H" THEN 13690
  357. 13560    'lop off H
  358. 13570     TN$ = LEFT$(TN$,LEN(TN$)-1)
  359. 13580    'scan for non-hex digits (exit)
  360. 13590     I = 1
  361. 13600     FOR I = 1 TO LEN(TN$)
  362. 13610       C$ = MID$(TN$,I,1)
  363. 13620       IF INSTR("0123456789ABCDEF",C$) = 0 THEN RETURN
  364. 13630       NEXT I
  365. 13640    'get value
  366. 13650     NUMVAL = VAL("&H" + TN$)
  367. 13660    'set type, return
  368. 13670     GOTO 13780
  369. 13680  '
  370. 13690  'decimal number?
  371. 13700    'scan for non-dec digits (exit)
  372. 13710     FOR I = 1 TO LEN(TN$)
  373. 13720       C$ = MID$(TN$,I,1)
  374. 13730       IF INSTR("0123456789-+",C$) = 0 THEN RETURN
  375. 13740       NEXT I
  376. 13750    'get value
  377. 13760     NUMVAL = VAL(TN$)
  378. 13770  '
  379. 13780  'sucess exit
  380. 13790   FOUND = TRUE
  381. 13800   IF LEN(HEX$(NUMVAL)) < 3  THEN NUMTYPE = IMMED16 OR IMMED8                        ELSE NUMTYPE = IMMED16
  382. 13810  RETURN
  383. 13820  '********************************************
  384. 13830  '* SUBROUTINE MEMREF                        *
  385. 13840  '* Trys to interpret target$ as a direct    *
  386. 13850  '* mem ref.  If sucessful, sets FOUND true, *
  387. 13860  '* & MEMADDR to the address referanced.     *
  388. 13870  '********************************************
  389. 13880  '
  390. 13890  MR$ = TARGET$  'save copy
  391. 13900  '
  392. 13910  'brackets?
  393. 13920   IF LEFT$(MR$,1) <> "[" OR RIGHT$(MR$,1) <> "]" THEN RETURN
  394. 13930  '
  395. 13940  'strip off brackets
  396. 13950   TARGET$ = MID$(MR$,2,LEN(MR$)-2)
  397. 13960  'try to interpret as addr.
  398. 13970    'might be number
  399. 13980     GOSUB 13440   'test_number
  400. 13990     IF NOT FOUND THEN 14030
  401. 14000       MEMADDR = NUMVAL
  402. 14010       GOTO 14150 'exit
  403. 14020  '
  404. 14030    'or might be symbol
  405. 14040     GOSUB 12030  'operand_lookup
  406. 14050     IF NOT FOUND THEN 14100
  407. 14060       IF (SYMTYPE(TABLEPTR) AND IMMED16) = FALSE THEN 14100
  408. 14070         MEMADDR = VAL1(TABLEPTR)
  409. 14080         GOTO 14150 'exit
  410. 14090  '
  411. 14100  'failure exit
  412. 14110   FOUND = FALSE
  413. 14120   TARGET$ = MR$
  414. 14130   RETURN
  415. 14140  '
  416. 14150  'sucessful exit
  417. 14160   TARGET$ = MR$
  418. 14170   RETURN
  419. 14180  '*****************************************************
  420. 14190  '* SUBROUTINE PARSE_DISP_OFF_REG                     *
  421. 14200  '* Trys to parse TARGET$ as an offset off a register *
  422. 14210  '* If sucessful, sets FOUND true, sets NEEDOFFSET    *
  423. 14220  '* to the offset's type, and OFFSET to it's value .  *
  424. 14230  '*****************************************************
  425. 14240  '
  426. 14250  PDOR$ = TARGET$  'save copy
  427. 14260  '
  428. 14270  'special case
  429. 14280   IF TARGET$ = "[BP]" THEN REGVAL = 6: NEEDOFFSET = IMMED8: OFFSET = 0:              GOTO 14670
  430. 14290  '
  431. 14300  'parse reg spec.
  432. 14310   'set ptr to candidate
  433. 14320    PTR = INSTR(TARGET$,"[")
  434. 14330    IF PTR <= 1 THEN 14710  'no disp, exit
  435. 14340   'isolate candidate
  436. 14350    REG$ = RIGHT$(PDOR$,LEN(PDOR$)-PTR+1)
  437. 14360   'valid reg. spec?
  438. 14370    IF REG$ = "[BP]" THEN REGVAL = 6: GOTO 14440
  439. 14380    TARGET$ = REG$
  440. 14390    GOSUB 12030  'operand_lookup
  441. 14400    IF NOT FOUND OR SYMTYPE(TABLEPTR) <> MEMREG THEN 14710
  442. 14410     'save reg value
  443. 14420      REGVAL = VAL1(TABLEPTR)
  444. 14430  '
  445. 14440  'now parse disp.
  446. 14450   'isolate candidate
  447. 14460    DISP$ = LEFT$(PDOR$,PTR-1)
  448. 14470   'valid disp?
  449. 14480    TARGET$ = DISP$
  450. 14490     'might be symbol
  451. 14500      GOSUB 12030   'operand_lookup
  452. 14510      IF NOT FOUND THEN 14560   'not sym
  453. 14520      IF (SYMTYPE(TABLEPTR) AND (IMMED16 OR IMMED8)) = FALSE THEN 14560
  454. 14530        NEEDOFFSET = SYMTYPE(TABLEPTR)
  455. 14540        OFFSET = VAL1(TABLEPTR)
  456. 14550        GOTO 14670
  457. 14560     'or number
  458. 14570      GOSUB 13440   'test_number
  459. 14580      IF NOT FOUND THEN 14620
  460. 14590        NEEDOFFSET = NUMTYPE
  461. 14600        OFFSET = NUMVAL
  462. 14610            GOTO 14670
  463. 14620     'or offset
  464. 14630      GOSUB 14750 'offset
  465. 14640      IF NOT FOUND THEN 14710
  466. 14650        NEEDOFFSET = OFFSETYPE
  467. 14660        OFFSET = OFFSETVAL
  468. 14670  'sucess exit
  469. 14680   TARGET$ = PDOR$
  470. 14690   FOUND = TRUE
  471. 14700   RETURN
  472. 14710  'failure exit
  473. 14720   TARGET$ = PDOR$
  474. 14730   FOUND = FALSE
  475. 14740   RETURN
  476. 14750  '***************************************************
  477. 14760  '* SUBROUTINE OFFSET                               *
  478. 14770  '* Trys to interpret TARGET$ as an offset operand. *
  479. 14780  '* If sucessful, set FOUND, set OFFSETYPE          *
  480. 14790  '* immed16, and TARGVAL1 to the label's offset.    *
  481. 14800  '***************************************************
  482. 14810  '
  483. 14820  OS$ = TARGET$
  484. 14830  '
  485. 14840  IF LEFT$(OS$,7) <> "OFFSET(" THEN FOUND = FALSE: RETURN
  486. 14850  IF PASS = 1 THEN 15010
  487. 14860  '
  488. 14870  'isolate label
  489. 14880    TARGET$ = MID$(TARGET$,8,LEN(TARGET$)-8)
  490. 14890  '
  491. 14900  'look it up
  492. 14910    GOSUB 12030 'operand_lookup
  493. 14920  '
  494. 14930  IF FOUND AND (SYMTYPE(TABLEPTR) AND (MEM OR NEAR)) THEN 14990
  495. 14940    ERRS = ERRS + 1
  496. 14950    PRINT#2, "****Error: Illegal or undefined argument for Offset"
  497. 14960    OFFSETVAL = 0
  498. 14970    GOTO 15010
  499. 14980  '
  500. 14990  OFFSETVAL = VAL1(TABLEPTR)
  501. 15000  '
  502. 15010  FOUND = TRUE
  503. 15020  OFFSETYPE = IMMED16
  504. 15030  TARGET$ = OS$
  505. 15040  RETURN
  506. 15050  '***************************************
  507. 15060  '* SUBROUTINE CHAR                     *
  508. 15070  '* Trys to interpret TARGET$ as a char *
  509. 15080  '***************************************
  510. 15090  FOUND = FALSE
  511. 15100  IF LEN(TARGET$) <> 3 THEN RETURN
  512. 15110  IF LEFT$(TARGET$,1) <> "'" THEN RETURN
  513. 15120  IF RIGHT$(TARGET$,1) <> "'" THEN RETURN
  514. 15130     FOUND = TRUE
  515. 15140     CHARVAL = ASC(MID$(TARGET$,2,1))
  516. 15150  RETURN
  517. 15160  '*************************************
  518. 15170  '* SUBROUTINE MACHOP                 *
  519. 15180  '* Updates loctr based on op length. *
  520. 15190  '* On pass 2, generates obj. code.   *
  521. 15200  '*************************************
  522. 15210  '
  523. 15220  GOSUB 15800  'op_type
  524. 15230  '
  525. 15240  'opcode
  526. 15250   LOCTR = LOCTR + 1
  527. 15260   IF PASS = 2 THEN GOSUB 16060  'build_opcode
  528. 15270  '
  529. 15280  '2nd op byte?
  530. 15290   IF (OPVAL(OPPTR) <> &HD5) AND (OPVAL(OPPTR) <> &HD4) THEN 15330
  531. 15300     LOCTR = LOCTR + 1
  532. 15310     IF PASS = 2 THEN OBJLEN = OBJLEN + 1: OBJ(OBJLEN) = &HA
  533. 15320  '
  534. 15330  'room for m. byte disp. (must go here, modebyte modifys offset)
  535. 15340   IF NEEDOFFSET = NONE THEN 15370
  536. 15350     IF (NEEDOFFSET AND IMMED8) THEN LOCTR = LOCTR + 1                                  ELSE LOCTR = LOCTR + 2
  537. 15360  '
  538. 15370  'if direct addr. mode byte, leave room for address
  539. 15380   IF (FLAG AND (NEEDMODEBYTE OR NEEDEXT)) = FALSE THEN 15410
  540. 15390     IF (DTYPE OR STYPE) AND MEM THEN LOCTR = LOCTR + 2
  541. 15400  '
  542. 15410  'extension byte?
  543. 15420   IF (FLAG AND NEEDEXT) = FALSE THEN 15460
  544. 15430     LOCTR = LOCTR + 1
  545. 15440     IF PASS = 2 THEN GOSUB 16320   'build_ext
  546. 15450  '
  547. 15460  'mode byte?
  548. 15470   IF (FLAG AND NEEDMODEBYTE) = FALSE THEN 15510
  549. 15480     LOCTR = LOCTR + 1
  550. 15490     IF PASS = 2 THEN GOSUB 16460  'build_modebyte
  551. 15500  '
  552. 15510  '8 bit disp.?
  553. 15520   IF (FLAG AND NEEDISP8) = FALSE THEN 15560
  554. 15530     LOCTR = LOCTR + 1
  555. 15540     IF PASS = 2 THEN GOSUB 16990  'build_disp8
  556. 15550  '
  557. 15560  '16 bit disp.?
  558. 15570   IF (FLAG AND NEEDISP16) = FALSE THEN 15610
  559. 15580     LOCTR = LOCTR + 2
  560. 15590     IF PASS = 2 THEN GOSUB 17210 'build_disp16
  561. 15600  '
  562. 15610  'immediate byte?
  563. 15620   IF (FLAG AND NEEDIMMED8) = FALSE THEN 15650
  564. 15630     LOCTR = LOCTR + 1
  565. 15640     IF PASS = 2 THEN GOSUB 17570
  566. 15650   IF WORD OR ((FLAG AND NEEDIMMED) = FALSE) THEN 15690
  567. 15660     LOCTR = LOCTR + 1
  568. 15670     IF PASS = 2 THEN GOSUB 17570   'build_immed8
  569. 15680  '
  570. 15690  'immediate word(s)?
  571. 15700   IF NOT(WORD) OR ((FLAG AND NEEDIMMED) = FALSE) THEN 15740
  572. 15710     IF DTYPE = IMMED16 THEN LOCTR = LOCTR + 4 ELSE LOCTR = LOCTR + 2
  573. 15720     IF PASS = 2 THEN GOSUB 17430  'build_immed16
  574. 15730  '
  575. 15740  'mem. addr.?
  576. 15750   IF (FLAG AND NEEDMEM) = FALSE THEN 15790
  577. 15760     LOCTR = LOCTR + 2
  578. 15770     IF PASS = 2 THEN GOSUB 17730  'mem_addr
  579. 15780  '
  580. 15790  RETURN
  581. 15800  '************************************
  582. 15810  '* SUBROUTINE OP_TYPE               *
  583. 15820  '* Decides between word & byte ops. *
  584. 15830  '************************************
  585. 15840  '
  586. 15850  IF (DTYPE OR STYPE) AND (REG16 OR ACUM16 OR SEG OR CS) THEN 15900
  587. 15860  IF (DTYPE OR STYPE) AND (REG8 OR ACUM8) THEN 15940
  588. 15870  '
  589. 15880  IF RIGHT$(OP$,1) = "B" THEN 15940
  590. 15890  '
  591. 15900  'word
  592. 15910   WORD = TRUE
  593. 15920   RETURN
  594. 15930  '
  595. 15940  'byte
  596. 15950   WORD = FALSE
  597. 15960   RETURN
  598. 15970  '**********************************************
  599. 15980  '* SUBROUTINE PSEUDO-OP                       *
  600. 15990  '* Branches to routines to handle each pseudo *
  601. 16000  '* op using the value field as an index.      *
  602. 16010  '**********************************************
  603. 16020  '
  604. 16030  ON OPVAL(OPPTR) GOSUB 17860, 18050, 18130, 18510, 18740, 18890
  605. 16040  '                      EQU    ORG    DB     DS     PROC   ENDP
  606. 16050  RETURN
  607. 16060  '**********************************************************
  608. 16070  '* SUBROUTINE BUILD_OPCODE                                *
  609. 16080  '* Builds opcode, stores it in obj. Increments objlength. *
  610. 16090  '**********************************************************
  611. 16100  '
  612. 16110  OBJLEN = OBJLEN + 1
  613. 16120  OBJ(OBJLEN) = OPVAL(OPPTR)
  614. 16130  '
  615. 16140  'add reg. field if requested
  616. 16150   IF (FLAG AND ADDREG) = FALSE THEN 16230
  617. 16160     'segment reg.
  618. 16170      IF DTYPE AND (SEG OR CS) THEN R = DVAL2: GOTO 16210
  619. 16180     'normal reg.
  620. 16190      IF (FLAG AND DIRECTION) THEN R = SVAL2/8 ELSE R = DVAL2/8
  621. 16200  '
  622. 16210     OBJ(OBJLEN) = OBJ(OBJLEN) + R
  623. 16220  '
  624. 16230  'auto word bit?
  625. 16240   IF (FLAG AND AUTOW) = FALSE THEN 16270
  626. 16250     IF WORD THEN OBJ(OBJLEN) = OBJ(OBJLEN) + 1
  627. 16260  '
  628. 16270  'auto count bit?
  629. 16280   IF (FLAG AND AUTOC) = FALSE THEN 16310
  630. 16290     IF STYPE AND CL THEN OBJ(OBJLEN) = OBJ(OBJLEN) + 2
  631. 16300  '
  632. 16310  RETURN
  633. 16320  '**************************************************
  634. 16330  '* SUBROUTINE BUILD_EXTENSION_BYTE                *
  635. 16340  '* Builds an opcode extension byte.  The ext. val *
  636. 16350  '* is extracted from bits 3-5 of the flag word.   *
  637. 16360  '**************************************************
  638. 16370  '
  639. 16380  'get ext.
  640. 16390   MASK = &H38
  641. 16400   EXT = FLAG AND MASK
  642. 16410  '
  643. 16420  'define proper operand as ext. & build mode byte
  644. 16430    IF FLAG AND DIRECTION THEN DVAL2 = EXT ELSE SVAL2 = EXT
  645. 16440    GOSUB 16460  'build_modebyte
  646. 16450  RETURN
  647. 16460  '***************************************************************
  648. 16470  '* SUBROUTINE BUILD_MODE_BYTE                                  *
  649. 16480  '* Given direction flag, memreg values in dval1 and sval1 and  *
  650. 16490  '* reg values in dval2 and sval2, builds an addressing mode    *
  651. 16500  '* byte.  If necessary, also builds displacement byte(s).      *
  652. 16510  '***************************************************************
  653. 16520  '
  654. 16530  OBJLEN = OBJLEN + 1
  655. 16540  '
  656. 16550  'special case: direct mem. addressing?
  657. 16560   IF ((DTYPE OR STYPE) AND MEM) = FALSE THEN 16630
  658. 16570     IF DTYPE = MEM THEN  M = SVAL2 ELSE M = DVAL2
  659. 16580       OBJ(OBJLEN) = 6 + M
  660. 16590       GOSUB 17730  'build_mem_addr
  661. 16600       RETURN
  662. 16610  '
  663. 16620  'normal mode byte
  664. 16630   'operands in normal or reverse order?
  665. 16640    IF FLAG AND DIRECTION THEN M = SVAL1 + DVAL2 ELSE M = DVAL1 + SVAL2
  666. 16650  '
  667. 16660   OBJ(OBJLEN) = M
  668. 16670  '
  669. 16680  'offset byte(s)?
  670. 16690  '
  671. 16700  IF NEEDOFFSET = NONE THEN 16880
  672. 16710  '
  673. 16720  '8 bit disp.
  674. 16730  IF OFFSET > 127 OR OFFSET < -128 THEN 16810
  675. 16740    OBJ(OBJLEN) = OBJ(OBJLEN) + 64  'set mod field
  676. 16750    'crunch neg. offset to 8 bits
  677. 16760      IF OFFSET < 0 THEN OFFSET = OFFSET AND &HFF
  678. 16770    OBJLEN = OBJLEN + 1
  679. 16780    OBJ(OBJLEN) = OFFSET
  680. 16790    RETURN
  681. 16800  '
  682. 16810  '16 bit disp.
  683. 16820   OBJ(OBJLEN) = OBJ(OBJLEN) + 128  'set mod field
  684. 16830   OBJLEN = OBJLEN + 2
  685. 16840   'convert to hi/low form
  686. 16850      NUMLOW = OFFSET: GOSUB 16890  'hi/low
  687. 16860   OBJ(OBJLEN-1) = NUMLOW
  688. 16870   OBJ(OBJLEN) = NUMHIGH
  689. 16880  RETURN
  690. 16890  '************************************************
  691. 16900  '* SUBROUTINE HI/LOW                            *
  692. 16910  '* Splits 16 bit number in numlow, into two     *
  693. 16920  '* byte-sized componants in numhigh and numlow. *
  694. 16930  '************************************************
  695. 16940  H$ = HEX$(NUMLOW)
  696. 16950  H$ = STRING$(4-LEN(H$),"0") + H$
  697. 16960  NUMLOW =  VAL("&H" + RIGHT$(H$,2))
  698. 16970  NUMHIGH = VAL("&H" + LEFT$(H$,2))
  699. 16980  RETURN
  700. 16990  '*********************************************
  701. 17000  '* SUBROUTINE BUILD_DISP8                    *
  702. 17010  '* Calculates the disp. from the present     *
  703. 17020  '* loc to the loc given as an operand.       *
  704. 17030  '* Prints error message if disp. exceeds 127.*
  705. 17040  '*********************************************
  706. 17050  '
  707. 17060  'calculate disp.
  708. 17070   D = DVAL1 - LOCTR
  709. 17080  '
  710. 17090  'check size
  711. 17100   IF ABS(D) < 128 THEN 17140
  712. 17110     D = 0
  713. 17120     IF PASS = 2 THEN PRINT#2,"****Error: Too far for short jump":                     ERRS = ERRS + 1
  714. 17130  '
  715. 17140  'if neg. crunch to 8 bits
  716. 17150   IF D < 0 THEN D = D AND &HFF
  717. 17160  '
  718. 17170  'build obj. code
  719. 17180   OBJLEN = OBJLEN + 1
  720. 17190   OBJ(OBJLEN) = D
  721. 17200  RETURN
  722. 17210  '********************************************
  723. 17220  '* SUBROUTINE BUILD_DISP16                  *
  724. 17230  '* Builds 16 bit displacement. Prints error *
  725. 17240  '* msg. for negative disps not on CALL ops. *
  726. 17250  '********************************************
  727. 17260  '
  728. 17270  'calculate disp.
  729. 17280   D = DVAL1 - LOCTR
  730. 17290  '
  731. 17300  IF OP$ = "JMP" AND D<=128 THEN PRINT#2, "****Diagnostic: Could use JMPS" :        DIAG = DIAG + 1
  732. 17310  '
  733. 17320  'legal?
  734. 17330   IF D >= 0 OR OP$ = "CALL" THEN 17370
  735. 17340     D = 0
  736. 17350     IF PASS = 2 THEN PRINT#2,"****Error: Illegal reverse long jump":                  ERRS = ERRS + 1
  737. 17360  '
  738. 17370  'build obj. code
  739. 17380   NUMLOW = D: GOSUB 16890  'hi/low
  740. 17390   OBJLEN = OBJLEN + 2
  741. 17400   OBJ(OBJLEN-1) = NUMLOW
  742. 17410   OBJ(OBJLEN) = NUMHIGH
  743. 17420  RETURN
  744. 17430  '************************************
  745. 17440  '* SUBROUTINE BUILD_IMMED16         *
  746. 17450  '* Builds word(s) of immediate data *
  747. 17460  '************************************
  748. 17470  '
  749. 17480  IF DTYPE AND IMMED16 THEN IVAL = DVAL1: GOSUB 17510
  750. 17490  IF STYPE AND IMMED16 THEN IVAL = SVAL1: GOSUB 17510
  751. 17500  RETURN
  752. 17510  'internal subroutine immed16
  753. 17520  NUMLOW = IVAL: GOSUB 16890   'hi/low
  754. 17530  OBJLEN = OBJLEN + 2
  755. 17540  OBJ(OBJLEN-1) = NUMLOW
  756. 17550  OBJ(OBJLEN) = NUMHIGH
  757. 17560  RETURN
  758. 17570  '**********************************
  759. 17580  '* SUBROUTINE BUILD_IMMED8        *
  760. 17590  '* Builds byte of immediate data. *
  761. 17600  '**********************************
  762. 17610  '
  763. 17620  IF DTYPE AND IMMED8 THEN IVAL = DVAL1: GOSUB 17650
  764. 17630  IF STYPE AND IMMED8 THEN IVAL = SVAL1: GOSUB 17650
  765. 17640  RETURN
  766. 17650  'int. sub. immed8
  767. 17660  IF IVAL <= 255 AND IVAL >= 0 THEN 17700
  768. 17670    IVAL = 0
  769. 17680    IF PASS = 2 THEN ERRS = ERRS + 1: PRINT#2,"****Error: Data too long"
  770. 17690  '
  771. 17700  OBJLEN = OBJLEN + 1
  772. 17710  OBJ(OBJLEN) = IVAL
  773. 17720  RETURN
  774. 17730  '*********************************
  775. 17740  '* SUBROUTINE MEMREF             *
  776. 17750  '* Builds a memory address word. *
  777. 17760  '*********************************
  778. 17770  '
  779. 17780  'get addr. in hi/low form
  780. 17790   IF DTYPE = MEM THEN NUMLOW = DVAL1 ELSE NUMLOW = SVAL1
  781. 17800   GOSUB 16890
  782. 17810  'build word
  783. 17820   OBJLEN = OBJLEN + 2
  784. 17830   OBJ(OBJLEN-1) = NUMLOW
  785. 17840   OBJ(OBJLEN) = NUMHIGH
  786. 17850  RETURN
  787. 17860  '***************************
  788. 17870  '* SUBROUTINE EQU          *
  789. 17880  '* Handles equ pseudo-op.  *
  790. 17890  '***************************
  791. 17900  '
  792. 17910  IF (LABEL$ <> "")  THEN 17950
  793. 17920    IF PASS = 2 THEN ERRS = ERRS+1: PRINT#2,"****Error: EQU without symbol"
  794. 17930    RETURN
  795. 17940  '
  796. 17950  IF PASS = 2 THEN 18040
  797. 17960  '
  798. 17970  IF DTYPE <> (NEAR OR MEM) THEN 18020   'pass 1 default if not found
  799. 17980    ERRS = ERRS + 1
  800. 17990    PRINT#2, "****Error: EQU with forward referance in ";LINENUM
  801. 18000    RETURN
  802. 18010  '
  803. 18020  VAL1(NUMSYM) = DVAL1
  804. 18030  SYMTYPE(NUMSYM) = DTYPE
  805. 18040  RETURN
  806. 18050  '**************************
  807. 18060  '* SUBROUTINE ORG         *
  808. 18070  '* Handles org pseudo-op. *
  809. 18080  '**************************
  810. 18090  '
  811. 18100  'set loctr to new value
  812. 18110   LOCTR = DVAL1
  813. 18120  RETURN
  814. 18130  '*************************
  815. 18140  '* SUBROUTINE DB         *
  816. 18150  '* Handles db pseudo-op. *
  817. 18160  '*************************
  818. 18170  '
  819. 18180  'label? set type to mem
  820. 18190   IF LABEL$ <> "" THEN SYMTYPE(NUMSYM) = MEM
  821. 18200  '
  822. 18210  'scan operand area, building obj. code
  823. 18220   LINEPTR = OPDPTR: LINEPTR2 = OPDPTR
  824. 18230   WHILE LINEPTR < ENDPTR
  825. 18240    'get operand
  826. 18250     GOSUB 11270  'get_field
  827. 18260     IF NOT FOUND THEN 18380  'exit
  828. 18270    'branch for byte value or string
  829. 18280     TARGET$ = FLD$: GOSUB 13440 'test_number
  830. 18290     IF NOT FOUND OR (NUMTYPE AND IMMED8) = FALSE THEN 18320
  831. 18300       GOSUB 18400  'build_byte
  832. 18310       GOTO 18370
  833. 18320     IF LEFT$(FLD$,1) <> "'" THEN 18350
  834. 18330       GOSUB 18440  'build_stg
  835. 18340       GOTO 18370
  836. 18350    'if not byte or string, error on pass 2
  837. 18360     IF PASS = 2 THEN PRINT#2,"****Error: unrecognized operand ";FLD$:                 ERRS = ERRS + 1
  838. 18370    WEND
  839. 18380  LOCTR = LOCTR + OBJLEN
  840. 18390  RETURN
  841. 18400  'subroutine build_byte
  842. 18410  OBJLEN = OBJLEN + 1
  843. 18420  OBJ(OBJLEN) = NUMVAL
  844. 18430  RETURN
  845. 18440  'subroutine build_stg
  846. 18450  FLD$ = MID$(FLD$,2,LEN(FLD$)-2) 'strip off 's
  847. 18460  FOR I = 1 TO LEN(FLD$)
  848. 18470    OBJLEN = OBJLEN + 1
  849. 18480    OBJ(OBJLEN) = ASC(MID$(FLD$,I,1))
  850. 18490    NEXT I
  851. 18500  RETURN
  852. 18510  '*************************
  853. 18520  '* SUBROUTINE DS         *
  854. 18530  '* Handles ds pseudo-op. *
  855. 18540  '*************************
  856. 18550  '
  857. 18560  DSFLAG = TRUE  'signal this is a ds
  858. 18570  '
  859. 18580  'label? set type to mem
  860. 18590   IF LABEL$ <> "" THEN SYMTYPE(NUMSYM) = MEM
  861. 18600  '
  862. 18610  'set output code
  863. 18620   IF STYPE AND IMMED8 THEN DSVAL = SVAL1 ELSE DSVAL = 0
  864. 18630  '
  865. 18640  'on pass 2, generate obj. code directly
  866. 18650   IF PASS = 1 THEN 18700
  867. 18660     FOR I = 1 TO DVAL1
  868. 18670       LSET BYTE$ = CHR$(DSVAL): PUT #3
  869. 18680       NEXT I
  870. 18690  '
  871. 18700  'advance loctr
  872. 18710   LOCTR = LOCTR + DVAL1
  873. 18720  '
  874. 18730  RETURN
  875. 18740  '***************************
  876. 18750  '* SUBROUTINE PROC         *
  877. 18760  '* Handles proc pseudo-op. *
  878. 18770  '***************************
  879. 18780  '
  880. 18790  IF STKTOP < MAXSTK THEN 18850
  881. 18800    IF PASS = 1 THEN 18830
  882. 18810      ERRS = ERRS + 1
  883. 18820      PRINT#2, "****Error: Procedures nested too deeply"
  884. 18830    RETURN
  885. 18840  '
  886. 18850  'push new proc type for returns
  887. 18860   STKTOP = STKTOP + 1
  888. 18870   PROCTYPE(STKTOP) = DTYPE
  889. 18880  RETURN
  890. 18890  '********************
  891. 18900  '* SUBROUTINE ENDP  *
  892. 18910  '* Pops proc stack. *
  893. 18920  '********************
  894. 18930  '
  895. 18940  IF STKTOP > 0 THEN 19000
  896. 18950    IF PASS = 1 THEN 18980
  897. 18960      ERRS = ERRS + 1
  898. 18970      PRINT#2, "****Error: ENDP without PROC"
  899. 18980    RETURN
  900. 18990  '
  901. 19000  STKTOP = STKTOP - 1
  902. 19010  RETURN
  903. 19020  '************************************
  904. 19030  '* SUBROUTINE OUTPUT                *
  905. 19040  '* Outputs obj code & listing line, *
  906. 19050  '* given code in obj(objlength).    *
  907. 19060  '************************************
  908. 19070  '
  909. 19080  IF DSFLAG THEN H$ = HEX$(LOCTR-DVAL1) ELSE H$ = HEX$(LOCTR-OBJLEN)
  910. 19090  H$ = STRING$(4-LEN(H$),"0") + H$
  911. 19100  PRINT#2, TAB(1) H$;
  912. 19110  'first 6 bytes
  913. 19120   I = 1
  914. 19130   PRINT#2, TAB(6)
  915. 19140   WHILE I <= 6
  916. 19150     IF I > OBJLEN THEN 19220
  917. 19160     LSET BYTE$ = CHR$(OBJ(I)): PUT #3
  918. 19170     H$ = HEX$(OBJ(I)): IF LEN(H$) = 1 THEN H$ = "0" + H$
  919. 19180     PRINT#2, H$;
  920. 19190     I = I + 1
  921. 19200     WEND
  922. 19210  '
  923. 19220  'source (truncate if necessary)
  924. 19230   PRINT#2, TAB(19)
  925. 19240   PRINT#2, USING "####"; LINENUM;
  926. 19250   PRINT#2, SPACE$(2) LEFT$(INPLINE$, LWIDTH-26)
  927. 19260  '
  928. 19270  'rest of obj. code
  929. 19280   WHILE I <= OBJLEN
  930. 19290     IF I MOD 6 = 1 THEN PRINT#2, TAB(6)
  931. 19300     LSET BYTE$ = CHR$(OBJ(I)): PUT #3
  932. 19310     H$ = HEX$(OBJ(I)): IF LEN(H$) = 1 THEN H$ = "0" + H$
  933. 19320     PRINT#2, H$;
  934. 19330     I = I + 1
  935. 19340     WEND
  936. 19350  IF OBJLEN > 6 THEN PRINT#2,
  937. 19360  RETURN
  938. 19370  '***************************
  939. 19380  '* SUBROUTINE PASSTWO_INIT *
  940. 19390  '***************************
  941. 19400  '
  942. 19410  'reset input file
  943. 19420   CLOSE #1: OPEN SC$ FOR INPUT AS #1
  944. 19430  '
  945. 19440  PASS = 2
  946. 19450  LOCTR = 256
  947. 19460  LINENUM = 0
  948. 19470  '
  949. 19480  RETURN
  950. 19490  '************************
  951. 19500  '* SUBROUTINE FINALPROC *
  952. 19510  '* Cleanup              *
  953. 19520  '************************
  954. 19530  '
  955. 19540  IF STKTOP > 0 THEN ERRS = ERRS + 1: PRINT#2,"****Error: missing ENDP"
  956. 19550  '
  957. 19560  PRINT#2,: PRINT#2,: PRINT#2, ERRS; "Error(s) detected"
  958. 19570  PRINT#2, DIAG; "Diagnostic(s) offered"
  959. 19580  'dump sym table
  960. 19590   GOSUB 19690
  961. 19600  'return printer to normal
  962. 19610   IF L$ = "lpt1:" THEN PRINT#2, PMODEOFF$
  963. 19620  'hang onto screen listing
  964. 19630   IF L$ <> "scrn:" THEN 19680
  965. 19640     PRINT: BEEP: COLOR 0,7
  966. 19650     PRINT TAB(30) "Hit any key to exit" TAB(79);
  967. 19660     C$ = INKEY$: IF C$ = "" THEN 19660
  968. 19670     COLOR 7,0
  969. 19680  RETURN
  970. 19690  '*****************************
  971. 19700  '* SUBROUTINE DUMP_SYM_TABLE *
  972. 19710  '*****************************
  973. 19720  '
  974. 19730  PRINT#2,: PRINT#2, "SYMBOL TABLE DUMP:"
  975. 19740  I = PREDEF + 1
  976. 19750  F$ =  "\        \!\  \\  \"  'format
  977. 19760  PERLINE = LWIDTH \ LEN(F$)
  978. 19770  WHILE I <= NUMSYM
  979. 19780    H$ = HEX$(VAL1(I)): H$ = STRING$(4-LEN(H$),"0") + H$
  980. 19790    PRINT#2, USING F$; SYM$(I); " ";  H$; "    ";
  981. 19800    I = I + 1
  982. 19810    IF (I-PREDEF) MOD PERLINE = 1 THEN PRINT#2,
  983. 19820    WEND
  984. 19830  PRINT#2,
  985. 19840  RETURN
  986. 19850  '*************************************
  987. 19860  '* SUBROUTINE PROGESS REPORT         *
  988. 19870  '* Maintains reassuring msg. on scrn *
  989. 19880  '*************************************
  990. 19890  '
  991. 19900  X = POS(0): Y = CSRLIN: LOCATE 25,1: COLOR 0,7
  992. 19910  IF PASS = 1 THEN PRINT "First"; ELSE PRINT "Second";
  993. 19920  PRINT " pass in progress. Lines processed = "; LINENUM;
  994. 19930  PRINT TAB(79);: COLOR 7,0: LOCATE Y,X
  995. 19940  RETURN
  996. 19950  '****************************************
  997. 19960  '* SUBROUTINE SET_UP_SYMBOL_TABLE       *
  998. 19970  '* Sets up sym table, & opens obj. file *
  999. 19980  '****************************************
  1000. 19990  '
  1001. 20000  INPUT#3, PREDEF, MAXSYM: LINE INPUT#3, C$: LINE INPUT#3, C$
  1002. 20010  DIM SYM$(MAXSYM), VAL1(MAXSYM), VAL2(PREDEF), SYMTYPE(MAXSYM)
  1003. 20020  '
  1004. 20030  FOR I = 1 TO PREDEF  '# of pre-defined syms
  1005. 20040    INPUT#3, SYM$(I), VAL1(I), VAL2(I), SYMTYPE(I)
  1006. 20050    NEXT I
  1007. 20060  NUMSYM = PREDEF
  1008. 20070  '
  1009. 20080  CLOSE #3
  1010. 20090  OPEN O$ AS #3 LEN=1: FIELD #3,1 AS BYTE$
  1011. 20100  RETURN
  1012. 50000  '**********************************
  1013. 50010  '* SUBROUTINE INIT                *
  1014. 50020  '* Initializes all but sym table. *
  1015. 50030  '**********************************
  1016. 50040  '
  1017. 50050  DEFINT A-Z
  1018. 50060  ERRS = 0: DIAG = 0
  1019. 50070  '
  1020. 50080  'title page
  1021. 50090   GOSUB 50190
  1022. 50100  'define constants
  1023. 50110   GOSUB 50450
  1024. 50120  'open files
  1025. 50130   GOSUB 50660
  1026. 50140  'op table
  1027. 50150   GOSUB 51190
  1028. 50160  'listing header
  1029. 50170   GOSUB 51350
  1030. 50180  RETURN
  1031. 50190  '*************************************************
  1032. 50200  '* SUBROUTINE TITLE                              *
  1033. 50210  '* Prints title page, & waits for user response. *
  1034. 50220  '*************************************************
  1035. 50230  '
  1036. 50240  SCREEN 0,0,0: WIDTH 80: KEY OFF: CLS: LOCATE 24,1,0
  1037. 50250  PRINT TAB(12)"KEY";STRING$(56,"THEN");"CLOSE
  1038. 50260  PRINT TAB(12)"OPEN"TAB(69)"OPEN
  1039. 50270  PRINT TAB(12)"OPEN"TAB(32)"CHASM  version 1.9"TAB(69)"OPEN
  1040. 50280  PRINT TAB(12)"OPEN"TAB(69)"OPEN
  1041. 50290  PRINT TAB(12)"OPEN"TAB(25)"Cheap Assembler for the IBM PC"TAB(69)"OPEN
  1042. 50300  PRINT TAB(12)"OPEN"TAB(69)"OPEN
  1043. 50310  PRINT TAB(12)"OPEN      If you have used this program and found it of     OPEN
  1044. 50320  PRINT TAB(12)"OPEN   value, your $20 contribution will be appreciated.    OPEN
  1045. 50330  PRINT TAB(12)"OPEN"TAB(69)"OPEN
  1046. 50340  PRINT TAB(12)"OPEN"TAB(29)"David Whitman"TAB(69)"OPEN
  1047. 50350  PRINT TAB(12)"OPEN"TAB(29)"Dept. of Chemistry"TAB(69)"OPEN
  1048. 50360  PRINT TAB(12)"OPEN"TAB(29)"Dartmouth College"TAB(69)"OPEN
  1049. 50370  PRINT TAB(12)"OPEN"TAB(29)"Hanover, NH  03755"TAB(69)"OPEN
  1050. 50380  PRINT TAB(12)"OPEN"TAB(69)"OPEN
  1051. 50390  PRINT TAB(12)"OPEN   You are encouraged to copy and share this program.   OPEN
  1052. 50400  PRINT TAB(12)"OPEN"TAB(69)"OPEN
  1053. 50410  PRINT TAB(12) "SCREEN";STRING$(56,"THEN");"LOAD":PRINT
  1054. 50420  PRINT TAB(27) "Hit any key to continue...":PRINT:PRINT
  1055. 50430  I$ = INKEY$: IF I$ = "" THEN 50430
  1056. 50440  CLS: RETURN
  1057. 50450  '****************************
  1058. 50460  '* SUBROUTINE SET_CONSTANTS *
  1059. 50470  '****************************
  1060. 50480  'general
  1061. 50490   TRUE = -1: FALSE = 0
  1062. 50500  '
  1063. 50510  'flag values
  1064. 50520  'bits 3-5 reserved for ext. values
  1065. 50530   MACHOP = 1: AUTOW = 4: ADDREG = 64: NEEDEXT = 128
  1066. 50540   NEEDISP8 = 256: NEEDISP16 = 512: NEEDMODEBYTE = 1024: NEEDIMMED8 = 2048
  1067. 50550   NEEDIMMED = 4096: DIRECTION = 8192: NEEDMEM = 16384: AUTOC = &H8000
  1068. 50560  '
  1069. 50570  'operand types
  1070. 50580   ACUM8 = 1: ACUM16 = 2: REG8 = 4: REG16 = 8: MEMREG = 16: CS = 32
  1071. 50590   SEG = 64: MEM = 128: IMMED8 = 256: IMMED16 = 512: NONE = 1024
  1072. 50600   STRING = 2048: NEAR = 4096: FAR = 8192: CL = 16384
  1073. 50610  '
  1074. 50620  'arrays
  1075. 50630  MAXOBJ = 50: DIM OBJ(MAXOBJ)
  1076. 50640  MAXSTK = 10: DIM PROCTYPE(MAXSTK): STKTOP = 0
  1077. 50650  RETURN
  1078. 50660  '*****************************************************
  1079. 50670  '* SUBROUTINE OPEN_FILES                             *
  1080. 50680  '* Prompts user for i/o filenames, then opens files. *
  1081. 50690  '*****************************************************
  1082. 50700  '
  1083. 50710  ON ERROR GOTO 51000
  1084. 50720  '
  1085. 50730  'input file
  1086. 50740   LOCATE 1,1: INPUT"Source code file name? [.asm] ", S$
  1087. 50750   IF S$ = "" THEN BEEP: GOTO 50740
  1088. 50760   'if no extension, add default
  1089. 50770      IF INSTR(S$,".") = 0                                                              THEN SC$ = S$ + ".asm"                                                          ELSE SC$ = S$: S$ = LEFT$(S$,INSTR(S$,".")-1)
  1090. 50780     OPEN SC$ FOR INPUT AS #1
  1091. 50790   LOCATE 3,1
  1092. 50800   INPUT"Direct listing to Printer (P), Screen (S), or Disk (D)?",L$
  1093. 50810   IF L$ = "" THEN BEEP: GOTO 50790
  1094. 50820     IF INSTR("PpSsDd",L$) = 0 THEN BEEP: GOTO 50790  'invalid response
  1095. 50830     IF L$ = "P" OR L$ = "p" THEN L$ = "lpt1:" : GOTO 50890  'printer?
  1096. 50840     IF L$ = "S" OR L$ = "s" THEN L$ = "scrn:" : GOTO 50890  'screen?
  1097. 50850       LOCATE 3,1: PRINT SPACE$(79);: LOCATE 3,1
  1098. 50860       PRINT"Name for listing file? [";S$;".lst] ";
  1099. 50870       INPUT "",L$
  1100. 50880       IF L$ = "" THEN L$ = S$ + ".lst"  'default to source name
  1101. 50890     OPEN L$ FOR OUTPUT AS #2
  1102. 50900  PRINT#2, 'test listing device
  1103. 50910  'object file
  1104. 50920   LOCATE 5,1: PRINT "Name for object file?  [";S$;".com] ";
  1105. 50930   INPUT "",O$
  1106. 50940   'default to source file name.com
  1107. 50950     IF O$ = "" THEN O$ = S$ + ".com"
  1108. 50960   'will open after symtable setup
  1109. 50970  ON ERROR GOTO 0 'kill error trapping
  1110. 50980   PRINT: PRINT: PRINT
  1111. 50990  RETURN
  1112. 51000  '****************
  1113. 51010  '*Error Handler *
  1114. 51020  '****************
  1115. 51030  '
  1116. 51040  IF ERR <> 53 THEN 51120
  1117. 51050    COLOR 0,7: BEEP
  1118. 51060    PRINT SC$; " not found.  Press Esc to exit, anything else to continue.";
  1119. 51070    SC$ = INKEY$: IF SC$ = "" THEN 51070
  1120. 51080    IF SC$ = CHR$(27) THEN SYSTEM
  1121. 51090    LOCATE ,1: COLOR 7,0: PRINT SPACE$(79);
  1122. 51100    LOCATE 1,31: PRINT SPACE$(48); : LOCATE ,1: RESUME 50740
  1123. 51110  '
  1124. 51120  IF ERR <> 27 THEN 51180
  1125. 51130     CLOSE #2: COLOR 0,7: BEEP
  1126. 51140     PRINT"Printer not available.  Press any key to continue.";
  1127. 51150     L$ = INKEY$ : IF L$ = "" THEN 51150
  1128. 51160     LOCATE ,1: COLOR 7,0: PRINT SPACE$(79);
  1129. 51170     LOCATE 3,56: PRINT SPACE$(23);: LOCATE ,1: RESUME 50800
  1130. 51180    ON ERROR GOTO 0
  1131. 51190  '***********************
  1132. 51200  '* SUBROUTINE OP_TABLE *
  1133. 51210  '***********************
  1134. 51220  '
  1135. 51230  OPEN "chasm.dat" FOR INPUT AS #3
  1136. 51240  'note: c$ used to skip data comments
  1137. 51250  '
  1138. 51260  INPUT#3, NUMOP: LINE INPUT#3,C$: LINE INPUT#3, C$
  1139. 51270  DIM OPCODE$(NUMOP), OPVAL(NUMOP), SRCTYPE(NUMOP)
  1140. 51280  DIM DSTTYPE(NUMOP), OFLAG(NUMOP)
  1141. 51290  '
  1142. 51300  FOR I = 1 TO NUMOP
  1143. 51310    INPUT#3, OPCODE$(I),OPVAL(I),DSTTYPE(I),SRCTYPE(I),OFLAG(I)
  1144. 51320    LINE INPUT#3, C$
  1145. 51330    NEXT I
  1146. 51340  RETURN
  1147. 51350  '*************************
  1148. 51360  '* SUBROUTINE HEADER     *
  1149. 51370  '* Prints listing header.*
  1150. 51380  '*************************
  1151. 51390  '
  1152. 51400  LWIDTH = 79  'default width
  1153. 51410  '
  1154. 51420  'title & date
  1155. 51430   D$ = LEFT$(DATE$,2) + "/" + MID$(DATE$,4,2) + "/" +  RIGHT$(DATE$,2)
  1156. 51440   PRINT#2, SC$ TAB(LWIDTH-LEN(D$)) D$:PRINT#2,:PRINT#2,
  1157. 51450  '
  1158. 51460  'printer set up?
  1159. 51470   IF L$ <> "lpt1:" THEN 51540
  1160. 51480     'for NEC 8023 printer, remove quotes for auto condensed mode
  1161. 51490     'similar code may be substituted for other printers.
  1162. 51500  ' LWIDTH = 131: WIDTH #2, LWIDTH + 1
  1163. 51510  ' PRINT#2, CHR$(27) + "Q" 'pmodeon
  1164. 51520  ' PMODEOFF$ = CHR$(27) + "N"
  1165. 51530  '
  1166. 51540  'column headings
  1167. 51550   PRINT#2,"LOC"TAB(6)"OBJ"TAB(19)"LINE"TAB(25)"SOURCE":PRINT#2,
  1168. 51560  '
  1169. 51570  RETURN
  1170.