1 TITLE 'IMSAI SCS-1 REV. 2 06 OCT. 1976' 2; 3; PAGE 62 4; 5; MODIFIED TO ASSEMBLE WITH INTEL 8080 CROSS ASSEMBLER 6; OCTOBER 2008, UDO MUNK 7; 8TTS EQU 03H 9TTI EQU 02H 10TTO EQU 02H 11TTYDA EQU 02H 12TTYTR EQU 01H 13; 14 ORG 0H 15 JMP INITA ;DEAD START 16 JMP EOR ;RESTART MONITOR 17; 18 ORG 08H 19 JMP BRKP ;BREAKPOINT RESTART 20; 21 ORG 40H; 22; 23; THIS ROUTINE SETS UP THE SIO BOARD 24; 25INITA: MVI A,0AAH ;GET DUMMY MODE WORD 26 OUT TTS ;OUTPUT IT 27 MVI A,40H ;GET RESET BIT 28 OUT TTS ;RESET SIO BOARD 29 MVI A,0CEH ;GET REAL MODE WORD 30 OUT TTS ;SET THE MODE FOR REAL 31 MVI A,37H ;GET THE COMMAND 32 OUT TTS ;OUTPUT IT 33; 34; THIS ROUTINE INITIALIZES THE FILE AREAD FOR SUBSEQUENT 35; PROCESSING 36; 37 LXI H,FILE0 38 MVI C,MAXFIL*FELEN 39 XRA A 40INIT2: MOV M,A 41 INX H 42 DCR C 43 JNZ INIT2 44; 45; CLEAR THE BREAKPOINT TABLE 46; 47 MVI B,NBR*3 48 LXI H,BRT 49INIT3: MOV M,A 50 INX H 51 DCR B 52 JNZ INIT3 53; 54; THIS IS THE STARTING POINT OF THE SELF CONTAINED 55; SYSTEM ONCE THE SYSTEM HAS BEEN INITIALIZED. COMMANDS 56; ARE READ FROM THE USER, EXECUTED, AND CONTROL RETURNS 57; BACK TO THIS POINT TO READ ANOTHER COMMAND. 58; 59EOR: LXI SP,AREA+18 60 CALL CRLF ;PRINT C/R, LINE FEED 61 CALL READ ;READ INPUT LINE 62 INX H 63 MOV A,M ;FETCH FIRST CHARACTER 64 CPI '9'+1 ;COMMAND OR LINE NUMBER? 65 JC LINE ;JUMP IF LINE FOR FILE 66 CALL VALC 67 CALL COMM 68 JMP EOR 69; 70; THIS ROUTINE READS IN A LINE FROM THE TTY AND PLACES 71; IT IN AN INPUT BUFFER. 72; THE FOLLOWING ARE SPECIAL CHARACTERS 73; CR TERMINATES READ ROUTINE 74; LF NOT RECOGNIZED BY ROUTINE 75; CTRL X DELETES CURRENT LINE 76; DEL DELETES CHARACER 77; ALL DISPLAYABLE CHARACTERS BETWEEN BLANK & Z AND THE 78; ABOVE ARE RECOGNIZED BY THE READ ROUTINE, ALL OTHERS 79; ARE SKIPPED OVER. THE ROUTINE WILL NOT ACCEPT MORE 80; CHARACTERS THAN THE INPUT BUFFER WILL HOLD. 81; 82READ: LXI H,IBUF ;GET INPUT BUFFER ADDRESS 83 SHLD ADDS ;SAVE ADDRESS 84 MVI E,2 ;INITIALIZE CHARACTER COUNT 85NEXT: CALL IN8 ;READ A LINE 86 MOV A,B 87 CPI 24 ;CHECK FOR CTRL X 88 JNZ CR 89 CALL CRLF ;OUTPUT A CRLF 90 JMP READ 91CR: CPI ASCR ;GET AN ASCII CR 92 JNZ DEL 93 MOV A,L 94 CPI IBUF AND 00FFH ;CHECK FOR FIRST CHAR 95 JZ READ 96 MVI M,ASCR ;PLACE CR AT END OF LINE 97 INX H 98 MVI M,1 ;PLACE EOF INDICATOR IN LINE 99 INX H 100 MVI A,IBUF+83 AND 00FFH 101 CALL CLER ;CLEAR REMAINING BUFFER 102 LXI H,IBUF-1 103 MOV M,E ;SAVE CHARACTER COUNT 104 RET 105DEL: CPI 127 ;CHECK FOR DELETE CHARACTER 106 JNZ CHAR 107 MVI A,IBUF AND 00FFH 108 CMP L ;IS IT 1ST CHARACTER 109 JZ NEXT 110 DCX H ;DECREMENT POINTER 111 DCR E ;DECREMENT COUNT 112BSPA: MVI B,5FH 113 CALL OUT8 114 JMP NEXT 115CHAR: CPI ' ' ;CHECK FOR LEGAL CHARACTER 116 JC NEXT 117 CPI 'Z'+1 118 JNC NEXT 119 MOV B,A 120 CALL OUT8 ;ECHO CHARACTER 121 MOV M,B 122 MVI A,IBUF+81 AND 00FFH 123 CMP L ;CHECK FOR END OF LINE 124 JZ BSPA 125 INX H 126 INR E ;INCREMENT CHARACTER COUNT 127 JMP NEXT 128; 129; THIS ROUTINE IS USED TO BLANK OUT A PORTION OF MEMORY 130; 131CLER: CMP L 132 RZ 133 MVI M,' ' ;PLACE BLANK IN MEMORY 134 INX H 135 JMP CLER 136; 137; SEE IF TTY INPUT READY AND CHECK FOR CTRL X. 138; 139INK: IN TTS ;GET TTY STATUS 140 CMA ;INVERT STATUS 141 ANI TTYDA ;IS DATA AVAILABLE? 142 RNZ ;RETURN IF NOT 143 IN TTI ;GET THE CHAR 144 ANI 07FH ;STRIP OFF PARITY 145 CPI 'X'-40H ;IS IT A CTRL X? 146 RET 147; 148; THIS ROUTINE READS A BYTE OF DATA FROM THE USART 149; 150IN8: IN TTS ;READ USART STATUS 151 ANI TTYDA 152 JZ IN8 153 IN TTI ;READ DATA 154 ANI 127 ;STRIP OFF PARITY 155 MOV B,A 156 RET 157 158; 159; THIS ROUTINE OUTPUTS A BYTE OF DATA TO THE USART 160; 161OUT8: IN TTS ;READ STATUS 162 ANI TTYTR 163 JZ OUT8 164OK: MOV A,B 165 OUT TTO ;TRANSMIT DATA 166 RET 167; 168; THIS ROUTINE WILL OUTPUT A CARRIAGE RETURN AND 169; LINE FEED FOLLOWED BY TWO DELETE CHARACTERS WHICH 170; PROVIDE TIME FOR PRINT HEAD TO RETURN. 171; 172CRLF: MVI B,13 ;CR 173 CALL OUT8 174LF: MVI B,10 ;LF 175 CALL OUT8 176 MVI B,127 177 CALL OUT8 178 CALL OUT8 179 RET 180; 181; THIS ROUTINE JUMPS TO A LOCATION IN MEMORY GIVEN BY 182; THE INPUT COMMAND AND BEGINS EXECUTION OF PROGRAM 183; THERE. 184; 185EXEC: CALL VCHK ;CHECK FOR PARAMETERS 186 CALL CRLF 187 LHLD BBUF ;FETCH ADDRESS 188 PCHL ;JUMP TO PROGRAM 189; 190; THIS ROUTINE CHECKS THE INPUT COMMAND AGAINS ALL 191; LEGAL COMMANDS STORED IN A TABLE. IF A LEGAL COMMAND 192; IS FOUND, A JUMP IS MADE TO THAT ROUTINE. OTHERWISE 193; AN ERROR MESSAGE IS OUTPUT TO THE USER. 194; 195COMM: LXI D,CTAB ;COMMAND TABLE ADDRESS 196 MVI B,NCOM ;NUMBER OF COMMANDS 197 MVI A,4 ;LENGTH OF COMMAND 198 STA NCHR ;SAVE 199 CALL COMS ;SEARCH TABLE 200 JNZ WHAT ;JUMP IF ILLEGAL COMMAND 201 PCHL ;BE HERE NOW 202; 203; THIS ROUTINE CHECKS TO SEE IF A BASE CHARACTER STRING 204; IS EQUAL TO ANY OF THE STRINGS CONTAINED IN A TABLE 205; POINTED TO BY D,E. tHE TABLE CONSISTS OF ANY NUMBER 206; OF CHARS, WITH 2 BYTES CONTAINING VALUES ASSOCIATED 207; WITH IT. REG B CONTAINS THE # OF STRINGS TO COMPARE. 208; THIS ROUTINE CAN BE USED TO SEARCH THROUGH A COMMAND 209; OR SYMBOL TABLE. ON RETURN, IF THE ZERO FLAG IS SET, 210; A MATCH WAS FOUND; IF NOT, NO MATCH WAS FOUND. IF 211; A MATCH WAS FOUND, D,E POINT TO THE LAST BYTE 212; ASSOCIATED WITH THE CHARACTER STRING. iF NOT, D,E 213; POINT TO THE NEXT LOCATION AFTER THE END FO THE TABLE. 214; 215COMS: LHLD ADDS ;FETCH COMPARE ADDRESS 216 LDA NCHR ;GET LENGTH OF STRING 217 MOV C,A 218 CALL SEAR ;COMPARE STRINGS 219 LDAX D ;FETCH VALUE 220 MOV L,A 221 INX D 222 LDAX D ;FETCH VALUE 223 MOV H,A 224 RZ 225 INX D ;SET TO NEXT STRING 226 DCR B ;DECREMENT COUNT 227 JNZ COMS 228 INR B ;CLEAR ZERO FLAG 229 RET 230; 231; THIS ROUTINE CHECKS TO SEE IF TWO CHARACTER STRINGS IN 232; MEMORY ARE EQUAL. tHE STRINGS ARE POINTED TO BY D,E 233; AND H,L. ON RETURN, THE ZERO FLAG SET INDICATES A 234; MATCH. REG C INDICATES THE LENGTH OF THE STRINGS. ON 235; RETURN, THE POINTERS POINT TO THE NEXT ADDRESS AFTER 236; THE CHARACTER STRINGS. 237; 238SEAR: LDAX D ;FETCH CHARACTER 239 CMP M ;COMPARE CHARACTERS 240 JNZ INCA 241 INX H 242 INX D 243 DCR C ;DECREMENT CHARACTER COUNT 244 JNZ SEAR 245 RET 246INCA: INX D 247 DCR C 248 JNZ INCA 249 INR C ;CLEAR ZERO FLAG 250 RET 251; 252; THIS ROUTINE ZEROES OUT A BUFFER IN MEMORY WHICH IS 253; THEN USED BY OTHER SCANNING ROUTINES 254; 255ZBUF: XRA A ;GET A ZERO 256 LXI D,ABUF+12 ;BUFFER ADDRESS 257 MVI B,12 ;BUFFER LENGTH 258ZBU1: DCX D ;DECREMENT ADDRESS 259 STAX D ;ZERO BUFFER 260 DCR B 261 JNZ ZBU1 262 RET 263; 264; THIS ROUTINE CALLS ETRA TO OBTAIN THE INPUT PARAMETER 265; VALUES AND CALLS AN ERROR ROUTINE IF AN ERROR OCCURED 266; IN THAT ROUTINE 267; 268VALC: CALL ETRA ;GET INPUT PARAMETERS 269 JC WHAT ;JUMP IF ERROR 270 RET 271; 272; THIS ROUTINE EXTRACTS THE VALUES ASSOCIATED WITH A 273; COMMAND FROM THE INPUT STREAM AND PLACES THEM IN THE 274; ASCII BUFFER (ABUF). IT ALSO CALLS A ROUTINE TO 275; CONVERT THE ASCII HEXADECIMALS TO BINARY AND STORES 276; THEM IN THE BINARY BUFFER (BBUF). ON RETURN, CARRY 277; SET INDICATES AN ERROR IN INPUT PARAMETERS. 278; 279ETRA: LXI H,0 ;GET A ZERO 280 SHLD BBUF+2 ;ZERO VALUE 281 SHLD FBUF ;SET NO FILE NAME 282 CALL ZBUF ;ZERO BUFFER 283 LXI H,IBUF-1 284VAL1: INX H 285 MOV A,M ;FETCH INPUT CHARACTER 286 CPI ' ' ;LOOK FOR FIRST CHARACTER 287 CMC 288 RNC ;RETURN IF NO CARRY 289 JNZ VAL1 ;JUMP IF NO BLACK 290 SHLD PNTR ;SAVE POINTER 291 CALL SBLK ;SCAN TO FIRST PARAMETER 292 CMC 293 RNC ;RETURN IF CR 294 CPI '/' 295 JNZ VAL5 ;NO FILE NAME 296 LXI D,FBUF ;NAME FOLLOWS PUT IN FBUF 297 MVI C,NMLEN 298VAL2: INX H 299 MOV A,M 300 CPI '/' 301 JZ VAL3 302 DCR C 303 JM WHAT 304 STAX D ;STORE FILE NAME 305 INX D 306 JMP VAL2 307VAL3: MVI A,' ' ;GET AN ASCII SPACE 308VAL4: DCR C 309 JM DONE 310 STAX D ;FILL IN WITH SPACES 311 INX D 312 JMP VAL4 313DONE: CALL SBL2 314 CMC 315 RNC 316VAL5: LXI D,ABUF 317 CALL ALPS ;PLACE PARAMETER IN BUFFER 318 MOV A,B ;GET DIGIT COUNT 319 CPI 5 ;CHECK NUMBER OF DIGITS 320 CMC 321 RC ;RETURN IF TOO MANY DIGITS 322 LXI B,ABUF 323 CALL AHEX ;CONVERT VALUE 324 RC ;ILLEGAL CHARACTER 325 SHLD BBUF ;SAVE IN BINARY BUFFER 326 LXI H,ABUF 327 CALL NORM ;NORMALIZE ASCII VALUE 328 CALL SBLK ;SCAN TO NEXT PARAMETER 329 CMC 330 RNC ;RETURN IF cr 331 LXI D,ABUF+4 332 CALL ALPS ;PLACE PARAMETERS IN BUFFER 333 MOV A,B ;GET DIGIT COUNT 334 CPI 5 ;CHECK NUMBER OF DIGITS 335 CMC 336 RC ;RETURN IF TOO MANY DIGITS 337 LXI B,ABUF+4 338 CALL AHEX ;CONVERT VALUE 339 RC ;ILLEGAL VALUE 340 SHLD BBUF+2 ;SAVE IN BINARY BUFFER 341 LXI H,ABUF+4 342 CALL NORM ;NORMALIZE ASCII VALUE 343 ORA A ;CLEAR CARRY 344 RET 345; 346; THIS ROUTINE FETCHES DIGITS FROM THE BUFFER ADDRESSED 347; BY B,C AND CONVERTS THE ASCII DECIMAL DIGITS INTO 348; BINARY. UP TO A 16-BIT VALUE CAN BE CONVERTED. THE 349; SCAN STOPS WHEN A BINARY ZERO IS FOUND IN THE BUFFER. 350; 351ADEC: LXI H,0 ;GET A 16 BIT ZERO 352ADE1: LDAX B ;FETCH ASCII DIGIT 353 ORA A ;SET ZERO FLAG 354 RZ ;RETURN IFF FINISHED 355 MOV D,H ;SAVE CURRENT VALUE 356 MOV E,L ;SAVE CURRENT VALUE 357 DAD H ;TIMES TWO 358 DAD H ;TIMES TWO 359 DAD D ;ADD IN ORIGINAL VALUE 360 DAD H ;TIMES TWO 361 SUI 48 ;ASCII BIAS 362 CPI 10 ;CHECK FOR LEGAL VALUE 363 CMC 364 RC ;RETURN IF ERROR 365 MOV E,A 366 MVI D,0 367 DAD D ;ADD IN NEXT DIGIT 368 INX B ;INCREMENT POINTER 369 JMP ADE1 370; 371; THIS ROUTINE FETCHES DIGITS FROM THE BUFFER ADDRESSED 372; BY B,C AND CONVERTS THE ASCII HEXADECIMAL DIGITS INTO 373; BINARY. UP TO A 16-BIT VALUE CAN BE CONVERTED. THE 374; SCAN STOPS WHEN A BINARY ZERO IS FOUNDIN THE BUFFER. 375; 376AHEX: LXI H,0 ;GET A 16 BIT ZERO 377AHE1: LDAX B ;FETCH ASCII DIGIT 378 ORA A ;SET ZERO FLAG 379 RZ ;RETURN IF DONE 380 DAD H ;LEFT SHIFT 381 DAD H ;LEFT SHIFT 382 DAD H ;LEFT SHIFT 383 DAD H ;LEFT SHIFT 384 CALL AHS1 ;CONVERT TO BINARY 385 CPI 10H ;CHECK FOR LEGAL VALUE 386 CMC 387 RC ;RETURN IF ERROR 388 ADD L 389 MOV L,A 390 INX B ;INCREMENT POINTER 391 JMP AHE1 392; 393; THIS ROUTINE CONVERTS ASCII HEX DIGITS INTO BINARY 394; 395AHS1: SUI 48 ;ASCII BIAS 396 CPI 10 ;DIGIT 0-10 397 RC 398 SUI 7 ;ALPHA BIAS 399 RET 400; 401; THIS ROUTINE CONVERTS A BINARY VALUE TO ASCII 402; HEXADECIMAL AND OUTPUTS THE CHARACTERS TO THE TTY. 403; 404HOUT: CALL BINH 405 LXI H,HCON 406CHOT: MOV B,M 407 CALL OUT8 408 INX H 409 MOV B,M 410 CALL OUT8 411 RET 412; 413; THIS ROUTINE DOES THE SAME AS ABOVE BUT OUTPUTS A 414; BLANK AFTER THE LAST CHARACTER 415; 416HOTB: CALL HOUT ;CONVERT AND OUTPUT 417 CALL BLK1 ;OUTPUT A BLANK 418 RET 419; 420; THIS ROUTINE CONVERTS A BINARY VALUE TO ASCII 421; DECIMAL DIGITS AND OPTPUTS THE CHARACTERS TO THE TTY 422; 423 424DOUT: CALL BIND ;CONVERT VALUE 425 CALL HOUT+3 ;OUTPUT VALUE (2 DIGITS) 426 INX H 427 MOV B,M ;GET LAST DIGIT 428 CALL OUT8 ;OUTPUT 429 RET 430; 431; THIS ROUTINE OUTPUTS A BLANK 432; 433BLK1: MVI B,' ' ;GET A BLANK 434 CALL OUT8 435 RET 436; 437; THIS ROUTINE IS USED BY OTHER ROUTINES TO INCREMENT 438; THE STARTING ADDRESS IN A COMMAND AND COMPARE IT WITH 439; THE FINAL ADDRESS IN THE COMMAND. ON RETURN, THE 440; CARRY FLAG SET INDICATES THAT THE FINAL ADDRESS HAS 441; BEEN REACHED. 442; 443ACHK: LHLD BBUF ;FETCH START ADDRESS 444 LDA BBUF+3 ;STOP ADDRESS (HIGH) 445 CMP H ;COMPARE ADDRESSES 446 JNZ ACH1 447 LDA BBUF+2 ;STOP ADDRESS (LOW) 448 CMP L ;COMPARE ADDRESSES 449 JNZ ACH1 450 STC ;SET CARRY IF EQUAL 451ACH1: INX H ;INCREMENT START ADDRESSES 452 SHLD BBUF ;STORE START ADDRESS 453 RET 454; 455; THIS ROUTINE OUTPUTS CHARACTER OF A STRING 456; UNTIL A CARRIAGE RETURN IS FOUND 457; 458SCRN: MOV B,M ;FETCH CHARACTER 459 MVI A,13 ;CARRIAGE RETURN 460 CMP B ;CHARACTER = CR? 461 RZ 462 CALL OUT8 463 INX H 464 JMP SCRN 465; 466; THIS ROUTINE CONVERTS THE BINARY VALUE IN REG A INTO 467; ASCII HEXADECIMAL DIGITS AND STORES THEM IN MEMORY 468; 469BINH: LXI H,HCON ;CONVERSION 470 MOV B,A ;SAVE VALUE 471 RAR 472 RAR 473 RAR 474 RAR 475 CALL BIN1 476 MOV M,A 477 INX H 478 MOV A,B 479 CALL BIN1 ;CONVERT TO ASCII 480 MOV M,A 481 RET 482; 483; THIS ROUTINE CONVERTS A VALUE TO HEXADECIMAL 484; 485BIN1: ANI 0FH ;LOW 4 BITS 486 ADI 48 ;CONVERT TO ASCII 487 CPI 58 ;DIGIT 0-9 488 RC 489 ADI 7 ;MODIFY FOR A-F 490 RET 491; 492; THIS ROUTINE CONVERTS THE BINARY VALUE IN REG A INTO 493; ASCII DECIMAL DIGITS AND STORES THEM IN MEMORY 494; 495BIND: LXI H,HCON ;CONVERSION ADDRESS 496 MVI B,100 497 CALL BID1 ;CONVERT HUNDREDS DIGIT 498 MVI B,10 499 CALL BID1 ;CONVERT TENS DIGIT 500 ADI '0' ;GET UNITS DIGIT 501 MOV M,A ;STORE IN MEMORY 502 RET 503; 504; THIS ROUTINE CONVERTS A VALUE TO DECIMAL 505; 506BID1: MVI M,'0'-1 ;INITIALIZE DIGIT COUNT 507 INR M 508 SUB B ;CHECK DIGIT 509 JNC BID1+2 510 ADD B ;RESTORE VALUE 511 INX H 512 RET 513; 514; LEGAL COMMAND TABLE 515; 516CTAB: DB 'DUMP' 517 DW DUMP 518 DB 'EXEC' 519 DW EXEC 520 DB 'ENTR' 521 DW ENTR 522 DB 'FILE' 523 DW FILE 524 DB 'LIST' 525 DW LIST 526 DB 'DELT' 527 DW DELL 528 DB 'ASSM' 529 DW ASSM 530 DB 'PAGE' 531 DW PAGEMOV 532 DB 'CUST' 533 DW 2000H 534 DB 'BREK' 535 DW BREAK 536 DB 'PROC' 537 DW PROC 538; 539; THIS ROUTINE CHECKS IF ANY PARAMETERS WERE ENTERED 540; WITH THE COMMAND, IF NOT AN ERROR MESSAGE IS ISSUED 541; 542VCHK: LDA ABUF ;FETCH PARAMETER BYTE 543 ORA A ;SET FLAGS 544 JZ WHAT ;NO PARAMETER 545 RET 546; 547; THIS ROUTINE DUMPS OUT THE FONTENTS OF MEMORY FROM 548; THE START TO FINAL ADDRESSES GIVEN IN THE COMMAND. 549; 550DUMP: CALL VCHK ;CHECK FOR PARAMETERS 551DUMS: CALL CRLF ;START NEW LINE 552DUM1: LHLD BBUF ;FETCH MEMORY ADDRESS 553 MOV A,M 554 CALL HOTB ;OUTPUT VALUE 555 CALL ACHK ;CHECK ADDRESS 556 RC ;RETURN IF FINISHED 557 MOV A,L ;IS NEXT ADDRESS 558 ANI 0FH ; DIVISIBLE BY 16? 559 JNZ DUM1 560 JMP DUMS 561; 562; THIS ROUTINE WILL MOVE 256 BYTES FROM 1ST ADDRESS 563; GIVEN IN COMMAND TO 2ND ADDRESS IN COMMAND. 564; 565PAGEMOV:CALL VCHK ;CHECK FOR PARAMETER 566 LDA ABUF+4 ;FETCH 2ND PARAMETER 567 ORA A ;DOES 2ND PARAMETER EXIST? 568 JZ WHAT 569 LHLD BBUF ;FETCH MOVE TO ADDRESS 570 XCHG 571 LHLD BBUF+2 ;FETCH MOVE TO ADDRESS 572 MVI B,0 ;SET COUNTER 573PAG1: LDAX D 574 MOV M,A 575 INX H 576 INX D 577 DCR B ;DECREMENT COUNTER 578 JNZ PAG1 579 RET 580; 581; THIS COMMAND INITIALIZES THE BEGINNING OF FILE ADDRESS 582; AND END OF FILE ADDRESS AS WELL AS THE FILE AREA 583; WHEN THE FILE COMMAND IS USED 584; 585FILE: CALL CRLF 586; CHECK FOR FILE PARAMETERS 587 LDA FBUF 588 ORA A 589 JZ FOUT ;NO ? GO LIST 590 CALL FSEA ;LOOK UP FILE 591 XCHG ;PNTR IN DE 592 JNZ TEST 593; NO ENTRY 594 LDA ABUF ;CHECK FOR PARAM 595 ORA A 596 JZ WHA1 ;NO?? - ERROR 597; CHECK FOR ROOM IN DIRECTORY 598 LDA FEF 599 ORA A 600 JNZ ROOM 601 LXI H,EMES1 602 JMP MESS 603; ENTRY FOUND ARE THESE PARAMETERS 604TEST: LDA ABUF 605 ORA A 606 JZ SWAPS 607 LHLD BBUF 608 MOV A,H 609 ORA L 610 JZ SWAPS 611 LXI H,EMES2 ;NO-NO CAN?T DO 612 JMP MESS ;IT - DELETE FIRST 613; MOVE FILE NAME TO BLOCK POINTED TO BY FREAD 614ROOM: LHLD FREAD 615 XCHG 616 LXI H,FBUF ;FILE NAME POINTER IN H,L 617 PUSH D 618 MVI C,NMLEN ;NAME LENGTH COUNT 619MOV23: MOV A,M 620 STAX D 621 INX D 622 DCR C ;TEST COUNT 623 INX H 624 JNZ MOV23 625 POP D ;RESTORE ENTRY POINTER 626; MAKE FILE POINTED TO BY D,E CURRENT 627SWAPS: LXI H,FILE0 628 MVI C,FELEN ;ENTRY LENGTH 629SWAP: LDAX D 630 MOV B,M 631 MOV M,A ;EXCHANGE 632 MOV A,B 633 STAX D 634 INX D 635 INX H ;BUMP POINTER 636 DCR C ;TEST COUNT 637 JNZ SWAP 638 639; CHECK FOR 2ND PARAMETER 640 LDA ABUF 641 ORA A 642 JZ FOOT ;NO SECOND PARAMETER 643; PROCESS 2ND PARAMETER 644 LHLD BBUF ;GET ADDRESS 645 SHLD BOFP ;SET BEGIN 646 SHLD EOFP ;SET END 647 MOV A,L ;IS ADDRESS ZERO 648 ORA H 649 JZ FIL35 ;YES 650FIL30: MVI M,1 ;NON-ZERO ? SET EOF 651FIL35: XRA A ;AND MAX LINE # 652 STA MAXL 653 JMP FOOT ;OUTPUT PARAMETERS 654FOUT: LDA IBUF+4 655 CPI 'S' ;IS COMMAND FILES? 656 MVI C,MAXFIL 657 JZ FOUL 658FOOT: MVI C,1 659; OUTPUT THE # OF ENTRIES IN C 660FOUL: LXI H,FILE0 661 MOV A,C 662FINE: STA FOCNT ;SAVE COUNT 663 PUSH H 664 LXI D,NMLEN 665 DAD D 666 MOV A,M 667 ORA A 668 JNZ FOOD 669 INX H 670 ADD M 671 INX H 672 JNZ FOOD ;NON ZERO, OK TO OUTPUT 673 INX SP 674 INX SP 675 INX H 676 INX H 677 JMP FEET 678; HAVE AN ENTRY TO OUTPUT 679FOOD: POP H ;PTR 680 MVI C,NMLEN 681FAST: MOV B,M ;LOAD CHARACTER TO B 682 CALL OUT8 683 DCR C 684 INX H 685 JNZ FAST ;DO THE REST 686; NOW OUTPUT BEGIN-END PTRS 687 CALL FOOL ;OUTPUT BEGIN 688 CALL FOOL ;OUTPUT END 689 CALL CRLF ;AND C/R 690; TEST COUNT, H,L POINTS PAST EOFP 691FEET: LXI D,FELEN-NMLEN-4 692 DAD D ;MOVE TO NEXT ENTRY 693 LDA FOCNT 694 DCR A ;TEST COUNT 695 JNZ FINE ;MORE TO DO 696 RET ;DONE! 697; OUTPUT NUMBER POINTED TO BY H,L 698; ON RET, H,L POINT 2 WORDS LATER 699FOOL: CALL BLK1 ;SPACE 700 INX H 701 MOV A,M 702 DCX H 703 PUSH H 704 CALL HOUT ;OUTPUT 705 POP H 706 MOV A,M 707 INX H 708 INX H 709 PUSH H 710 CALL HOTB ;OUTPUT 711 POP H ;RESTORE H,L 712 RET 713; 714; SEARCH THE FILE DIRECTORY FOR THE FILE 715; WHOSE NAME IS IN FBUF. 716; RETURN IF FOUND, ZERO IF OFF, H,L POINT TO 717; ENTRY WHILE SEARCHING, ON ENTRY FOUND WITH ADDR 718; ZERO, SET FEF TO >0 AND FREAD TO THE ADDR OF ENTRY 719; 720FSEA: XRA A 721 STA FEF ;CLAIM NO FREE ENTRIES 722 MVI B,MAXFIL ;COUNT OF ENTRIES 723 LXI D,FILE0 ;TABLE ADDRESS 724FSE10: LXI H,FBUF 725 MVI C,NMLEN 726 CALL SEAR ;TEST STRINGS 727 PUSH PSW ;SAVE FLAG 728 PUSH D 729 LDAX D ;GET BOFP 730 ORA A ;EMPTY ENTRY? 731 JNZ FSE20 732 INX D ;STORE OTHER WORD 733 LDAX D 734 ORA A 735 JNZ FSE20 ;NOPE-GO TEST FOR MATCH 736 XCHG 737 LXI D,-NMLEN-1 738 DAD D ;MOVE TO BEGINNING 739 SHLD FREAD ;SAVE ADDR 740 MOV A,D 741 STA FEF ;SET FREE ENTRY FOUND 742 POP H ;RESTORE INTERIM PTR 743 POP PSW ;UNJUNK STACK 744; MOVE TO NEXT ENTRY 745FSE15: LXI D,FELEN-NMLEN 746 DAD D 747 XCHG ;NEXT ENTRY IN DE 748 DCR B ;TEST COUNT 749 RZ ;DONE--NOPE 750 JMP FSE10 ;TRY NEXT 751; ENTRY WASN?T FREE, TEST FOR MATCH 752FSE20: POP H 753 POP PSW 754 JNZ FSE15 ;IF ZERO CLEAR, NO MATCH 755; ENTRY FOUND 756 LXI D,-NMLEN ;BACKUP 757 DAD D ;H,L POINTS TO ENTRY 758 MOV A,D 759 ORA A ;CLEAR ZERO 760 RET ;THAT?S ALL 761; 762; OUTPUT ERROR MESSAGE FOR ILLEGAL COMMAND 763; 764WHAT: CALL CRLF ;OUT CRLF 765WHA1: LXI H,EMES ;MESSAGE ADDRESS 766MESS: CALL SCRN 767 JMP EOR 768; 769EMES: DB 'WHAT' 770 DB 13 771EMES1: DB 'FULL',13 772EMES2: DB 'NO NO',13 773; 774; CALL ROUTINE TO ENTER DATA INTO MEMORY 775; AND CHECK FOR ERROR ON RETURN 776; 777; THIS ROUTINE IS USED TO ENTER DATA VALUES INTO MEMORY. 778; EACH VALUE IS ONE BYTE AND IS WRITTEN IN HEXADECIMAL 779; VALUES GREATER THAN 255 WILL CAUSE CARRY TO BE SET 780; AND RETURN TO BE MADE TO CALLING PROGRAM 781; 782ENTR: CALL VCHK ;CHECK FOR PARAMETERS 783 CALL ENTS 784 JC WHAT 785 CALL CRLF 786 RET 787; 788EEND EQU '/' ;TERMINATION CHARACTER 789ENTS: CALL CRLF 790 CALL READ ;READ INPUT DATA 791 LXI H,IBUF ;SET LINE POINTER 792 SHLD PNTR ;SAVE POINTER 793ENT1: CALL ZBUF ;CLEAR BUFFER 794 CALL SBLK ;SCAN TO FIRST VALUE 795 JC ENTS ;JUMP IF CR FOUND 796 CPI EEND 797 RZ ;RETURN CARRY IS ZERO 798 CALL ALPS ;PLACE VALUE IN BUFFER 799 MOV A,B ;GET DIGIT COUNT 800 CPI 3 ;CHECK NMBR OF DIGITS 801 CMC 802 RC ;RETURN IF MORE THAN 2 DIGITS 803 LXI B,ABUF ;CONVERSION ADDRESS 804 CALL AHEX ;CONVERT VALUE 805 RC ;ERROR IN HEX CHARACTER 806 MOV A,L 807 LHLD BBUF ;FETCH MEMORY ADDRESS 808 MOV M,A ;PUT IN MEMORY 809 CALL ACH1 ;INCREMENT MEMORY LOCATION 810 JMP ENT1 811; 812; THIS ROUTINE IS USED TO ENTER LINES INTO THE FILE 813; AREA. THE LINE NUMBER IS FIRST CHECKED TO SEE IF IT IS 814; A VALID NUMBER (0000-9999). NEXT IT IS CHECKED TO SEE 815; IF IT IS GREATER THAN THE MAXIMUM CURRENT LINE NUMBER. 816; IF IT IS, THE NEXT LINE IS INSERTED AT THE END OF THE 817; CURRENT FILE AND THE MAXIMUM LINE NUMBER IS UPDATED AS 818; WELL AS THE END OF FILE POSITION. LINE NUMBERS THAT 819; ALREADY EXIST ARE INSERTED INTO THE FILE AREA AT THE 820; APPROPRIATE PLACE AND ANY EXTRA CHARACTERS IN THE OLD 821; LINE ARE DELETED. 822; 823LINE: LDA FILE0 ;IS A FILE DEFINED? 824 ORA A 825 JZ WHAT ;ABORT IF NOT 826 MVI C,4 ;NO OF DIGITS TO CHECK 827 LXI H,IBUF-1 ;INITIALIZE ADDRESS 828LICK: INX H 829 MOV A,M ;FETCH LINE DIGIT 830 CPI '0' ;CHECK FOR VALID NUMBER 831 JC WHAT 832 CPI '9'+1 833 JNC WHAT 834 DCR C 835 JNZ LICK 836 SHLD ADDS ;FIND ADDRESS 837 LXI D,MAXL+3 ;GET ADDRESS 838 CALL COM0 839 JNC INSR 840; GET HERE IF NEW LINE IS GREATER THAN MAXIMUM LINE # 841 INX H 842 CALL LODM ;GET NEW LINE NUMBER 843 LXI H,MAXL+3 844 CALL STOM ;MAKE IT MAXIMUM LINE NUMBER 845 LXI D,IBUF-1 846 LHLD EOFP ;END OF FILE POSITION 847 MVI C,1 848 CALL LMOV ;PLACE LINE IN FILE 849SEOF: MVI M,1 ;END OF FILE INDICATOR 850 SHLD EOFP ;END OF FILE ADDRESS 851 JMP EOR 852; GET HERE IF NEW LINE MUST BE INSERTED INTO ALREADY 853; EISTING FILE AREA 854INSR: CALL FIN1 ;FIND LINE IN FILE 855 MVI C,2 856 JZ EQUL 857 DCR C ;NEW LN NOT EQUAL TO SOME OLD LN 858EQUL: MOV B,M 859 DCX H 860 MVI M,2 ;MOVE LINE INDICATOR 861 SHLD INSP ;INSERT LINE POSITION 862 LDA IBUF-1 ;NEW LINE COUNT 863 DCR C 864 JZ LESS ;NEW LN NOT = OLD LN 865 SUB B ;COUNT DIFFERENCE 866 JZ ZERO ;LINE LENGTHS EQUAL 867 JC MORE 868; GET HERE IF # OF CHARS IN OLD LINE > # OF CHARS IN 869; NEW LINE OR NEW LINE # WAS NOT EQUAL TO SOLD OLD 870; LINE # 871LESS: LHLD EOFP ;END OF FILE ADDRESS 872 MOV D,H 873 MOV E,L 874 CALL ADR ;MOVE TO ADDRESS 875 SHLD EOFP ;NEW END OF FILE ADDRESS 876 MVI C,2 877 CALL RMOV ;OPEN UP FILE AREA 878 JMP ZERO 879; GET HERE IF # OF CHARS IN OLD LINE < # OF CHARS IN 880; NEW LINE 881MORE: CMA 882 INR A ;COUNT DIFFERENCE 883 MOV D,H 884 MOV E,L 885 CALL ADR 886 XCHG 887 CALL LMOV ;DELETE EXCESS CHAR IN FILE 888 MVI M,1 ;E-O-F INDICATOR 889 SHLD EOFP ;E-O-F ADDRESS 890; GET HERE TO INSERT LINE INTO FILE AREA 891ZERO: LHLD INSP ;INSERT ADDRESS 892 MVI M,ASCR 893 INX H 894 LXI D,IBUF-1 ;NEW LINE ADDRESS 895 MVI C,1 ;CHECK VALUE 896 CALL LMOV ;PLACE LINE IN FILE 897 JMP EOR 898; 899; THIS ROUTINE IS USED TO FIND A LN IN THE FILE AREA 900; WHICH IS GREATER THAN OR EQUAL TO THE CURRENT LINE # 901; 902FIND: LXI H,ABUF+3 ;BUFFER ADDRESS 903 SHLD ADDS ;SAVE ADDRESS 904FIN1: LHLD BOFP ;BEGIN FILE ADDRESS 905 MOV A,H ;RETURN TO MONITOR IF 906 ORA L ; FILE IS EMPTY... 907 JZ EOR 908FI1: CALL EO1 ;CHECK FOR END OF FILE 909 XCHG 910 LHLD ADDS ;FETCH FIND ADDRESS 911 XCHG 912 MVI A,4 913 CALL ADR ;BUMP LINE ADDRESS 914 CALL COM0 ;COMPARE LINE NUMBERS 915 RC 916 RZ 917FI2: MOV A,M 918 CALL ADR ;NEXT LINE ADDRESS 919 JMP FI1 920; 921; WHEN SEARCHING THROUGH THE FILE AREA, THIS ROUTINE 922; CHECKS TO SEE IF THE CURRENT ADDRESS IS THE END OF 923; FILE 924; 925EOF: INX H 926EO1: MVI A,1 ;E-O-F INDICATOR 927 CMP M 928 RNZ 929 JMP EOR 930; 931; THIS ROUTINE IS USED TO ADD A VALUE TO AN ADDRESS 932; CONTAINED IN REGISTER H,L 933; 934ADR: ADD L 935 MOV L,A 936 RNC 937 INR H 938 RET 939; 940; THIS ROUTINE WILL MOVE CHARACTER STRINGS FROM ONE 941; LOCATION OF MEMORY TO ANOTHER 942; CHARACTERS ARE MOVED FROM LOCATION ADDRESSED BY D,E 943; TO LOCATION ADDRESSED BY H,L. ADDITIONAL CHARACTERS 944; ARE MOVED BY BUMPING POINTERS UNTIL THE CHARACTER IN 945; REG C IS FETCHED. 946; 947LMOV: LDAX D ;FETCH CHARACTER 948 INX D ;INCREMENT FETCH ADDRESS 949 CMP C ;TERMINATION CHARACTER 950 RZ 951 MOV M,A ;STORE CHARACTER 952 INX H ;INCREMENT STORE ADDRESS 953 JMP LMOV 954; 955; THIS ROUTINE IS SIMILAR TO ABOVE EXCEPT THAT THE 956; CHARACTER ADDRESS IS DECREMENTED AFTER EACH FETCH 957; AND STORE 958; 959RMOV: LDAX D ;FETCH CHARACTER 960 DCX D ;DECREMENT FETCH CHARACTER 961 CMP C ;TERMINATION CHARACTER 962 RZ 963 MOV M,A ;STORE CHARACTER 964 DCX H ;DECREMENT STORE ADDRESS 965 JMP RMOV 966; 967; THIS ROUTINE IS USED TO LOAD FOUR CHARACTERS FROM 968; MEMORY INTO REGISTERS 969; 970 971LODM: MOV B,M ;FETCH CHARACTER 972 INX H 973 MOV C,M ;FETCH CHARACTER 974 INX H 975 MOV D,M ;FETCH CHARACTER 976 INX H 977 MOV E,M ;FETCH CHARACTER 978 RET 979; 980; THIS ROUTINE STORES FOUR CHARACTERS FROM THE REGISTERS 981; INTO MEMORY 982; 983STOM: MOV M,E ;STORE CHARACTER 984 DCX H 985 MOV M,D ;STORE CHARACTER 986 DCX H 987 MOV M,C ;STORE CHARACTER 988 DCX H 989 MOV M,B ;STORE CHARACTER 990 RET 991; 992; THIS ROUTINE IS USED TO COMPARE TWO CHARACTER STRINGS 993; OF LENGTH 4, ON RETURN ZERO FLAG SET MEANS BOTH 994; STRINGS ARE EQUAL. CARRY FLAG =0 MEANS STRING ADDRESS 995; BY D,E WAS GREATER THAN OR EQUAL TO CHARACTER STRING 996; ADDRESSED BY H,L 997; 998COM0: MVI B,1 ;EQUAL COUNTER 999 MVI C,4 ;STRING LENGTH 1000 ORA A ;CLEAR CARRY 1001CO1: LDAX D ;FETCH CHARACTER 1002 SBB M ;COMPARE CHARACTERS 1003 JZ CO2 1004 INR B ;INCREMENT EQUAL COUNTER 1005CO2: DCX D 1006 DCX H 1007 DCR C 1008 JNZ CO1 1009 DCR B 1010 RET 1011; 1012; THIS ROUTINE IS SIMILAR TO THE ABOVE ROUTINE EXCEPT ON 1013; RETURN CARRY FLAG = 0 MEANS THAT CHARACTER STRING 1014; ADDRESSED BY D,E IS ONLY > STRING ADDRESSED BY H,L. 1015; 1016COM1: MVI C,4 ;STRING LENGTH 1017 LDAX D ;TCH CHARACTER 1018 SUI 1 1019 JMP CO1+1 1020; 1021; THIS ROUTINE WILL TAKE ASCII CHARACTERS AND ADD ANY 1022; NECESSARY ASCII ZEROES SO THE RESULT IS A 4 CHARACTER 1023; ASCII VALUE 1024; 1025NORM: CALL LODM ;LOAD CHARACTERS 1026 XRA A ;FETCH A ZERO 1027 CMP B 1028 RZ 1029NOR1: CMP E 1030 CNZ STOM ;STORE VALUES 1031 RNZ 1032 MOV E,D ;NORMALIZE VALUE 1033 MOV D,C 1034 MOV C,B 1035 MVI B,'0' 1036 JMP NOR1 1037; 1038; THIS ROUTINE IS USED TO LIST THE CONTENTS OF THE FILE 1039; AREA STARTING AT THE LINE NUMBER GIVEN IN THE COMMAND 1040; 1041LIST: CALL CRLF 1042 CALL FIND ;FIND STARTING LINE NUMBER 1043LIST0: INX H ;OUTPUT LINE... 1044 CALL SCRN 1045 CALL CRLF 1046 CALL EOF ;CHECK FOR END OF FILE 1047 CALL INK ;CHECK FOR ?X 1048 JNZ LIST0 ;LOOP IF NO ?X 1049 RET 1050; 1051; THIS ROUTINE IS USED TO DELETE LINES FROM THE 1052; FILE AREA. THE REMAINING FILE AREA IS THEN MOVED IN 1053; MEMORY SO THAT THERE IS NO EXCESS SPACE. 1054; 1055DELL: CALL VCHK ;CHECK FOR PARAMETER 1056 CALL FIND ;FIND LINE IN FILE AREA 1057 SHLD DELP ;SAVE DELETE POSITION 1058 LXI H,ABUF+7 1059 MOV A,M ;CHECK FOR 2ND PARAMETER 1060 ORA A ;SET FLAGS 1061 JNZ DEL1 1062 LXI H,ABUF+3 ;USE FIRST PARAMETER 1063DEL1: SHLD ADDS ;SAVE FIND ADDRESS 1064 XCHG 1065 LXI H,MAXL+3 1066 CALL COM0 ;COMPARE LINE NUMBERS 1067 LHLD DELP ;LOAD DELETE POSITION 1068 JC NOVR 1069; GET HERE IF DELETION INVOLVES END OF FILE 1070 SHLD EOFP ;CHANGE E-O-F POSITION 1071 MVI M,1 ;SET E-O-F INDICATOR 1072 XCHG 1073 LHLD BOFP 1074 XCHG 1075 MVI B,13 ;SET SCAN SWITCH 1076 DCX H ;CHECK FOR BOFP 1077DEL2: MOV A,L 1078 SUB E 1079 MOV A,H 1080 SBB D 1081 MVI A,ASCR ;LOOK FOR CR 1082 JC DEL4 ;DECREMENTED PAST BOF 1083 DCR B 1084 DCX H 1085 CMP M ;FIND NEW MAX LN 1086 JNZ DEL2 1087 DCX H 1088 MOV A,L 1089 SUB E 1090 MOV A,H 1091 SBB D 1092 JC DEL5 1093 CMP M ;END OF PREVIOUS LINE 1094 INX H 1095 INX H 1096 JZ DEL3 1097 INX H 1098DEL3: CALL LODM ;LOAD NEW MAX LN 1099 LXI H,MAXL+3 ;SET ADDRESS 1100 CALL STOM ;STORE NEW MAX LN 1101 RET 1102DEL4: CMP B ;CHECK SWITCH 1103DEL5: XCHG 1104 JNZ DEL3-1 1105 STA MAXL ;MAKE MAX LN A SMALL NUMBER 1106 RET 1107; GET HERE IF DELETION IS IN THE MIDDLE OF FILE AREA 1108NOVR: CALL FI1 ;FIND END OF DELETE AREA 1109 CZ FI2 ;NEXT LINE IF THIS LN EQUAL 1110NOV1: XCHG 1111 LHLD DELP ;CHAR MOVE TO POSITION 1112 MVI C,1 ;MOVE TERMINATOR 1113 CALL LMOV ;COMPACT FILE AREA 1114 SHLD EOFP ;SET EOF POSITION 1115 MVI M,1 ;SET EOF INDICATOR 1116 RET 1117; 1118; STARTING HERE IS THE SELF ASSEMBLER PROGRAM 1119; THIS PROGRAM ASSEMBLES PROGRAMS WHICH ARE 1120; IN THE FILE AREA 1121; 1122ASSM: CALL VCHK ;CHECK FOR PARAMETERS 1123 LDA ABUF+4 ;GET 2ND PARAMETER 1124 ORA A ;CHECK FOR PRARMETERS 1125 JNZ ASM4 1126 LHLD BBUF ;FETCH 1ST PARAMETER 1127 SHLD BBUF+2 ;STORE INTO 2ND PARAMETER 1128ASM4: LDA IBUF+4 ;FETCH INPUT CHARACTER 1129 SUI 'E' ;RESET a IF ERRORS ONLY 1130 STA AERR ;SAVE ERROR FLAG 1131 XRA A ;GET A ZERO 1132 STA NOLA ;INITIALIZE LABEL COUNT 1133ASM3: STA PASI ;SET PASS INDICATOR 1134 CALL CRLF ;INDICATE START OF PASS 1135 LHLD BBUF ;FETCH ORIGIN 1136 SHLD ASPC ;INITIALIZE PC 1137 LHLD BOFP ;GET START OF FILE 1138 SHLD APNT 1139ASM1: LHLD APNT ;FETCH LINE POINTER 1140 LXI SP,AREA+18 1141 MOV A,M ;FETCH CHARACTER 1142 CPI 1 ;END OF FILE? 1143 JZ EASS ;JUMP IF END OF FILE 1144 XCHG 1145 INX D ;INCREMENT ADDRESS 1146 LXI H,OBUF ;BLANK START ADDRESS 1147 MVI A,IBUF-5 AND 0FFH ;BLANK END ADDRESS 1148 CALL CLER ;BLANK OUT BUFFER 1149 MVI C,ASCR ;STOP CHARACTER 1150 CALL LMOV ;MOVE LINE INTO BUFFER 1151 MOV M,C ;PLACE CR IN BUFFER 1152 XCHG 1153 SHLD APNT ;SAVE ADDRESS 1154 LDA PASI ;FETCH PASS INDICATOR 1155 ORA A ;SET FLAGW 1156 JNZ ASM2 ;JUMP IF PASS 2 1157 CALL PAS1 1158 JMP ASM1 1159; 1160ASM2: CALL PAS2 1161 LXI H,OBUF ;OUTPUT BUFFER ADDRESS 1162 CALL AOUT ;OUTPUT LINE 1163 JMP ASM1 1164; 1165; THIS ROUTINE IS USED TO OUTPUT THE LISTING FOR 1166; AN ASSEMBLY. IT CHECKS THE ERROR SWITCH TO SEE IF 1167; ALL LINES ARE TO BE PRINTED OR JUST THOSE WITH 1168; ERRORS. 1169; 1170AOUT: LDA AERR ;FETCH ERROR SWITCH 1171 ORA A ;SET FLAGS 1172 JNZ AOU1 ;OUTPUT ALL LINES 1173AOU2: LDA OBUF ;FETCH ERROR INDICATOR 1174 CPI ' ' ;CHECK FOR AN ERROR 1175 RZ ;RETURN IF NO ERROR 1176AOU1: LXI H,OBUF ;OUTPUT BUFFER ADDRESS 1177 CALL SCRN ;OUTPUT LINE... 1178 CALL CRLF 1179 RET 1180; 1181; PASS 1 OF ASSEMBLER, USED TO FORM SYMBOL TABLE 1182; 1183PAS1: CALL ZBUF ;CLEAR BUFFER 1184 STA PASI ;SET FOR PASS1 1185 LXI H,IBUF ;INITIALIZE LINE POINTER 1186 SHLD PNTR 1187 MOV A,M ;FETCH CHARACTER 1188 CPI ' ' ;CHECK FOR A BLANK 1189 JZ OPC ;JUMP IF NO LABLE 1190 CPI '*' ;CHECK FOR COMMENT 1191 RZ ;RETURN IF COMMENT 1192; 1193; PROCESS LABEL 1194; 1195 CALL SLAB ;GET AND CHECK LABEL 1196 JC OP5 ;ERROR IN LABEL 1197 JZ ERRD ;DUPLICATE LABEL 1198 CALL LCHK ;CHECK CHARACTER AFTER LABEL 1199 JNZ OP5 ;ERROR IF NO BLANK 1200 MVI C,LLAB ;LENGTH OF LABELS 1201 LXI H,ABUF ;SET BUFFER ADDRESS 1202MLAB: MOV A,M ;FETCH NEXT CHARACTER 1203 STAX D ;STORE IN SYMBOL TABLE 1204 INX D 1205 INX H 1206 DCR C 1207 JNZ MLAB 1208 XCHG 1209 SHLD TABA ;SAVE TABLE ADDRESS FOR EQU 1210 LDA ASPC+1 ;FETCH PC (HIGH) 1211 MOV M,A 1212 INX H 1213 LDA ASPC ;FETCH PC (LOW) 1214 MOV M,A ;STORE IN TABLE 1215 LXI H,NOLA 1216 INR M ;INCREMENT NUMBER OF LABELS 1217; 1218; PROCESS OPCODE 1219; 1220OPC: CALL ZBUF ;ZERO WORKING BUFFER 1221 CALL SBLK ;SCAN TO OPCODE 1222 JC OERR ;FOUND CARRIAGE RETURN 1223 CALL ALPS ;PLACE OPCODE IN BUFFER 1224 CPI ' ' ;CHECK FOR BLANK AFTER OPCODE 1225 JC OPCD ;CR AFTER OPCODE 1226 JNZ OERR ;ERROR IF NO BLANK 1227 JMP OPCD ;CHECK OPCODE 1228; 1229; THIS ROUTINE CHECKS THE CHARACTER AFTER A LABEL 1230; FOR A BLANK OR COLON 1231; 1232LCHK: LHLD PNTR 1233 MOV A,M ;GET CHARACTER AFTER LABEL 1234 CPI ' ' ;CHECK FOR BLANK 1235 RZ ;RETURN IF A BLANK 1236 CPI ':' ;CHECK FOR COLON 1237 RNZ 1238 INX H 1239 SHLD PNTR ;SAVE POINTER 1240 RET 1241; 1242; PROCESS ANY PSEUDO OPS THAT NEED TO BE IN PASS 1 1243; 1244PSU1: CALL SBLK ;SCAN TO OPERAND 1245 LDAX D ;FETCH VALUE 1246 ORA A ;SET FLAGS 1247 JZ ORG1 ;ORG OPCODE 1248 JM DAT1 ;DATA STATEMENT 1249 JPO EQU1 ;EQU OPCODE 1250 CPI 5 1251 JC RES1 ;RES OPCODE 1252 JNZ EASS ;JUMP IF END 1253; DO DW PSEUDO/OP 1254ACO1: MVI C,2 ;2 BYTE INSTRUCTION 1255 XRA A ;GET A ZERO 1256 JMP OCN1 ;ADD VALUE TO PROGRAM COUNTER 1257; DO ORG PSUEDO OP 1258ORG1: CALL ASCN ;GET OPERAND 1259 LDA OBUF ;FETCH ERROR INDICATOR 1260 CPI ' ' ;CHECK FOR AN ERROR 1261 RNZ 1262 SHLD ASPC ;STORE NEW ORIGIN 1263 LDA IBUF ;GET FIRST CHARACTER 1264 CPI ' ' ;CHECK FOR AN ERROR 1265 RZ ;NO LABEL 1266 JMP EQUS ;CHANGE LABEL VALUE 1267; DO EQU PSUEDO-OP 1268EQU1: CALL ASCN ;GET OPERAND 1269 LDA IBUF ;FETCH 1ST CHARACTER 1270 CPI ' ' ;CHECK FOR LABEL 1271 JZ ERRM ;MISSING LABEL 1272EQUS: XCHG 1273 LHLD TABA ;SYMBOL TABLE ADDRESS 1274 MOV M,D ;STORE LABEL VALUE 1275 INX H 1276 MOV M,E 1277 RET 1278; DO DS PSEUDO-OP 1279RES1: CALL ASCN ;GET OPERAND 1280 MOV B,H 1281 MOV C,L 1282 JMP RES21 ;ADD VALUE TO PROGRAM COUNTER 1283; 1284; DO DB PSEUDO-OP 1285; 1286DAT1: JMP DAT2A 1287; 1288; PERFORM PASS 2 OF THE ASSEMBLER 1289; 1290PAS2: LXI H,OBUF+2 ;SET OUTPUT BUFFER ADDRESS 1291 LDA ASPC+1 ;FETCH PC (HIGH) 1292 CALL BINH+3 ;CONVERT FOR OUTPUT 1293 INX H 1294 LDA ASPC ;FETCH PC(LOW) 1295 CALL BINH+3 ;CONVERT FOR OUTPUT 1296 INX H 1297 SHLD OIND ;SAVE OUTPUT ADDRESS 1298 CALL ZBUF ;CLEAR BUFFER 1299 LXI H,IBUF ;INITIALIZE LINE POINTER 1300PABL: SHLD PNTR ;SAVE POINTER 1301 MOV A,M ;FETCH FIRST CHARACTER 1302 CPI ' ' ;CHECK FOR LABEL 1303 JZ OPC ;GET OPCODE 1304 CPI '*' ;CHECK FOR COMMENT 1305 RZ ;RETURN IF COMMENT 1306 CALL SLAB ;SCAN OFF LABEL 1307 JC ERRL ;ERROR IN LABEL 1308 CALL LCHK ;CHECK FOR A BLANK OR COLON 1309 JNZ ERRL ;ERROR IF NOT A BLANK 1310 JMP OPC 1311; 1312; PROCESS PSEUDO OPS FOR PASS2 1313; 1314PSU2: LDAX D 1315 ORA A ;SET FLAGS 1316 JZ ORG2 ;ORG OPCODE 1317 JM DAT2 ;DATA OPCODE 1318 JPO EQU2 ;EQUATE PSEUDO-OP 1319 CPI 5 1320 JC RES2 ;RES OPCODE 1321 JNZ EASS ;END OPCODE 1322; DO DW OPCODE 1323ACO2: CALL TYS6 ;GET VALUE 1324 JMP ACO1 1325; DO DS PSEUDO-OP 1326RES2: CALL ASBL ;GET OPERAND 1327 MOV B,H 1328 MOV C,L 1329 LHLD BBUF+2 ;FETCH STORAGE COUNTER 1330 DAD B ;ADD VALUE 1331 SHLD BBUF+2 1332RES21: XRA A ;GET A ZERO 1333 JMP OCN2 1334; DO DB PSEUDO-OP 1335DAT2: CALL TY55 ;GET OPERAND 1336DAT2A: XRA A ;MAKE ZERO 1337 MVI C,1 ;BYTE COUNT 1338 JMP OCN1 1339; 1340; HANDLE EQUATES ON 2ND PASS 1341; 1342EQU2: CALL ASBL ;GET OPERAND INTO HL AND 1343 ; FALL INTO NEXT ROUTINE 1344; 1345; STORE CONTENTS OF HL AS HEX ASCII AT OBUF+2 1346; ON RETURN, DE HOLDS VALUE WHICH WAS IN HL. 1347; 1348BINAD: XCHG ;PUT VALUE INTO DE 1349 LXI H,OBUF+2 ;POINTER TO ADDR IN OBUF 1350 MOV A,D ;STORE HI BYTE 1351 CALL BINH+3 1352 INX H 1353 MOV A,E ;STORE LOW BYTE... 1354 CALL BINH+3 1355 INX H 1356 RET 1357; DO ORG PSEUDO-OP 1358ORG2: CALL ASBL ;GET NEW ORIGIN 1359 LDA OBUF ;GET ERROR INDICATOR 1360 CPI ' ' ;CHECK FOR AN ERROR 1361 RNZ ;DON?T MODIFY PC IF ERROR 1362 CALL BINAD ;STORE NEW ADDR IN OBUF 1363 LHLD ASPC ;FETCH PC 1364 XCHG 1365 SHLD ASPC ;STORE NEW PC 1366 MOV A,L 1367 SUB E ;FORM DIFFERENCE OF ORIGINS 1368 MOV E,A 1369 MOV A,H 1370 SBB D 1371 MOV D,A 1372 LHLD BBUF+2 ;FETCH STORAGE POINTER 1373 DAD D ;MODIFY 1374 SHLD BBUF+2 ;SAVE 1375 RET 1376; 1377; PROCESS 1 BYTE INSTRUCTIONS WITHOUT OPERANDS 1378; 1379TYP1: CALL ASTO ;STORE VALUE IN MEMORY 1380 RET 1381; 1382; PROCESS STAX AND LDAX INSTRUCTIONS 1383; 1384TYP2: CALL ASBL ;FETCH OPERAND 1385 CNZ ERRR ;ILLEGAL REGISTER 1386 MOV A,L ;GET LOW ORDER OPERAND 1387 ORA A ;SET FLAGS 1388 JZ TY31 ;OPERAND = 0 1389 CPI 2 ;OPERAND = 2 1390 CNZ ERRR ;ILLEGAL REGISTER 1391 JMP TY31 1392; 1393; PROCESS PUSH, POP, INX, DCX, DAD INSTRUCTIONS 1394; 1395TYP3: CALL ASBL ;FETCH OPERAND 1396 CNZ ERRR ;ILLEGAL REGISTER 1397 MOV A,L ;GET LOW ORDER OPERAND 1398 RRC ;CHECK LOW ORDER BIT 1399 CC ERRR ;ILLEGAL REGISTER 1400 RAL ;RESTORE 1401 CPI 8 1402 CNC ERRR ;ILLEGAL REGISTER 1403TY31: RLC ;MULTIPLY BY 8 1404 RAL 1405 RAL 1406TY32: MOV B,A 1407 LDAX D ;FETCH OPCODE BASE 1408 ADD B ;FORM OPCODE 1409 CPI 118 ;CHECK FOR MOV M,M 1410 CZ ERRR ;ILLEGAL REGISTER 1411 JMP TYP1 1412; 1413; PROCESS ACCUMULATOR, INR,DCR,MOV,RST INSTRUCTIONS 1414; 1415TYP4: CALL ASBL ;FETCH OPERAND 1416 CNZ ERRR ;ILLEGAL REGISTER 1417 MOV A,L ;GET LOW ORDER OPERAND 1418 CPI 8 1419 CNC ERRR ;ILLEGAL REGISTER 1420 LDAX D ;FETCH OPCODE BASE 1421 CPI 64 ;CHECK FOR MOV INSTRUCTION 1422 JZ TY41 1423 CPI 199 1424 MOV A,L 1425 JZ TY31 ;RST INSTRUCTION 1426 JM TY32 ;ACCUMULATOR INSTRUCTION 1427 JMP TY31 ;INR, DCR 1428; PROCESS MOV INSTRUCTION 1429TY41: DAD H ;MULTIPLY OPERAND BY 8 1430 DAD H 1431 DAD H 1432 ADD L ;FORM OPCODE 1433 STAX D ;SAVE OPCODE 1434 CALL MPNT 1435 CALL ASCN 1436 CNZ ERRR ;INCREMENT POINTER 1437 MOV A,L 1438 CPI 8 1439 CNC ERRR ;ILLEGAL REGISTER 1440 JMP TY32 1441; 1442; PROCESS IMMEDIATE INSTRUCTIONS 1443; IMMEDIATE BYTE CAN BETWEEN -256 AND +255 1444; MVI INSTRUCTION IS A SPECIAL CASE AND CONTAINS 1445; 2 ARGUMENTS IN OPERAND 1446; 1447TYP5: CPI 6 ;CHECK FOR MVI 1448 CZ TY56 1449 CALL ASTO ;STORE OBJECT BYTE 1450TY55: CALL ASBL ;GET IMMEDIATE ARGUMENT 1451 INR A 1452 CPI 2 ;CHECK OPERAND FOR RANGE 1453 CNC ERRV 1454 MOV A,L 1455 JMP TYP1 1456; 1457; FETCH 1ST ARG FOR MVI AND LXI INSTRUCTIONS 1458; 1459TY56: CALL ASBL ;FETCH ARG 1460 CNZ ERRR ;ILLEGAL REGISTER 1461 MOV A,L ;GET LOW ORDER ARGUMENT 1462 CPI 8 1463 CNC ERRR ;ILLEGAL REGISTER 1464 DAD H 1465 DAD H 1466 DAD H 1467 LDAX D ;FETCH OPCODE BASE 1468 ADD L ;FOR OPCODE 1469 MOV E,A ;SAVE OBJECT BYTE 1470MPNT: LHLD PNTR ;FETCH POINTER 1471 MOV A,M ;FETCH CHARACTER 1472 CPI ',' ;CHECK FOR COMMA 1473 INX H ;INCREMENT POINTER 1474 SHLD PNTR 1475 JNZ ERRS ;SYNTAX ERROR IF NO COMMA 1476 MOV A,E 1477 RET 1478; 1479; PROCESS 3 BYTE INSTRUCTIONS 1480; LXI INSTRUCTION IS A SPECIAL CASE 1481; 1482TYP6: CPI 1 ;CHECK FOR LXI INSTRUCTION 1483 JNZ TY6 ;JUMP IF NOT LXI 1484 CALL TY56 ;GET REGISTER 1485 ANI 08H ;CHECK FOR ILLEGAL REGISTER 1486 CNZ ERRR ;REGISTER ERROR 1487 MOV A,E ;GET OPCODE 1488 ANI 0F7H ;CLEAR BIT IN ERROR 1489TY6: CALL ASTO ;STORE OBJECT BYTE 1490TYS6: CALL ASBL ;FETCH OPERAND 1491 MOV A,L 1492 MOV D,H 1493 CALL ASTO ;STORE 2ND BYTE 1494 MOV A,D 1495 JMP TYP1 1496 RET 1497; 1498; THIS ROUTINE IS USED TO STORE OBJECT CODE PRODUCED 1499; BY THE ASSEMBLER DURING PASS 2 INTO MEMORY 1500; 1501ASTO: LHLD BBUF+2 ;FETCH STORAGE ADDRESS 1502 MOV M,A ;STORE OBJECT BYTE 1503 INX H ;INCREMENT LOCATION 1504 SHLD BBUF+2 1505 LHLD OIND ;FETCH OUTPUT ADDRESS 1506 INX H 1507 CALL BINH+3 ;CONVERT OBJECT BYTE 1508 SHLD OIND 1509 RET 1510; 1511; GET HERE WHEN END PSEUDO-OP IS FOUND OR WHEN 1512; END-OF-FILE OCCURS IN SOURCE FILE. CONTROL IS SET 1513; FOR EITHER PASS 2 OR ASSEMBLY TERMINATOR IF FINISHED 1514; 1515EASS: LDA PASI ;FETCH PASS INDICATOR 1516 ORA A ;SET FLAGS 1517 JNZ EOR ;JUMP IF FINISHED 1518 MVI A,1 ;PASS INDICATOR FOR 2ND PASS 1519 JMP ASM3 ;DO 2ND PASS 1520; 1521; THIS ROUTINE SCANS THROUGH A CHARACTER STRING UNTIL 1522; THE FIRST NON-BLANK CHARACTER IS FOUND 1523; 1524; ON RETURN, CARRY SET INDICATES A CARRIAGE RETURN 1525; AS FIRST NON-BLANK CHARACTER. 1526; 1527SBLK: LHLD PNTR ;FETCH ADDRESS 1528SBL1: MOV A,M ;FETCH CHARACTER 1529 CPI ' ' ;CHECK FOR BLANK 1530 RNZ ;RETURN IF NON-BLANK 1531SBL2: INX H ;INCREMENT 1532 SHLD PNTR ;SAVE POINTER 1533 JMP SBL1 1534; 1535; THIS ROUTINE IS USED TO CHECK THE CONDITION 1536; CODE NMEUMONICS FOR CONDITIONAL JUMPS, CALLS, 1537; AND RETURNS. 1538; 1539COND: LXI H,ABUF+1 1540 SHLD ADDS 1541 MVI B,2 ;2 CHARACTERS 1542 CALL COPC 1543 RET 1544; 1545; THE FOLLOWING IS THE OPCODE TABLE 1546; 1547OTAB: DB 'ORG' 1548 DB 0 1549 DB 0 1550 DB 'EQU' 1551 DB 0 1552 DB 1 1553 DB 'DB' 1554 DB 0 1555 DB 0 1556 DB -1 AND 0FFH 1557 DB 'DS' 1558 DB 0 1559 DB 0 1560 DB 3 1561 DB 'DW' 1562 DB 0 1563 DB 0 1564 DB 5 1565 DB 'END' 1566 DB 0 1567 DB 6 1568 DB 0 1569 DB 'HLT' 1570 DB 118 1571 DB 'RLC' 1572 DB 7 1573 DB 'RRC' 1574 DB 15 1575 DB 'RAL' 1576 DB 23 1577 DB 'RAR' 1578 DB 31 1579 DB 'RET' 1580 DB 201 1581 DB 'CMA' 1582 DB 47 1583 DB 'STC' 1584 DB 55 1585 DB 'DAA' 1586 DB 39 1587 DB 'CMC' 1588 DB 63 1589 DB 'EI' 1590 DB 0 1591 DB 251 1592 DB 'DI' 1593 DB 0 1594 DB 243 1595 DB 'NOP' 1596 DB 0 1597 DB 0 1598 DB 'XCHG' 1599 DB 235 1600 DB 'XTHL' 1601 DB 227 1602 DB 'SPHL' 1603 DB 249 1604 DB 'PCHL' 1605 DB 233 1606 DB 0 1607 DB 'STAX' 1608 DB 2 1609 DB 'LDAX' 1610 DB 10 1611 DB 0 1612 DB 'PUSH' 1613 DB 197 1614 DB 'POP' 1615 DB 0 1616 DB 193 1617 DB 'INX' 1618 DB 0 1619 DB 3 1620 DB 'DCX' 1621 DB 0 1622 DB 11 1623 DB 'DAD' 1624 DB 0 1625 DB 9 1626 DB 0 1627 DB 'INR' 1628 DB 4 1629 DB 'DCR' 1630 DB 5 1631 DB 'MOV' 1632 DB 64 1633 DB 'ADD' 1634 DB 128 1635 DB 'ADC' 1636 DB 136 1637 DB 'SUB' 1638 DB 144 1639 DB 'SBB' 1640 DB 152 1641 DB 'ANA' 1642 DB 160 1643 DB 'XRA' 1644 DB 168 1645 DB 'ORA' 1646 DB 176 1647 DB 'CMP' 1648 DB 184 1649 DB 'RST' 1650 DB 199 1651 DB 0 1652 DB 'ADI' 1653 DB 198 1654 DB 'ACI' 1655 DB 206 1656 DB 'SUI' 1657 DB 214 1658 DB 'SBI' 1659 DB 222 1660 DB 'ANI' 1661 DB 230 1662 DB 'XRI' 1663 DB 238 1664 DB 'ORI' 1665 DB 246 1666 DB 'CPI' 1667 DB 254 1668 DB 'IN' 1669 DB 0 1670 DB 219 1671 DB 'OUT' 1672 DB 211 1673 DB 'MVI' 1674 DB 6 1675 DB 0 1676 DB 'JMP' 1677 DB 0 1678 DB 195 1679 DB 'CALL' 1680 DB 205 1681 DB 'LXI' 1682 DB 0 1683 DB 1 1684 DB 'LDA' 1685 DB 0 1686 DB 58 1687 DB 'STA' 1688 DB 0 1689 DB 50 1690 DB 'SHLD' 1691 DB 34 1692 DB 'LHLD' 1693 DB 42 1694 DB 0 1695; CONDITION CODE TABLE 1696 DB 'NZ' 1697 DB 0 1698 DB 'Z' 1699 DB 0 1700 DB 8 1701 DB 'NC' 1702 DB 16 1703 DB 'C' 1704 DB 0 1705 DB 24 1706 DB 'PO' 1707 DB 32 1708 DB 'PE' 1709 DB 40 1710 DB 'P' 1711 DB 0 1712 DB 48 1713 DB 'M' 1714 DB 0 1715 DB 56 1716 DB 0 1717; 1718; THIS ROUTINE IS USED TO CHECK A GIVEN OPCODE 1719; AGAINST THE LEGAL OPCODES IN THE OPCODE TABLE 1720; 1721COPC: LHLD ADDS 1722 LDAX D ;FETCH CHARACTER 1723 ORA A ;SET FLAGS 1724 JZ COP1 ;JUMP IF TERMINATION CHARACTER 1725 MOV C,B 1726 CALL SEAR 1727 LDAX D 1728 RZ ;RETURN IF A MATCH 1729 INX D ; NEXT STRING 1730 JMP COPC ;CONTINUE SEARCH 1731COP1: INR A ;CLEAR ZERO FLAG 1732 INX D ;INCREMENT ADDRESS 1733 RET 1734; 1735; THIS ROUTINE CHECKS THE LEGAL OPCODES IN BOTH PASS 1 1736; AND PASS 2. IN PASS 1 THE PROGRAM COUNTER IS INCRE- 1737; MENTED BY THE CORRECT NUMBER OF BYTES. AN ADDRESS IS 1738; ALSO SET SO THAT AN INDEXED JUMP CAN BE MADE TO 1739; PROCESS THE OPCODE FOR PASS 2. 1740; 1741OPCD: LXI H,ABUF ;GET ADDRESS 1742 SHLD ADDS 1743 LXI D,OTAB ;OPCODE TABLE ADDRESS 1744 MVI B,4 ;CHARACTER COUNT 1745 CALL COPC ;CHECK OPCODE 1746 JZ PSEU ;JUMP IF PSEUDO-OP 1747 DCR B ;3-CHARACTER OPCODES 1748 CALL COPC 1749 JZ OP1 1750 INR B ;4 CHARACTER OPCODES 1751 CALL COPC 1752OP1: LXI H,TYP1 ;TYPE 1 INSTRUCTIONS 1753OP2: MVI C,1 ;1 BYTE INSTRUCTIONS 1754 JZ OCNT 1755; 1756OPC2: CALL COPC ;CHECK FOR STAX, LDAX 1757 LXI H,TYP2 1758 JZ OP2 1759 CALL COPC ;CHECK FOR PUSH,POP,INX 1760 ; DCX AND DAD 1761 LXI H,TYP3 1762 JZ OP2 1763 DCR B ;3 CHAR OPCODES 1764 CALL COPC ;ACCUMULATOR INSTRUCTIONS, 1765 ; INR, DCR, MOV, RST 1766 LXI H,TYP4 1767 JZ OP2 1768; 1769OPC3: CALL COPC ;IMMEDIATE INSTRUCTIONS 1770 LXI H,TYP5 1771 MVI C,2 ;2 BYTE INSTRUCTIONS 1772 JZ OCNT 1773 INR B ;4 CHARACTER OPCODES 1774 CALL COPC ;JMP, CALL, LIX, LDA, STA, 1775 ; LHLD, SHLD OPCODES 1776 JZ OP4 1777 CALL COND ;CONDITIONAL INSTRUCTIONS 1778 JNZ OERR ;ILLEGAL OPCODE 1779 ADI 192 ;ADD BASE VALUE TO RETURN 1780 MOV D,A 1781 MVI B,3 ;3 CHARACTER OPCODES 1782 LDA ABUF ;FETCH FIRST CHARACTER 1783 MOV C,A ;SAVE CHARACTER 1784 CPI 'R' ;CONDITIONAL RETURN 1785 MOV A,D 1786 JZ OP1 1787 MOV A,C 1788 INR D ;FORM CONDITIONAL JUMP 1789 INR D 1790 CPI 'J' ;CONDITIONAL JUMP 1791 JZ OPAD 1792 CPI 'C' ;CONDITIONAL CALL 1793 JNZ OERR ;ILLEGAL OPCODE 1794 INR D ;FORM CONDITIONAL CALL 1795 INR D 1796OPAD: MOV A,D ;GET OPCODE 1797OP4: LXI H,TYP6 1798OP5: MVI C,3 ;3 BYTE INSTRUCTION 1799OCNT: STA TEMP ;SAVE OPCODE 1800; 1801; CHECK FOR OPCODE ONLY CONTAINING THE CORRECT NUMBER OF 1802; CHARACTERS. THUS ADDQ, SAY, WOULD GIVE AN ERROR 1803; 1804 MVI A,ABUF AND 0FFH ;LOAD BUFFER ADDRESS 1805 ADD B ;ADD LENGTH OF BUFFER 1806 MOV E,A 1807 MVI A,ABUF/256 1808 ACI 0 ;GET HIGH ORDER ADDRESS 1809 MOV D,A 1810 LDAX D ;FETCH CHARACTER AFTER OPCODE 1811 ORA A ;IT SHOULD BE ZERO 1812 JNZ OERR ;OPCODE ERROR 1813 LDA PASI ;FETCH PASS INDICATOR 1814OCN1: MVI B,0 1815 XCHG 1816OCN2: LHLD ASPC ;FETCH PROGRAM COUNTER 1817 DAD B ;ADD IN BYTE COUNT 1818 SHLD ASPC ;STORE PC 1819 ORA A ;WHICH PASS? 1820 RZ ;RETURN IF PASS 1 1821 LDA TEMP ;FETCH OPCODE 1822 XCHG 1823 PCHL 1824; 1825OERR: LXI H,ERRO ;GET ERROR ADDRESS 1826 MVI C,3 ;LEAVE 3 BYTES FOR PATCH 1827 JMP OCN1-3 1828; 1829PSEU: LXI H,ABUF+4 ;SET BUFFER ADDRESS 1830 MOV A,M ;FETCH CHARACTER AFTER OPCODE 1831 ORA A ;SHOULD BE A ZERO 1832 JNZ OERR 1833 LDA PASI ;FETCH PASS INDICATOR 1834 ORA A 1835 JZ PSU1 1836 JMP PSU2 1837; 1838; THIS ROUTINE IS USED TO PROCESS LABELS. 1839; IT CHECKS TO SEE IF A LABEL IS IN THE SYMBOL TABLE 1840; OR NOT. ON RETURN, Z=1 INDICATES A MATCH WAS FOUND 1841; AND H,L CONTAIN THE VALUE ASSOCIATED WITH THE LABEL. 1842; THE REGISTER NAMES A, B, C, D, E, H, L, P, AND S ARE 1843; PRE-DEFINED AND NEED NOT BE ENTERED BY THE USER. 1844; ON RETURN, C=1 INDICATES A LABEL ERROR. 1845; 1846SLAB: CPI 'A' ;CHECK FOR LEGAL CHARACTER 1847 RC 1848 CPI 'Z'+1 ;CHECK FOR ILLEGAL CHARACTER 1849 CMC 1850 RC ;RETURN IF ILLEGAL CHARACTER 1851 CALL ALPS ;PLACE SYMBOL IN BUFFER 1852 LXI H,ABUF ;SET BUFFER ADDRESS 1853 SHLD ADDS ;SAVE ADDRESS 1854 DCR B ;CHECK IF ONE CHARACTER 1855 JNZ SLA1 1856; CHECK IF PREFEFINED REGISTER NAME 1857 INR B ;SET B=1 1858 LXI D,RTAB ;REGISTER NAME TABLE 1859 CALL COPC ;CHECK NAME OF REGISTER 1860 JNZ SLA1 ;NOT A PREFEFINED REGIGTER 1861 MOV L,A ;SET VALUE (HIGH) 1862 MVI H,0 1863 JMP SLA2 1864SLA1: LDA NOLA ;FETCH SYMBOL COUNT 1865 MOV B,A 1866 LXI D,SYMT ;SET SYMBOL TABLE ADDRESS 1867 ORA A ;ARE THERE ANY LABELS? 1868 JZ SLA3 ;JUMP IF NO LABELS 1869 MVI A,LLAB ;FETCH LENGTH OF LABEL 1870 STA NCHR 1871 CALL COMS ;CHECK TABLE 1872 MOV C,H ;SWAP H AND L 1873 MOV H,L 1874 MOV L,C 1875SLA2: STC ;SET CARRY 1876 CMC ;CLEAR CARRY 1877 RET ;RETURN 1878SLA3: INR A ;CLEAR ZERO FLAG 1879 ORA A ;CLEAR CARRY 1880 RET 1881; 1882; PREDEFINE REGISTER VALUES IN THIS TABLE 1883; 1884RTAB: DB 'A' 1885 DB 7 1886 DB 'B' 1887 DB 0 1888 DB 'C' 1889 DB 1 1890 DB 'D' 1891 DB 2 1892 DB 'E' 1893 DB 3 1894 DB 'H' 1895 DB 4 1896 DB 'L' 1897 DB 5 1898 DB 'M' 1899 DB 6 1900 DB 'P' 1901 DB 6 1902 DB 'S' 1903 DB 6 1904 DB 0 ;END OF TABLE INDICATOR. 1905; 1906; THIS ROUTINE SCANS THE INPUT LINE AND PLACES TH 1907; OPCODES AND LABELS IN THE BUFFER. THE SCAN TERMINATES 1908; WHEN A CHARACTER OTHER THAN 0-9 OR A-Z IS FOUND. 1909; 1910ALPS: MVI B,0 ;SET COUNT 1911ALP1: STAX D ;STORE CHARACTER IN BUFFER 1912 INR B ;INCREMENT COUNT 1913 MOV A,B ;FETCH COUNT 1914 CPI 11 ;MAXIMUM BUFFER SIZE 1915 RNC ;RETURN IF BUFFER FILLED 1916 INX D ;INCREMENT BUFFER 1917 INX H ;INCREMENT INPUT POINTER 1918 SHLD PNTR ;SAVE LINE POINTER 1919 MOV A,M ;FETCH CHARACTER 1920 CPI '0' ;CHECK FOR ILLEGAL CHARACTERS 1921 RC 1922 CPI '9'+1 1923 JC ALP1 1924 CPI 'A' 1925 RC 1926 CPI 'Z'+1 1927 JC ALP1 1928 RET 1929; 1930; THIS ROUTINE IS USED TO SCAN THROUGH THE INPUT LINE 1931; TO FETCH THE VALUE OF THE OPERAND FIELD. ON RETURN, 1932; THE VALUE OF THE OPERAND IS CONTAINED IN REG?S H,L 1933; 1934ASBL: CALL SBLK ;GET 1ST ARGUMENT 1935ASCN: LXI H,0 ;GET A ZERO 1936 SHLD OPRD ;INITIALIZE OPERAND 1937 INR H 1938 SHLD OPRI-1 ;INITIALIZE OPERAND INDICATOR 1939NXT1: LHLD PNTR ;FETCH SCAN POINTER 1940 DCX H 1941 CALL ZBUF ;CLEAR BUFFER 1942 STA SIGN ;ZERO SIGN INDICATOR 1943NXT2: INX H ;INCREMENT POINTER 1944 MOV A,M ;FETCH NEXT CHARACTER 1945 CPI ' '+1 1946 JC SEND ;JUMP IF CR OR BLANK 1947 CPI ',' ;FIELD SEPARATOR 1948 JZ SEND 1949; CHECK FOR OPERATOR 1950 CPI '+' ;CHECK FOR PLUS 1951 JZ ASC1 1952 CPI '-' ;CHECK FOR MINUS 1953 JNZ ASC2 1954 STA SIGN 1955ASC1: LDA OPRI ;FETCH OPERAND INDICATOR 1956 CPI 2 ;CHECK FOR 2 OPERATORS 1957 JZ ERRS ;SYNTAX ERROR 1958 MVI A,2 1959 STA OPRI ;SET INDICATOR 1960 JMP NXT2 1961; CHECK FOR OPERANDS 1962ASC2: MOV C,A ;SAVE CHARACTER 1963 LDA OPRI ;GET INDICATOR 1964 ORA A ;CHECK FOR 2 OPERANDS 1965 JZ ERRS ;SYNTAX ERROR 1966 MOV A,C 1967 CPI '$' ;LC EXPRESSION 1968 JNZ ASC3 1969 INX H ;INCREMENT POINTER 1970 SHLD PNTR ;SAVE POINTER 1971 LHLD ASPC ;FETCH LOCATION COUNTER 1972 JMP AVAL 1973;CHECK FOR ASCII CHARACTERS 1974ASC3: CPI 27H ;CHECK FOR SINGLE QUOTE 1975 JNZ ASC5 ;JUMP IF NOT QUOTE 1976 LXI D,0 ;GET A ZERO 1977 MVI C,3 ;CHARACTER COUNT 1978ASC4: INX H ;BUMP POINTER 1979 SHLD PNTR ;SAVE 1980 MOV A,M ;FETCH NEXT CHARACTER 1981 CPI ASCR ;IS IT A CARRIAGE RETURN? 1982 JZ ERAR ;ARGUMENT ERROR 1983 CPI 27H ;IS IT A QUOTE? 1984 JNZ SSTR 1985 INX H ;INCREMENT POINTER 1986 SHLD PNTR ;SAVE 1987 MOV A,M ;FETCH NEXT CHAR 1988 CPI 27H ;CHECK FOR 2 QUOTES IN A ROW 1989 JNZ AVAL+1 ;TERMINAL QUOTE 1990SSTR: DCR C ;CHECK COUNT 1991 JZ ERAR ;TOO MANY CHARACTERS 1992 MOV D,E 1993 MOV E,A ;SET CHARACTER IN BUFFER 1994 JMP ASC4 1995ASC5: CPI '0' ;CHECK FOR NUMERIC 1996 JC ERAR ;ILLEGAL CHARACTER 1997 CPI '9'+1 1998 JNC ALAB 1999 CALL NUMS ;GET NUMERIC VALUE 2000 JC ERAR ;ARGUMENT ERROR 2001AVAL: XCHG 2002 LHLD OPRD ;FETCH OPERAND 2003 XRA A ;GET A ZERO 2004 STA OPRI ;STOR IN OPERAND INDICATOR 2005 LDA SIGN ;GET SIGN INDICATOR 2006 ORA A ;SET FLAGS 2007 JNZ ASUB 2008 DAD D ;FORM RESULT 2009ASC7: SHLD OPRD ;SAVE RESULT 2010 JMP NXT1 2011ASUB: MOV A,L 2012 SUB E 2013 MOV L,A 2014 MOV A,H 2015 SBB D 2016 MOV H,A 2017 JMP ASC7 2018ALAB: CALL SLAB 2019 JZ AVAL 2020 JC ERAR ;ILLEGAL SYMBOL 2021 JMP ERRU ;UNDEFINED SYMBOL 2022; 2023; GET HERE WHEN TERMINATING CHARACTER IS FOUND. 2024; CHECK FOR LEADING FIELD SEPARATOR 2025; 2026SEND: LDA OPRI ;FETCH OPERAND INDICATOR 2027 ORA A ;SET FLAGS 2028 JNZ ERRS ;SYNTAX ERROR 2029 LHLD OPRD 2030SEN1: MOV A,H ;GET HIGH ORDER BYTE 2031 LXI D,TEMP ;GET ADDRESS 2032 ORA A ;SET FLAGS 2033 RET 2034; 2035; GET A NUMERIC VALUE WHICH IS EITHER HEXADECIMAL OR 2036; DECIMAL. ON RETURN, CARRY SET INDICATES AN ERROR. 2037; 2038NUMS: CALL ALPS ;GET NUMERIC 2039 DCX D 2040 LDAX D ;GET LAST CHARACTER 2041 LXI B,ABUF ;SET BUFFER ADDRESS 2042 CPI 'H' ;IS IT HEXADECIMAL? 2043 JZ NUM2 2044 CPI 'D' ;IS IT DECIMAL 2045 JNZ NUM1 2046 XRA A ;GET A ZERO 2047 STAX D ;CLEAR D FROM BUFFER 2048NUM1: CALL ADEC ;CONVERT DECIMAL VALUE 2049 RET 2050NUM2: XRA A ;GET A ZERO 2051 STAX D ;CLEAR H FROM BUFFER 2052 CALL AHEX 2053 RET 2054; 2055; PROCESS REGISTER ERROR 2056; 2057ERRR: MVI A,'R' ;GET INDICATOR 2058 LXI H,0 ;GET A ZERO 2059 STA OBUF ;SET IN OUTPUT BUFFER 2060 RET 2061; 2062; PROCESS SYNTAX ERROR 2063; 2064ERRS: MVI A,'S' ;GET INDICATOR 2065 STA OBUF ;STORE IN OUTPUT BUFFER 2066 LXI H,0 2067 JMP SEN1 2068; 2069; PROCESS UNDEFINED SYMBOL ERROR 2070; 2071ERRU: MVI A,'U' ;GET INDICATOR 2072 JMP ERRS+2 2073; 2074; PROCESS VALUE ERROR 2075; 2076ERRV: MVI A,'V' ;GET INDICATOR 2077 JMP ERRR+2 2078; 2079; PROCESS MISSING LABEL ERROR 2080; 2081ERRM: MVI A,'M' ;GET INDICATOR 2082 STA OBUF ;STORE IN OUTPUT BUFFER 2083 CALL AOU1 ;DISPLAY ERROR 2084 RET 2085; 2086;PROCESS ARGUMENT ERROR 2087; 2088ERAR: MVI A,'A' ;GET INDICATOR 2089 JMP ERRS+2 2090; 2091; PROCESS OPCODE ERROR 2092; STORE 3 BYTES OF ZERO IN OBJECT CODE TO PROVIDE 2093; FOR A PATCH 2094; 2095ERRO: MVI A,'O' ;GET INDICATOR 2096 STA OBUF ;STORE IN OUTPUT BUFFER 2097 LDA PASI ;FETCH PASS INDICATOR 2098 ORA A ;WHICH PASS 2099 RZ ;RETURN IF PASS 1 2100 MVI C,3 ;NEED 3 BYTES 2101ERO1: XRA A ;GET A ZERO 2102 CALL ASTO ;PUT IN LISTING AND MEMORY 2103 DCR C 2104 JNZ ERO1 2105 RET 2106; 2107; PROCESS LABEL ERROR 2108; 2109ERRL: MVI A,'L' ;GET INDICATOR 2110 JMP ERRO+2 2111; 2112; PROCESS DUPLICATE LABEL ERROR 2113; 2114ERRD: MVI A,'D' ;GET INDICATOR 2115 STA OBUF 2116 CALL AOUT 2117 JMP OPC 2118; 2119; THIS ROUTINE SETS OR CLEARS BREAKPOINTS 2120; 2121BREAK: LDA ABUF ;CHECK FOR AN ARG 2122 ORA A 2123 JZ CLRB ;IF NO ARGUMENT, GO CLEAR BREAKPOINT 2124 MVI D, NBR ;ELSE GET NUMBER OF BREAKPOINTS 2125 LXI H,BRT ;AND ADDR OF TABLE 2126B1: MOV A,M ;GET HI BYTE OF ENTRY 2127 INX H 2128 MOV B,M ;GET LOW BYTE OF ENTRY 2129 ORA B ;CHECK FOR EMPTY ENTRY 2130 JZ B2 ;BRANCH IF EMPTY 2131 INX H ;ELSE GO ON TO NEXT ENTRY 2132 INX H 2133 DCR D ;BUMP COUNT 2134 JNZ B1 ;AND TRY AGAIN 2135 JMP WHAT ;OOPS NO ROOM 2136B2: DCX H 2137 XCHG 2138 LHLD BBUF ;GET ADDRESS 2139 XCHG ;IN D,E 2140 MOV A,D ;CHECK FOR ADDR > 11D 2141 ORA A 2142 JNZ B3 2143 MOV A,E 2144 CPI 11 2145 JC WHAT ;OOPS, TOO LOW 2146B3: MOV M,D ;SAVE ADDRESS 2147 INX H 2148 MOV M,E 2149 INX H 2150 LDAX D ;PICK UP INSTRUCTION 2151 MOV M,A ;SAVE IT 2152 MVI A,0CFH ;RST 1 INSTRUCTION 2153 STAX D 2154 MVI A,0C3H ;SET UP LO MEMORY 2155 STA 8 ;WITH A JUMP TO BREAKPOINT 2156 LXI H,BRKP 2157 SHLD 9 2158 RET ;THEN RETURN 2159; 2160; THIS ROUTINE CLEARS ALL BREAKPOINTS 2161; 2162CLRB: LXI H,BRT ;GET TABLE ADDRESS 2163 MVI B,NBR ;GET NUMBER OF BREAKPOINTS 2164CLBL: XRA A ;GET A ZERO 2165 MOV D,M ;GET HI-BYTE OF ENTRY 2166 MOV M,A 2167 INX H 2168 MOV E,M ;GET LO-BYTE OF ENTRY 2169 MOV M,A 2170 INX H 2171 MOV B,M ;GET INST BYTE 2172 INX H 2173 MOV A,D ;WAS THIS A NULL ENTRY 2174 ORA E 2175 JZ CL2 ;BRANCH IF IT WAS 2176 MOV A,B 2177 STAX D ;ELSE PLUG INST BACK IN 2178CL2: DCR B ;BUMP COUNT 2179 JNZ CLBL ;GO DO NEXT ONE 2180 RET 2181; 2182; COME HERE WHEN WE HIT A BREAKPOINT 2183; 2184BRKP: SHLD HOLD+8 ;SAVE H,L 2185 POP H ;GET PC 2186 DCX H ;ADJUST IT 2187 SHLD HOLD+10 ;SAVE IT 2188 PUSH PSW ;SAVE FLAGS 2189 POP H ;GET THEM INTO H,L 2190 SHLD HOLD ;NOW STORE THEM FOR USER 2191 LXI H,0 2192 DAD SP ;GET STACK POINTER 2193 LXI SP,HOLD+8 ;SET STACK POINTER AGAIN 2194 PUSH H ;SAVE OLD SP 2195 PUSH D ;SAVE D,E 2196 PUSH B ;SAVE B,C 2197 CMA ;COMPLEMENT ACCUMULATOR 2198 OUT 0FFH ;DISPLAY IT IN LIGHTS 2199 LXI SP,AREA+18 ;SET SP AGAIN 2200 LHLD HOLD+10 ;GET PC 2201 XCHG ;INTO D,E 2202 LXI H,BRT ;GET ADDR OF TABLE 2203 MVI B,NBR ;AND NUMBER OF ENTRIES 2204BL1: MOV A,M ;GET AN ENTRY FROM THE TABLE 2205 INX H 2206 CMP D ;DOES IT MATCH? 2207 JNZ BL2 ;BRANCH IF NOT 2208 MOV A,M ;ELSE GET NEXT BYTE 2209 CMP E ;CHECK IT 2210 JZ BL3 ;IT MATCHES! 2211BL2: INX H ;BUMP AROUND THIS ENTRY 2212 INX H 2213 DCR B ;BUMP COUNT 2214 JZ WHAT ;NOT IN OUR TABLE 2215 JMP BL1 2216; 2217BL3: INX H 2218 MOV A,M ;GET INSTR BYTE 2219 STAX D ;PUT IT BACK 2220 XRA A ;CLEAR ENTRY IN TABLE 2221 DCX H 2222 MOV M,A 2223 DCX H 2224 MOV M,A 2225 CALL CRLF ;RESTORE THE CARRIAGE 2226 LDA HOLD+11 ;GET HI-BYTE OF PC 2227 CALL HOUT ;TYPE IT 2228 LDA HOLD+10 ;GET LO-BYTE OF PC 2229 CALL HOUT ;TYPE IT 2230 LXI H,BMES ;TELL USER WHAT IT IS 2231 CALL SCRN 2232 JMP EOR ;GO BACK TO COMMAND LEVEL 2233; 2234BMES: DB ' BREAK',13 2235; 2236; THIS ROUTINE PROCEEDS FROM A BREAKPOINT 2237; 2238PROC: LDA ABUF ;CHECK FOR ARG 2239 ORA A 2240 JZ P1 ;JUMP IF NO ARG 2241 LHLD BBUF ;ELSE GET ARG 2242 SHLD HOLD+10 ;PLUG IT INTO PC SLOT 2243P1: LXI SP,HOLD ;SET SP TO POINT AT REG?S 2244 POP PSW ;RESTORE PSW 2245 POP B ;RESTORE B,C 2246 POP D ;RESTORE D,E 2247 POP H ;GET OLD SP 2248 SPHL ;RESTORE IT 2249 LHLD HOLD+10 ;GET PC 2250 PUSH H ;PUT IT ON STACK 2251 LHLD HOLD+8 ;RESTORE H,L 2252 RET ;AND PROCEED 2253; 2254; SYSTEM RAM 2255; 2256 ORG 1000H 2257; 2258; DEFINE BREAKPOINT REGION 2259; 2260NBR EQU 8 ;NUMBER OF BREAKPOINTS 2261HOLD: DS 12 ;REGISTER HOLD AREA 2262BRT: DS 3*NBR ;BREAKPOINT TABLE 2263; 2264; FILE AREA PARAMETERS 2265; 2266MAXFIL EQU 6 2267NMLEN EQU 5 2268FELEN EQU NMLEN+8 2269FILE0: DS NMLEN 2270BOFP: DS 2 2271EOFP: DS 2 2272MAXL: DS 4 2273FILTB: DS (MAXFIL-1)*FELEN 2274INSP: DS 2 2275DELP EQU INSP 2276ASCR EQU 13 2277HCON: DS 2 2278ADDS EQU HCON 2279FBUF: DS NMLEN 2280FREAD: DS 2 2281FEF: DS 1 2282FOCNT EQU FEF 2283ABUF: DS 12 2284BBUF: DS 4 2285SCNT: DS 1 2286DCNT: DS 1 2287NCOM EQU 11 2288TABA: DS 2 2289ASPC: DS 2 2290PASI: DS 1 2291NCHR: DS 1 2292PNTR: DS 2 2293NOLA: DS 1 2294SIGN: DS 1 2295OPRD: DS 2 2296OPRI: DS 1 2297TEMP: DS 1 2298APNT EQU INSP 2299AERR EQU SCNT 2300OIND: DS 2 2301LLAB EQU 5 2302AREA: DS 18 2303OBUF: DS 16 2304 DS 5 2305IBUF: DS 83 2306SWCH EQU 0FFH 2307SYMT EQU $ 2308 END 2309