>>>>>>>>>>>>>>>>>>>>> CP/M-Net News <<<<<<<<<<<<<<<<<<<<<<<< ============================================================ Number 2 February,1981 Volume 1, Issue 2 ============================================================ Printed monthly (at worst quarterly) to inform user's of RCPM Systems to the latest software news, information, and updates of public domain software accessible via telephone/modem transfer. Yearly subscription for copies of the CP/M-Net News may be obtained by mailing $18.00 (check or money orders only) to Kelly Smith, CP/M-Net, 3055 Waco Street, Simi Valley, California 93063. CP/M-Net is a non- profit orginization and all money received on subscriptions are utilized for the sustaining and enhancments of the CP/M- Net System. If you would like to contribute an article, include a column containing your area of interest and expertise, or participate in an open forum for conversation and transfer of ideas, feel free to send it to the CP/M-Net System and indicate that you would like it to be included in the CP/M- Net News...if possible, use WordStar (trademark, MicroPro International) or Electric Pencil (trademark, Micheal Shrayer) in 60 column format. NOTE: CP/M is a registered trademark of Digital Research ============================================================ On the Stack ============ Many thanks to the following supporting subscribers to the CP/M-Net News: Brent Crable, Crable Enterprises Eddie Currie John T. Powers, Jr. Pete Mack, Mack Associates Note: Back issues for the CP/M-Net News Letter are available for two dollars each. Back issues currently available are: January 1981, Number 1, Volume 1, Issue 1 MODEM/XMODEM Protocol Explained Software Tricks for the 8080/Z80 CP/M Tip-of-the-Month, 'Changing logged disks in DDT or SID' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Software "Bug" Report Microsoft MBASIC.COM version 5.03 [CP/M Compatible] Reported By: Kelly Smith, January 11, 1981 Application: Any When utilizing the SAVE function under MBASIC.COM version 5.03, DO NOT use lower case for the filename...it will be placed in the CP/M directory in lower case, and any subsequent attempt to "read-it-in" again with MBASIC will result in a "File not found" error! The only way to get rid of it (kill it in the directory) is to ERA *.BAS, and this will (of course) clobber all other ".BAS" files. Sam Singer's DUMP.COM (CPMUG Volume 14.7) program can also be used to "erradicate" the file... ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ What to do about CP/M's "SYNCRONIZATION ERROR" (SYSGENing CP/M Version 2.2, from Version 1.4) by Kelly Smith, CP/M-Net "SYSOP" Question: "How in the #*@%! do I SYSGEN CP/M Version 2.2 on my CP/M 1.4 system, when using it's MOVCPM (to generate a new system image), and the &%#"*@ thing keeps coming back with SYNCRONIZATION ERROR, and then promptly HALTS!" The Problem: Those clever people at Digital Research have embedded the serial number (issued to YOU I hope!) in MOVCPM.COM, to discourage the "rip-off" of CP/M by someone other than the rightful owner...when MOVCPM is executed, it looks for a match of it's serial number to that of the host system (your CP/M Version 1.4) as it appears in your system memory, detects that a "mismatch" has occurred, and promptly locks- up your computer...ARGH! "You mean I have to write that crummy "GETSY" and "PUTSYS" stuff to SYSGEN from 1.4 to 2.2 ???" we ask ourselves... The Solution: Fake-out #1...your CP/M Version 2.2 as supplied by Digital Research, is SYSGEN'd for a 20 Kilo-byte Intel MDS 800 system...so write a 20 Kilobyte BIOS (and BOOT loader), then do as follows to get a 20 Kilo-byte CP/M 2.2 system image... A>B: <--- Switch from A (CP/M 1.4) to B (CP/M 2.2) B>SYSGEN <--- Use CP/M 2.2's SYSGEN to get a system image SYSGEN VER 2.0 SOURCE DRIVE NAME (OR RETURN TO SKIP)B <--- Get it... FUNCTION COMPLETE DESTINATION DRIVE NAME (OR RETURN TO REBOOT) <--- Return A>SAVE 34 B:CPM20.COM <--- Save the CP/M 2.2 system image O.K., now SYSGEN normally on the B drive, with your 20 Kilo-byte BIOS (and BOOT loader)... Fake-out #2...Ah hah, so this is NOT your copy (I know, your doing this for a friend...) of CP/M Version 2.2, and it's been SYSGEN'd for something OTHER THAN a 20 Kilo-byte system...double ARGH! All is not lost however, just follow the (less than simple) sequence that follows using the MOVPATCH.ASM file that is listed after the SYSGEN sequence... A word of CAUTION however! Some implementations of MOVCPM.COM NOT DIRECTLY SUPPLIED by Digital Research have been "fiddled"...the address referenced in MOVPATCH.ASM that follows WILL NOT be the same...Lifeboat Associates has modified MOST versions of MOVCPM.COM that I have seen, for particular applications (i.e., double density, etc.). A>DDT B:MOVCPM.COM <--- Get the CP/M 2.2 MOVCPM in... DDT VERS 1.4 NEXT PC 2800 0100 -IMOVPATCH.HEX <--- Set-up the MOVCPM patch -R <--- Read it in NEXT PC 2800 0000 -XP <--- We need to reset the program counter P=0000 100 <--- Set it back to address 0100 Hexadecimal -G <--- Go execute MOVCPM... CONSTRUCTING 56k CP/M VERS 2.2 <--- Making my system size... READY FOR "SYSGEN" OR "SAVE 34 CPM56.COM" A>B: <--- It was faked-out, switch to drive B B>SAVE 34 CPM56.COM <--- Save the CP/M 2.2 system image B>DDT CPM56.COM <--- Bring in the new system image DDT VERS 2.2 <--- The "new" DDT announcing itself... NEXT PC 2300 0100 -ISBOOT56.HEX <--- My BOOT loader -R900 <--- Offset required for BOOT loader position NEXT PC 2300 0000 -ICBIOS56.HEX <--- My 56 Kilo-byte BIOS -R4580 <--- Offset for 56 Kilo-byte BIOS position NEXT PC 2300 0000 -G0 <--- "Warm boot" your CP/M 1.4 system... B>SYSGEN <--- Use CP/M 2.2 SYSGEN to generate the system SYSGEN VER 2.0 <--- The "new" SYSGEN announcing itself... SOURCE DRIVE NAME (OR RETURN TO SKIP) <--- Return DESTINATION DRIVE NAME (OR RETURN TO REBOOT)B <--- Put on B DESTINATION ON B, THEN TYPE RETURN <--- Return FUNCTION COMPLETE DESTINATION DRIVE NAME (OR RETURN TO REBOOT) <--- Return A> <--- Return to your "old" CP/M version 1.4... O.K., now remove the CP/M 1.4 disk from the A drive, and remove the CP/M 2.2 from the B drive, insert it in the A drive and do a "cold boot"...hereafter, MOVCPM will operate normally, so no need to go thru the MOVPATCH routine... MOVPATCH.ASM for MOVCPM.COM CP/M Version 2.2 Note: you MUST SET "msize" for your intended system memory size to make this work...assemble normally with the CP/M Version 1.4 "ASM.COM" file. MOVPATCH.ASM may not work with copies of MOVCPM.COM that are NOT SUPPLIED by Digital Research. msize equ 56 ;put your memory size HERE... org 05ch ;absolute file control block address db 20h,'0'+msize/10,'0'+msize mod 10,20h org 232h ;serial number string length check xra a ;set flags org 2c4h ;serial number match check lxi h,1200h ;force MOVCPM to look at it's ;own serial number... end ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Loading DDT Without 'Clobbering' the CCP by Kelly Smith, CP/M-Net "SYSOP" January 25, 1981 From time to time, I need to do some 'special tricks' within CP/M itself to modify it's operation to do something other than what Digital Research had intended. If you attempt to load DDT 'normally', it 'clobbers' the Console Command Processor by overlaying it with DDT...making modification (using DDT) impossible. This program will load Digital Research's Dynamic Debugging Tool (DDT) without overlaying the CP/M Console Command Processor, and works for CP/M version 1.4 AND 2.0 through 2.2...Be sure and set the equate MSIZE for your particular CP/M system size, for proper operation...name it to something like 'DDTLOAD.ASM', assemble and load...then execute it as follows: A>DDTLOAD DDT will now load into memory 'nomally', but will be relocated BELOW the CCP. Here's the software to do it... true equ -1 ;define true false equ not true;define false cpm14 equ false ;true if CP/M vers 1.4 cpm22 equ true ;true if CP/M vers 2.2 ; msize equ 56 ;must be set for YOUR CP/M system size ; base equ 0 ;CP/M system base address ; if cpm14 cbase equ base+2900h ;base of 16k CP/M 1.4 CCP bias equ (msize-16)*1024 ;offset for system nbase equ cbase+bias-10h ;new base address endif ; if cpm22 cbase equ base+3400h ;base of 20k CP/M 2.X CCP bias equ (msize-20)*1024 ;offset for system nbase equ cbase+bias-10h ;new base address endif ; org base+100h ; lhld base+6 ;move old BDOS address to new BDOS entry shld nbase+1 ;swap new base address into original base shld base+6 mvi m,jmp ;make 'jump' opcode to new base address lxi h,'3D'-'0' ;create DDT command in ;console input buffer shld cbase+bias+7 lxi h,'DT' shld cbase+bias+9 xra a ;make 'EOL' as null for message end sta cbase+bias+11 mvi a,8 ;reset command pointer sta cbase+bias+136 lda base+4 ;select current drive mov c,a jmp cbase+bias ;all parameters set, load DDT end ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Using CP/M's Undocumented "Autoload" Feature by Kelly Smith, CP/M-Net "SYSOP" Ever wished you could just slam a diskette into your drive, boot it, and have it immediately start executing a program for you...or the kids want to play some nifty game, but your tired of having your diskettes trashed 'cause your 14 year old boy does not understand the full implications of ERA *.*...?!? Well here's a little known feature of CP/M that's worth knowing...it has a BUILT IN AUTOLOAD! I don't know why Digital Research fails to document this, for public consumption (?), they include the information in their OEM distribution documentation, but not anywhere else...and how many of us are OEM distributers? Well, here are the details of "autoload", and how to implement it on your CP/M system. First, take a "scratch" diskette and do a full disk copy of your CP/M system diskette (this includes the system tracks). If you don't have a disk copy program, SYSGEN the "scratch" diskette and PIP all the stuff to it. Now, stick the new diskette (to be set-up for "autoload") in drive A:, "warm boot" it (Control-C) and let's assume that we want to "autoload" Microsoft's MBASIC and have it execute STARTREK...Here's what you do: A>ddt movcpm.com <--- We need to "patch" MOVCPM.COM DDT VERS 2.2 NEXT PC 2800 0100 <--- Write down '2800' someplace -d0a00 <--- Dump starting at address 0A00 Hex Here is the start of CP/M (this is CP/M Version 2.2, but this "method" will work for CP/M Version 1.4 just as well): .___ CCP jump entry (normal entry) : : .___ CCP jump entry to bypass "autoload" : : : : .___ 128 characters allowed for command : : : : : : .___ Number of characters in filename : : : : : : : : .___ Start of filename to "autoload" : : : : : : : : : : 0A00 C3 5C 03 C3 58 03 7F 00 20 20 20 20 20 20 20 20 .\..X... 0A10 20 20 20 20 20 20 20 20 43 4F 50 59 52 49 47 48 COPYRIGH 0A20 54 20 28 43 29 20 31 39 37 39 2C 20 44 49 47 49 T (C) 1979, DIGI 0A30 54 41 4C 20 52 45 53 45 41 52 43 48 20 20 00 00 TAL RESEARCH .. 0A40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0A50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0A60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0A70 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ . . . O.k., now that we see that much, let's patch MOVCPM.COM to do the "autoload" of MBASIC.COM and STARTREK.BAS... -s0a07 <--- Substitute, starting at address 0A07 Hex 0A07 00 0f <--- 15 characters in filenames to "autoload" 0A08 20 4d <--- ASCII 'M' 0A09 20 42 <--- ASCII 'B' 0A0A 20 41 <--- ASCII 'A' 0A0B 20 53 <--- ASCII 'S' 0A0C 20 49 <--- ASCII 'I' 0A0D 20 43 <--- ASCII 'C' 0A0E 20 <--- We needed a 'SPACE', so leave as is... 0A0F 20 53 <--- ASCII 'S' 0A10 20 54 <--- ASCII 'T' 0A11 20 41 <--- ASCII 'A' 0A12 20 52 <--- ASCII 'R' 0A13 20 53 <--- ASCII 'T' 0A14 20 54 <--- ASCII 'R' 0A15 20 45 <--- ASCII 'E' 0A16 20 4B <--- ASCII 'K' 0A17 20 . <--- Quit substituting -d0a00 <--- Let's "Dump" what we just entered... .___ 15 characters in MBASIC STARTREK : : .___ Start of MBASIC STARTREK : : : : 0A00 C3 5C 03 C3 58 03 7F 0F 4D 42 41 53 49 43 20 53 .\..X...MBASIC.S 0A10 54 41 52 54 52 45 4A 20 43 4F 50 59 52 49 47 48 TARTREK.COPYRIGH 0A20 54 20 28 43 29 20 31 39 37 39 2C 20 44 49 47 49 T (C) 1979, DIGI 0A30 54 41 4C 20 52 45 53 45 41 52 43 48 20 20 00 00 TAL RESEARCH .. 0A40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0A50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0A60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0A70 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ . . . Keep in mind, that you are not limited to just filenames...you could just as well "autoload" and envoke submit files (including command strings), whatever, and can completely "overlay" Digital Research's copyright notice and use as many ASCII character entries as are required...don't substitute passed address 0A7F Hex however! Now exit DDT (Control-C or G0), and let's look at the number that you wrote down...it's there on that piece of paper, next to the beer can... Hmmm...says 2800...o.k., multiply the 2 by 16 (for those that are on beer number 7, that's 32...the number 7 is (as everyone knows) "Kelly's Konstant"). Now since the 8 ends in two zeros, subtract 1 from 8 (that leaves 7, for those of you that smoke the "funny stuff")...now add 32 and 7 together...errr...ahhhh...FAR OUT!...39! Now follow along closely: A>save 39 trekload.com We just saved 39 pages (256 bytes/page) of the patched MOVCPM.COM...and for reference, renamed it to TREKLOAD.COM...now SYSGEN your diskette (however you do that) with TREKLOAD instead of MOVCPM, and "cold boot" the diskette. It should "boot" with MBASIC being executed, then MBASIC takes over and loads in STARTREK, and then you are ready to "zap" some Klingons! ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ A Simple Subroutine to Check for "Stack Overflow" by Kelly Smith, CP/M-Net "SYSOP" Here is a simple subroutine to be CALLed in your applications program to check for a possible "stack overflow" condition. This subroutine might be especially helpful during the "debug stage" of your software where you may not be sure of your total stack requirements...you could make CALLs to "check$stack" from numerous places in your software as a monitor of stack allocation, and by using conditional assemblies, REMOVE all the CALLs when your debug is completed. Other applications, include stack oriented languages such as STOIC, FORTH or PASCAL where some heavily "compute bound" applications programs could eventually "gobble up" memory and clobber the operating system. I wrote a simple test program with which you can use to verify the operation of "check$stack"...the exit on "blow up", resets the stack pointer to the "old stack" pointer, then displays 'Stack Over-Flow, Depth = nn' (where nn equals the "stack depth" in hexadecimal for up to 256 stack "levels"). Remember that the stack works DOWN towards (typically) your applications program...leave sufficient code between the "stack$end" and "oldstk" so (at worst) you can exit on stack overflow "gracefully"...you clobber "oldstk", and all bets are off. ; ;This is the test for "check$stack"...with 'debug' false, ;the program will exit to CP/M with the stack overflow ;message. ; true equ -1 ;define true false equ not true;define false debug equ false ;define debug (if true, makes sufficient stack) org 100h lxi h,0 ;save "old" CP/M stack pointer dad sp shld oldstk lxi sp,stack;set "local" stack call test lhld oldstk sphl ret ; test: call test1 call check$stack test1: call test2 call check$stack test2: call test3 call check$stack ret test3: ret ; ;end of test on "check$stack", incorporate the following code ;for your particular application...with a little more thought, ;you could also display the address of the last CALL prior to ;the "stack overflow", and thereby let your program tell you ;WHERE it BLEW UP...I will leave that exercise for you. ; check$stack: ;check to see if stack pointer is below STACK$END ; push h ;save H$L Regs. lxi h,-stack$end ;won't work for STACK$END = 0000 dad sp pop h ;restore H$L Regs. rc ;return if still o.k. ; ;come here on stack over-flow ; lxi h,0 ;clear H&L Regs. dad sp ;stack pointer to H&L Regs. lxi d,stack ;get original stack top address mov a,e ;do 16 bit subtract, to calculate "stack depth" sub l mov e,a mov a,d sbb h mov d,a ;16 bit result in D&E Regs. lhld oldstk ;restore "old" CP/M stack pointer sphl push d ;save "stack depth" lxi d,stack$overflow$message mvi c,9 ;display string function call 5 ;let CP/M do the work... pop d ;recover "stack depth" ; display$stack$depth: ;display up to 256 deep stack digits ; mvi c,2 ;display 2 digits push b ! push d ;save 2 digit count and "stack depth" mov a,e ;get hexadecimal digit rar ! rar ! rar ! rar ;display high nibble first... ; hexascii: ;convert 1 digit hexadecimal to 1 digit ASCII ; ani 0fh ;mask for low nibble position adi 90h ;convert hex digit to ASCII digit daa aci 40h daa mov e,a ;pass to CP/M in E reg. mvi c,2 ;display character function call 5 ;let CP/M do the work... pop d ! pop b ;get "stack depth" and digit count dcr c ;debump digit count rz ;return to CP/M, if both digits displayed push b ! push d ;not yet, so display second digit mov a,e ;get hexadecimal digit jmp hexascii;display and exit to CP/M, next time thru... ; stack$overflow$message: ;indicate stack overflow ; db 0dh,0ah,'Stack Over-Flow, Depth = $' ; oldstk: ds 2 ;storage for "old" CP/M stack pointer ; ds 32 ;"dummy" program storage ; stack$end equ $ ;stack end if debug ;if debug, ds 32 ;16 level stack else ;else, ds 2 ;1 level stack endif stack equ $ ;stack starts here ; end ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ CP/M-Net "Tip-of-the-Month" Ever wished you could REPEAT a program over-and-over, without having to go through typing in the filename and waiting for it to load? This "program" uses no memory space, and "loads" very fast...it WILL NOT WORK however on programs that require secondary commands (e.g., where the program is instructed to operate on some file or parameter, after the invocation of the initial program name at the CP/M system prompt). Let's assume that you are logged on to drive A:, then: A>SAVE 0 @.COM <--- save the arbitrary filename "@.COM" A>FORMAT <--- we want to FORMAT a stack of diskettes A>@ <--- we want to do it again... A>@ <--- ...and again... A>@ <--- ......and again! What happens, is that the Console Command Processor (CCP) picks-up the filename "@"...passes it to the Basic Disk Operating SYSTEM (BDOS), the BDOS "matches" it as being a valid file in the directory of your diskette, loads it (nothing to load, because it has "0" file size), then jumps to address 100 Hex (where the previous file is still in memory), and executes the "old" file...Simple! ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++