úˆRELOC ASMÉèDEMO ASMŽGENMOD BAS)¹™READDIR BASEd*ÿÿÿ; Reprinted from Micro/Systems Journal, Vol. 1, No. 1, March- ; April 1985, article titled "Assembly Language Extensions for ; MS-Basic" by Ron Kreymborg. ; ;**************************************************************; ; RELOC: A program to move a page relocatable assembly ; ; language module with an origin at zero to the top ; ; of available memory. ; ; ; ; Ron Kreymborg ; ; ; ; This code resides at the end of MBASIC ; ;**************************************************************; org 6000h exit: jmp 0 ; original address of Basic Šstart: lxi sp,stack ; Define code length and start address lxi h,buff ; source for move mov c,m ; get length of module inx h mov b,m mov a,b ; anything there? ora c jz exit ; ..no lxi d,0feh dad d ; start of code xchg ; put in DE push b ; save count push b ; Compute destination address in HL lhld 6 ; get bdos address shld buff+100h ; insert in module mvi l,0 ; ensure we go to a page boundry inr b ; convert length to pages mov a,h sub b mov h,a Š ; Now move the code to the address in HL pop b ; restore byte count push h ; save destination address movlp: ldax d ; get byte of code mov m,a ; move to new location inx h ; step pointers inx d dcx b ; and decrement counter mov a,c ora b ; done? jnz movlp ; ..no, loop pop h ; restore destination shld 6 ; setup new bdos vector xchg pop b ; restore count ; Now BC has the byte count, HL points to the first byte of the ; bit map, and DE has the destination address push h ; bit map address to top of stack mov h,d ; (h) is relocated page offset reclp: mov a,b ; check if done ora c Š jz exit ; ..yes, go start up Basic dcx b ; decrease count mov a,e ; is DE address modulo 8 bytes? ani 7 ; if so - must get next map byte jnz rec2 ; ..no ; Get next map byte via top of stack xthl ; get current map pointer mov a,m ; get byte into A inx h ; point to next byte xthl mov l,a ; store in L rec2: mov a,l ; check next bit in byte ral mov l,a ; save for later jnc rec3 ; no relocation required ; Add in the offset for a set bit ldax d ; get byte add h ; add offset stax d ; store relocated byte back rec3: inx d ; step to next byte in relocated jmp reclp ; code and around again Š; must occur on an 8 bit boundry org ($ AND 0fff0h) + 10h stack equ $ db 0 buff: dw 0 ; zero for no module case end ; Reprinted from Micro/Systems Journal, Vol. 1, No. 1, March- ; April 1985, article titled "Assembly Language Extensions for ; MS-Basic" by Ron Kreymborg. ; ;***************************************************************; ; Sample module. Preamble begins.. ; ;***************************************************************; bdos: jmp 0 ; bdos vector db (j-$)/2 ; routine count dw split ; split an integer dw get1st ; BDOS call 17 dw getnxt ; BDOS call 18 dw setdma ; BDOS call 26 j equ $ ;*************************************************************** Š; Split an integer into its seperate bytes. ; Basic call syntax is: ; CALL SPLIT% (SORCE%, LBYT%, RBYT%) split: mov a,m ; get right byte push psw ; and save it inx h ; get left byte mov a,m xchg ; and put in LBYT mov m,a inx h xra a mov m,a mov h,b ; right byte pointer into HL mov l,c pop psw ; restore right byte mov m,a ; and put in RBYT inx h xra a mov m,a ret ;*************************************************************** ; BDOS call 17 - search for first matching entry in the disc Š; directory. Must be preceded by a set dma call. Call with ; the syntax: ; CALL GET1ST% (FCB%(0), PTR%) ; Returns: ; PTR = 0 thru 3 ; PTR*32 -> directory entry in DMA. ; = FF ; no match found. get1st: push d ; save flag address xchg ; pointer into DE mvi c,17 call bdos pop h mov m,a ; return flag inx h xra a mov m,a ret ;*************************************************************** ; BDOS call 18 - search for next matching entry. Call and ; return as for . getnxt: push d ; save flag address xchg ; pointer into DE mvi c,18 call bdos Š pop h mov m,a ; return flag inx h xra a mov m,a ret ;*************************************************************** ; BDOS call 26 - set DMA address. Call with the syntax: ; CALL SETDMA% (DMABUFF%(0)) ; where DMABUFF is the first entry in a 128 byte array, ie set ; with a DIM DMABUFF%(64) statement. setdma: xchg ; pointer into DE mvi c,26 call bdos ret end 10 ' Reprinted from Micro/Systems Journal, Vol. 1, No. 1, March- 20 ' April 1985, article titled "Assembly Language Extensions for 30 ' MS-Basic" by Ron Kreymborg. 60 ' 1000 ' GENMOD 1010 ' 1020 ' A Microsoft Basic program which simulates the 1030 ' Digital Research program called GENMOD.COM. 1040 ' It takes a concatenated HEX file and produces 1050 ' a page relocatable version. 1060 ' 1070 ' Ron Kreymborg 1080 DEFINT A-Z 1090 INPUT "FILENAME (.HEX ASSUMED)? ",A$ 1100 B$=A$+".HEX" 1110 S=6000 Š1120 DIM M(S), B(S/8) 1130 H$="0123456789ABCDEF" 1140 NOPRNT=1 1150 ' 1160 OPEN "I",1,B$ 1170 PASS=1 1180 FLG=0 1190 G=0 1200 PRINT 1210 PRINT "FIRST PASS" 1220 IF EOF(1) THEN 1280 1230 LINE INPUT #1, L$ 1240 IF MID$(L$,2,2) = "00" THEN 1320 1250 GOSUB 2120 1260 GOTO 1220 1270 ' 1280 CLOSE 1290 PRINT "INCORRECT FILE END" 1300 STOP 1310 ' 1320 GOSUB 2370 1330 G=256 1340 PASS=2 1350 PRINT "SECOND PASS" 1360 IF EOF(1) THEN 1280 1370 LINE INPUT #1, L$ 1380 IF MID$(L$,2,2) = "00" THEN 1420 Š1390 GOSUB 2120 1400 GOTO 1360 1410 ' 1420 CLOSE 1430 Q=P+1 1440 FOR I=0 TO D 1450 P=P+1 1460 M(P)=B(I) 1470 NEXT I 1480 IF NOPRNT THEN 1690 1490 J=0 1500 PRINT 1510 PRINT "OUTPUT CODE:" 1520 PRINT 1530 T=512 : GOSUB 2480 : PRINT T$;" "; 1540 FOR I=0 TO P 1550 IF J<16 THEN 1620 1560 PRINT " "; 1570 FOR K=I-J TO I-1 1580 IF M(K)>=32 AND M(K)<=126 THEN PRINT CHR$(M(K)); ELSE PRINT "."; 1590 NEXT K 1600 PRINT 1610 J=0 : T=512+I : GOSUB 2480 : PRINT T$;" "; 1620 T=M(I) : GOSUB 2480 1630 PRINT MID$(T$,3);" "; 1640 J=J+1 1650 NEXT I Š1660 PRINT 1670 ' 1680 ' NOW WRITE THE PRL FILE 1690 B$=A$+".PRL" 1700 A$="0000000000000000" 1710 OPEN "R",1,B$,16 1720 FIELD 1, 1 AS B0$, 2 AS B1$, 13 AS B2$ 1730 LSET B0$=CHR$(0) 1740 FOR I=1 TO 14 1750 MID$(A$,I,1)=CHR$(0) 1760 NEXT I 1770 PH=Q\256 1780 PL=Q MOD 256 1790 B$=CHR$(PL)+CHR$(PH) 1800 LSET B1$=B$ 1810 LSET B2$=A$ 1820 PUT 1, 1 1830 LSET B1$=MKI$(0) 1840 FOR I=2 TO 16 1850 PUT 1, I 1860 NEXT I 1870 FIELD 1, 16 AS BUF$ 1880 N=P\16+1 1890 P=0 1900 FOR I=1 TO N 1910 FOR J=1 TO 16 1920 MID$(A$,J,1)=CHR$(M(P)) Š1930 P=P+1 1940 NEXT J 1950 LSET BUF$=A$ 1960 PUT 1, I+16 1970 NEXT I 1980 CLOSE 1990 PRINT 2000 T=Q : GOSUB 2480 : PRINT T$;" TOTAL CODE" 2010 T=P-1 : GOSUB 2480 : PRINT T$;" TOTAL BYTES" 2020 IF FLG THEN 2040 2030 PRINT "MODULE CONSTRUCTED" : GOTO 2050 2040 PRINT "ERRORS IN RE-LOCATION" 2050 PRINT 2060 SYSTEM 2070 END 2080 ' 2090 ' 2100 ' 2110 ' TRANSLATE THE CURRENT HEX LINE 2120 T$=MID$(L$,2,2) : GOSUB 2440 2130 N=T 2140 T$=MID$(L$,4,2) : GOSUB 2440 2150 P=T*256 2160 T$=MID$(L$,6,2) : GOSUB 2440 2170 P=P+T-G-1 2180 J=10 2190 FOR I=1 TO N Š2200 P=P+1 2210 T$=MID$(L$,J,2) : GOSUB 2440 2220 IF PASS = 1 THEN M(P)=T : GOTO 2320 2230 IF T = M(P) THEN 2320 2240 T=T-M(P) 2250 IF (T = 1 OR T = -255) THEN 2290 2260 PRINT HEX$(P);"RE-LOCATION ERROR";T 2270 FLG=1 2280 GOTO 2320 2290 P1=P\8 2300 P2=P MOD 8 2310 B(P1)=B(P1)+2^(7-P2) 2320 J=J+2 2330 NEXT I 2340 RETURN 2350 ' 2360 ' ZERO THE BIT MAP 2370 D=P\8+1 2380 FOR I=0 TO D 2390 B(I)=0 2400 NEXT I 2410 RETURN 2420 ' 2430 ' HEX TO DECIMAL 2440 T=(INSTR(H$,LEFT$(T$,1))-1)*16+INSTR(H$,RIGHT$(T$,1))-1 2450 RETURN 2460 ' Š2470 ' DECIMAL TO HEX 2480 T$="000"+HEX$(T) 2490 IF LEN(T$)>4 THEN T$=MID$(T$,2) : GOTO 2490 2500 RETURN 10 ' Reprinted from Micro/Systems Journal, Vol. 1, No. 1, March- 20 ' April 1985, article titled "Assembly Language Extensions for 30 ' MS-Basic" by Ron Kreymborg. 60 ' 100 ' Directory reading program in Basic. 110 ' 120 ' This program uses external assembly language routines 130 ' to assemble a string array containing matching entries 140 ' in the disc directory. Note that no new variables may 150 ' be defined between calling GET1ST and the last call to 160 ' GETNXT. 170 ' Ron Kreymborg 180 DEFINT A-Z 190 DIM FCB(20),DMA(64),DIR$(100),CR(2) 200 DEF FNA(A!) = PEEK(A!)+PEEK(A!+1)*256-2^16 210 A! = PEEK(7)*256+3 220 N = PEEK(A!) 230 IF N <> 4 THEN STOP 240 SPLIT% = FNA(A!+1) 250 GET1ST% = FNA(A!+3) 260 GETNXT% = FNA(A!+5) 270 SETDMA% = FNA(A!+7) 280 FLG=0 : CR(0)=0 : CR(1)=0 : E=0 : K=0 : U=0 : L=0 Š290 ' 300 PRINT "Enter required match string as 11 characters, with" 310 INPUT " a '?' to match any character: ",A$ 320 PRINT 330 IF LEN(A$) <> 11 THEN PRINT "Pardon?" : GOTO 300 340 PRINT "Matching entries:" 350 FCB$ = "."+A$ 360 FOR I=1 TO 100 370 DIR$(I) = " " 380 NEXT I 390 ' 400 ' Copy the specified filename into the FCB. 410 J = 0 420 FCB$ = FCB$+" " 430 FOR I=0 TO 5 440 J = J+1 : M = 1 : GOSUB 660 450 J = J+1 : M = 256 : GOSUB 660 460 NEXT I 470 CALL SETDMA% (DMA(0)) 480 CALL GET1ST% (FCB(0),FLG) 490 ' 500 E = E+1 510 IF FLG>3 THEN 560 520 GOSUB 720 530 CALL GETNXT% (FCB(0), FLG) 540 GOTO 500 550 ' Š560 FOR K=1 TO E-1 570 IF (K-1) MOD 4 = 0 THEN PRINT 580 PRINT DIR$(K);" "; 590 NEXT K 600 PRINT 610 PRINT 620 END 630 ' 640 ' Load the ASCII sequence number into the correct 650 ' byte (specified by M) of the Ith FCB word. 660 B$ = MID$(FCB$,J,1) 670 IF B$ <> "." THEN FCB(I) = FCB(I)+ASC(B$)*M 680 RETURN 690 ' 700 ' Extract each byte from the DMA buffer and load 710 ' them into the DIR$ string. 720 K = FLG*16 730 U = U+1 740 L = 1 750 FOR I=K TO K+5 760 CALL SPLIT% (DMA(I), CR(1), CR(0)) 770 FOR J=0 TO 1 780 IF (I = K AND J = 0) THEN 810 790 MID$(DIR$(U),L,1) = CHR$(CR(J)) 800 L = L+1 810 NEXT J 820 NEXT I Š830 RETURN