SLIDING INTO BDOS (Part II) WITH FILES MADE EASY by: Michael J. Karas 2468 Hansen Court Simi Valley, CA 93065 (805) 527-7922 Sincå  É  kno÷  thaô  alì devoteä  Lifå  Lineó  readeró  havå anxiouslù  beeî waitinç foò thió "seconä iî á series¢ tutoriaì oî usinç  fileó  witè thå CP/Í BDOS¬  É wilì noô gï oî á  lonç  timå tellinç  yoõ  whù thió thinç abouô CP/Í BDOÓ  filå  interfacå  ió sï  important®  Noò wilì É trù tï justifù whù thå turoriaì shoulä bå valuable® Yoõ wouldn'ô bå readinç herå aô thió timå iæ yoõ haä anù inclinatioî tï finä mù worë disinteresting® Iæ yoõ arå ne÷ oî thå scenå anä havå somå questionó abouô whaô thió ió alì abouô  É woulä likå tï direcô youò attentioî tï thå Novembeò 198² issuå oæ Lifå  Lineó  wherå  thå firsô parô oæ thió  tutoriaì  serieó  waó presented®  Therå  thå  purpose  oæ  thå  BDOÓ  anä  thå  generaì interfacå conceptó werå presented® Thå articlå wenô oî tï includå á  descriptioî  oæ  thå physicaì devicå systeí  calló  anä  otheò miscellaneous system control type functions. THIS TIME IT'S FILES Thió  montè thå tutoriaì continueó witè á descriptioî oæ thå sequentiaì  filå I/Ï systeí supporteä withiî thå BDOS®  Thå  con ceptó  oæ  CP/Í  filå  storagå arå tï  bå  describeä  alonç  witè appropiatå  CP/Í directorù structurå definitioî aó iô relateó  tï thå accesó oæ thå fileó storeä upoî á CP/Í disk® Thå FILÅ CONTROÌ BLOCË  (FCB©  wilì  bå describeä iî termó  oæ  itó  functionó  aó relateä  thå  á  filå tï bå accesseä upoî á  disk®  É  havå  alsï includeä  á  comprehensivå  programminç  examplå  thaô  allowó  á sequentiaì filå tï bå accesseä characteò bù character. HOW FILES ARE STORED UPON THE DISK Thå  CP/Í operatinç systeí manageó thå availablå spacå oî  á disë  bù  dividinç thå totaì availablå spacå uð intï á numbeò  oæ relativelù  smalì  datá blocë storagå areaó  calleä  "GROUPS"®  Á grouð sizå ió usuallù describeä aó thå minimuí allocatablå  spacå thaô  á  filå caî occupy®  Whaô thió meanó ió thaô thå  operatinç system¬  iî  itó disë spacå managemenô scheme¬  lumpó setó oæ thå normaì  12¸  bytå logicaì recordó oæ á filå togetheò  intï  theså thingó calleä groups®  Thå numbeò oæ groupó thaô maù bå containeä oî  á disë dependó upoî thå totaì filå storagå spacå oæ thå  disë iî  logicaì  12¸ bytå recordó divideä bù thå numbeò oæ  12¸  bytå Šlogicaì recordó lumpeä togetheò intï á group® (Á notå tï thå lesó casuaì  readeò ió thaô thå numbeò oæ groupó oî á disë ió  limiteä bù  desigî tï 65Ë groups®  Secondlù á grouð ió alwayó aî integraì poweò  oæ twï numbeò oæ 12¸ bytå logicaì recordó witè  á  minimuí sizå oæ ¸ recordó (1Ë byte)® Grouð sizå ió necessarilù limiteä tï 16K bytes due to the extent system described below). Aó  á filå ió storeä upoî á CP/Í disë iô consumeó disë spacå iî  12¸ bytå logicaì records®  Eacè timå á grouð  becomeó  filleä witè  recordó thå operatinç systeí allocateó anotheò grouð tï thå file®  Hencå thå terí "minimuí allocatablå size"® If¬ aó thå filå growó iî size¬ thå lasô allocateä grouð assigneä tï á filå ió noô completelù filleä thå remaininç spacå iî thå grouð ió "burned¢ iî thaô iô ió noô usablå bù otheò files® Thå CP/Í systeí keepó tracë oæ  thå  grouð assignmentó madå tï thå variouó fileó oî  á  disk¬ thå fileó names¬ anä thå totaì numbeò oæ 12¸ bytå logicaì recordó iî eacè filå througè á storeä directory® Thå firsô portioî oæ thå disë  ió  reserveä  foò thå filå directory®  Á  fixeä  numbeò  oæ directorù  entries¬  determineä bù thå system's BIOÓ design¬  arå available¬  usuallù á numbeò likå 64¬ 128¬ oò 256¬ dependinç upoî thå sizå oæ thå disk® Eacè filå haó á uniquå directorù entrù "set¢ thaô  describeó thå filå locatioî upoî thå disk®  Á "set¢ oæ directorù entrieó ió specifieä  becauså eacè entrù ió designeä tï "poinô to¢ oò  storå thå grouð allocatioî numberó foò thaô file®  Eacè directorù entrù haó á numbeò slotó wherå grouð numberó caî bå stored®  Thå systeí desigî allowó eacè directorù entrù tï specifù thå storagå foò 16Ë byteó  oæ  storagå  space®  Foò  fileó largeò thaî  16Ë  byteó  á seperatå directorù entrù ió useä foò eacè 16ë byteó (oò remaindeò portioî thereof)®  Eacè sucè piecå oæ á filå ió referreä tï aó aî "EXTENT¢  oæ  thå  file®  Thå directorù entrù "set¢  foò  á  filå containó  á  bytå iî eacè extenô directorù entrù thaô storeó  thå extenô  numbeò oæ thå file®  Extenô numberó starô witè ° anä  maù increaså tï á theoreticaì limiô oæ 25µ oò thå sizå oæ thå disë iî 16K byte pieces, whichever is smaller. Thå  charô belo÷ describeó thå functionó oæ alì byteó  iî  á typicaì directorù entry® Eacè entrù ió 3² byteó lonç anä theù arå packeä  fouò  tï  á  logicaì sectoò witè thå  numbeò  oæ  logicaì sectoró   filleä  uð  witè  directorù  entrieó  limiteä  tï   thå predetermined number of directory entries divided by four. .pa Š Figure 1. DISK DIRECTORY ENTRY DEFINITION byte 00 byte 01 byte 02 byte 03 byte 04 byte 05 byte 06 byte 07 +-------+-------+-------+-------+-------+-------+-------+-------+ |Activå |                                                       ü | |Entrù ü Eighô Characteò ASCIÉ Filå Namå Byteó 0± tï 0¸ | |& User | | |Flag | | +-------+-------+-------+-------+-------+-------+-------+-------+ byte 08 byte 09 byte 10 byte 11 byte 12 byte 13 byte 14 byte 15 +-------+-------+-------+-------+-------+-------+-------+-------+ |Last  |                       |       |               |Record ü | |File ü Three characteò ASCIÉ |Extent | Two Bytes |Count | |Name | File Name extension |Number | Reserved |of this| |Char | | | |Extent | +-------+-------+-------+-------+-------+-------+-------+-------+ byte 16 byte 17 byte 18 byte 19 byte 20 byte 21 byte 22 byte 23 +-------+-------+-------+-------+-------+-------+-------+-------+ |                                                       ü | Group Number storage for groups attached to this file | | One byte used per group number if disk contains less | | 255 groups. Two bytes if greater than 256. | +-------+-------+-------+-------+-------+-------+-------+-------+ byte 24 byte 25 byte 26 byte 27 byte 28 byte 29 byte 30 byte 31 +-------+-------+-------+-------+-------+-------+-------+-------+ |  Additional Group Number storage. ü | Group Number storage for groups attached to this file | | One byte used per group number if disk contains less | | 255 groups. Two bytes if greater than 256. | +-------+-------+-------+-------+-------+-------+-------+-------+ Thå  byteó oæ thå disë directorù entrù arå eacè describeä iî thå  followinç paragraphs®  Thå firsô bytå storeä iî aî entrù  ió seô tï indicatå iæ thió sloô iî thå predetermineä directorù  areá ió  emptù  oò iæ iô describeó aî activå filå extent®  Á valuå  oæ 0E5È  indicateó aî emptù slot®  Thió valuå waó choseî  presumablù duå tï thaô á freshlù formatteä diskettå containó alì 0E5È  byteó iî  thå  emptù sectors¬  thuó makinç sucè disë appeaò tï havå  nï fileó containeä thereon®  Iæ thå bytå valuå ió noî 0E5H¬ theî thå sloô  containó  á valiä filå extenô  descriptor®  Thå  CP/Í  useò numbeò  areá  tï whicè aî activå filå ió associateä ió storeä  iî thå firsô directorù entrù byte®  Useò numbeò valueó rangå froí  ° tï 15. Thå  nexô  eighô byteó contaiî thå primarù namå oæ thå  filå iî  ASCIÉ characters®  Iæ thå namå ió shorteò thaî  ¸  characteró theî  thå namå ió paddeä tï thå righô witè spaces®  Followinç thå namå  fielä  ió á threå bytå filå namå extensioî fielä  iî  ASCIÉ characters®  Thå extensioî field¬ iæ shorteò thaî ³ characteró ió paddeä tï thå righô witè spaces®  Foò CP/Í versioî 2.2¬ thå uppeò bitó  (biô  7©  oæ  thå extenô namå byteó arå  useä  tï  describå certaiî attributeó abouô thå file®  Iæ thå uppeò biô oæ thå firsô Šextenô  namå characteò ió set¬  theî thå filå ió describeä  aó  á read-onlù  file®   Thå  uppeò  biô  oæ  thå  seconä  extenô  namå character¬  iæ  set¬  indicateó thaô thå filå namå shoulä noô  bå displayed in directory listings. Eacè directorù entry¬  aó á filå descriptoò extent¬  haó thå nexô bytå seô tï á numbeò thaô specifieó whicè 16Ë bytå chunë  oæ thå  filå thaô thió entrù describes®  Twï byteó afteò thå extenô bytå  arå noô useä withiî thå directorù anä arå normallù  seô  tï zerï  bù  default®  Thå numbeò oæ recordó storeä iî  thå  extent¬ describeä  bù thió directorù entry¬  ió recordeä iî thå  bytå  1µ position®  Thå  maximuí valuå foò thå recorä counô ió 12¸  (080H© whicè  iæ equaì tï (12¸ ª 128© oò 16Ë bytes¬  thå maximuí sizå oæ an extent. Bytå  positionó 1¶ tï 3± contaiî thå grouð numberó upoî  thå disë  thaô  contaiî thå datá belonginç tï thå filå nameä  iî  thå directorù  entry®  Thå  numbeò  oæ  byteó  withiî  thå  totaì  1¶ availablå  thaô  arå useä foò grouð numbeò storagå  ió  dependanô upoî  thå amounô oæ filå datá describeä bù thió extenô anä bù thå grouð  sizå  oæ  thå disk®  Thå grouð  numberó  arå  singlå  bytå numbers¬ uð tï 1¶ total¬ iæ thå numbeò oæ groupó upoî thå disë ió lesó thaî oò equaì tï 255®  Iæ thå numbeò oæ groupó upoî thå disë ió  morå  thaî 25µ theî bytå positionó 1¶ tï 3± contaiî twï  bytå grouð  numbers¬  storeä iî lo÷ byte/higè bytå  order®  Thå  grouð numberó  containeä withiî á directorù entrù dï noô havå tï bå  iî increasing sequential order nor do they have to be consecutive. Thå  figurå belo÷ showó twï logicaì recordó oæ thå directorù froí á singlå sideä doublå densitù disë witè 2Ë bytå groups®  Thå totaì numbeò oæ groupó availablå ió 24³ sï thå grouð numberó  arå singlå bytå numbers® Notå thaô onlù onå halæ oæ thå 1¶ bytå spacå foò  grouð numberó ió useä duå tï thå facô thaô ¸ entrieó foò  2Ë bytå groupó ió alì thaô ió needeä tï describå thå storagå foò onå full 16K byte extent. Figure 2. EXAMPLE HEX/ASCII DIRECTORY RECORD DISPLAY 00 00414449 52202020 20434F4D 0000000B .ADIR COM.... 10 07000000 00000000 00000000 00000000 ................ 20 004D4552 47505249 4E4F5652 0000003C .MERGPRINOVR...< 30 16171819 00000000 00000000 00000000 ................ 40 00434F50 59202020 20434F4D 0000000E .COPY COM.... 50 0C000000 00000000 00000000 00000000 ................ 60 00435243 4B202020 20434F4D 0000000A .CRCK COM.... 70 0D000000 00000000 00000000 00000000 ................ 00 E5555345 52202020 204C4F47 00000030 eUSER LOG...0 10 04050600 00000000 00000000 00000000 ................ 20 00444454 20202020 20434F4D 00000026 .DDT COM...& 30 0F101100 00000000 00000000 00000000 ................ 40 0044552D 56373520 20434F4D 0000002E .DU-V75 COM.... 50 12131400 00000000 00000000 00000000 ................ 60 00464F52 4D415420 20434F4D 0000000C .FORMAT COM.... 70 15000000 00000000 00000000 00000000 ................ Š Thå  abovå  examlpeó alì sho÷ fileó thaô arå lesó  thaî  16Ë byteó  each®  Notå alsï thå displaù showinç thå eraseä "USER.LOG¢ file. HOW FILES ARE ACCESSED Thå   fileó  upoî  á  disë  arå  accesseä  througè  á   useò descriptioî  blocë  calleä á Filå Controì Blocë (FC foò  short)® Thå  filå controì block¬  useä bù virtuallù alì filå accesó  BDOÓ systeí calls¬  haó thå structurå aó showî iî Figurå 3® Thió charô ió takeî froí á Digitaì Researcè CP/Í manuaì anä ió includeä herå foò quicë educationaì reference. Notå thaô thå structurå oæ á filå controì blocë ió mucè  thå samå aó thaô oæ á directorù entrù witè á fe÷ minoò  changes®  Thå changeó  and/oò  differenceó arå aó follows,  otherwiså thå  bytå descriptions are the same as for the disk directory entry. Thå  firsô bytå oæ aî FC allowó thå programmeò  tï  specifù whicè  drivå shoulä bå useä foò thå filå access®  Drivå Aº  tï Pº arå  specifieä  aó  ± tï 1¶ respectivelù whilå á  valuå  oæ  zerï indicateó thaô thå currentlù loggeä defaulô drivå shoulä bå  useä for the access. Aî  FC  containó  fouò additionaì byteó thaô  arå  useä  aó pointeró  foò  filå accesó position®  Thå  "cr"¬  currenô  recorä number¬  indicateó  thå  sequentiaì recorä numbeò oæ thió  extenô thaô  wilì  bå  accesseä upoî thå nexô filå reaä  oò  filå  writå systeí  call®  Thå  useò normallù setó thå "cr¢ bytå tï  zerï  tï begiî filå accesó aô thå firsô logicaì recorä oæ thå  file®  Eacè timå  á  reaä oò writå ió performeä thå currenô recorä numbeò  ió incremented®  Wheî thå "cr¢ bytå attainó á valuå oæ 080È durinç á sequentiaì  filå operatioî thå BDOÓ automaticallù  realizeó  thaô thå  currenô  extenô  oæ  thå filå haó beeî  fullù  accesseä  anä performó  thå necessarù disë directorù accesseó tï setuð thå  FC tï allo÷ filå accesó tï thå nexô extent®  Foò readinç thió simplù meanó  thaô thå nexô extenô descriptoò directorù entrù  froí  thå disk¬  foò  thió  file¬  ió  reaä  intï  memorù  (ie®  thå  grouð allocatioî  numberó froí thå disë arå copieä intï thå d0-dî byteó oæ  thå FCB¬  thå extenô numbeò becomeó onå greater¬  thå  recorä counô  froí thå disë foò thå ne÷ extenô ió copieä intï  thå  "rc¢ bytå anä thå cò bytå ió zeroed)®  Durinç á writinç operatioî  thå "cr¢  bytå  attaininç á valuå oæ 080È indicateó thaô thå  currenô extenô  oæ thå filå ió fulì anä sï thå BDOÓ  automaticallù  findó thå  appropiatå directorù entrù spoô oî thå disë tï writå iî  thå newlù  assigneä grouð allocatioî bytes¬  recorä counô  valuå  anä extenô number®  Thå BDOÓ wilì theî creatå anotheò directorù entrù oî thå disë foò thå ne÷ extenô oæ thå file®  Iî thió caså thå d0- dî  byteó oæ thå FC arå zeroeä tï indicatå thaô storagå haó  noô yet been allocated for this extent. .pa Š Figure 3. FILE CONTROL BLOCK DESCRIPTION ------------------------------------------------------------ |dr|f1|f2|/ /|f8|t1|t2|t3|ex|s1|s2|rc|d0|/ /|dn|cr|r0|r1|r2| ------------------------------------------------------------ 00 01 02 ... 08 09 10 11 12 13 14 15 16 ... 31 32 33 34 35 where: dr drive code (0 - 16) 0 => use default drive for file access 1 => select drive A: for file access 2 => select drive B: for file access ... 16=> select drive P: for file access f1...f8 contain the files name in ASCII upper case with high bits equal to zero. t1,t2,t3 contain the file type in ASCII upper case witè higè bitó normallù equaì zero® tn§ denoteó the high bit of these bit positions. t1' = 1 => Read/Only file t2' = 1 => SYS file, no DIR list ex contains the current extent number, normally set to 00 by the user, but is in the range 0 - 31 during file I/O. s1 reserved for internal system use s2 reserved for internal system use, set to zero on call to OPEN, MAKE, SEARCH system calls. rc record count for extent "ex," takes on values 0 to 128. d0...dn filled-in by BDOS to indicate file group numbers for this extent. cr current record to read or write in a sequential file operation. Normally set to zero by the user upon initial access to a file. r0,r1,r² optionaì randoí recorä numbeò iî thå rangå oæ ° tï 65535¬ witè overflo÷ tï r2® r0/r± arå á 1¶ biô value in low/high byte order. .pa Š Thå  lasô threå byteó oæ thå FCB¬  r0,r1¬  ¦ r² arå useä foò randoí recorä filå I/Ï anä wilì bå covereä iî thå thirä anä finaì parô oæ thió turorial® Foò simpleò sequentiaì I/Ï thå FC iî facô doeó  noô eveî neeä tï bå setuð foò thå 3¶ byteó oæ  storage®  3³ bytes suffice for all sequential file I/O FCB operations. FILE ACCESS SETUP SYSTEM FUNCTIONS Thå  procedurå foò thå programmeò tï uså iî accessinç á filå generallù  startó iî onå oæ twï ways®  Thå firsô  senariï  startó with¬  "Letó  seå iæ ouò filå existó oî thå disk?¢ Therå arå  twï BDOÓ  systeí calló relateä tï thå functionó oæ searchinç thå disë directorù foò á filå namå matcè againsô thå FC specifieä bù  thå user®  Theså operationó allo÷ foò thå programmeò tï finä ouô iæ á specifiã filå namå alreadù existó upoî thå disk®  Iî additioî  iô provideó  á  mechanisí tï scaî á directorù tï determinå alì  filå nameó  thaô exisô iî thå directory®  Thå seconä  situatioî  comeó intï beinç iæ thå programmeò ió alreadù awarå oæ thå filå  statuó witè respecô tï "presence¢ oî thå disë oò aó thå logicaì sequencå oæ eventó followinç thå firsô senario® Theså latteò functionó arå useä tï worë witè specifiã fileó foò opening¬  closing¬ creating¬ renaming anä deleting. SEARCH FIRST AND SEARCH NEXT: Functions 17 and 18. Thå searcè functionó scaî thå directorù foò matcè oæ á  filå namå  thaô compareó witè thå useò specifieä FC pointeä tï bù thå (DE© registeò pair®  Thå matcè ió madå oî thå basió oæ  comparinç thå  f1-f8¬  t1-t3¬  anä eø byteó oæ thå FC tï thå correspondinç byteó  oæ  thå  disë directorù entries®  Anù  FC  positioî  thaô containó  aî  ASCIÉ questioî marë "?¢ (03FH© ió  specifieä  aó  á "matcè anù character¢ froí thå disë directory® Thå functioî calló returî  á  valuå oæ 0FFÈ iî thå (A© registeò iæ nï  morå  matcheä directorù  entrieó caî bå found®  Thå searcè functionó causå  thå currentlù  valiä disë buffeò addresó anä thå followinç 12¸  byteó tï  bå filleä witè á copù oæ thå directorù recorä containinç  thå matcheä entry¬ iæ onå ió found® Thå (A© registeò ió returneä witè á ° tï ³ valuå tï indicatå whicè onå oæ thå fouò possiblå 3² bytå chuncks of the directory record contain the matched entry. Searcè firsô meanó tï finä thå firsô occurrancå oæ á matcheä entrù  tï thå FCB®  Thå searcè nexô functioî scanó thå  directorù froí  thå currenô searcè positioî insteaä oæ froí thå  beginning® Notå  thaô  iô ió noô normallù valiä tï perforí thå  searcè  nexô functoî withouô firsô performinç thå searcè firsô function®  Alsï iô  ió  noô valiä tï perforí otheò directorù oò  filå  operationó between the search first and search next functions. Thå prograí examplå belo÷ showó á techniquå foò readinç  alì directorù  entrieó froí thå disë drivå specifieä bù thå firsô FC bytå  intï á memorù residenô list®  Thå lisô startó aô  thå  LISÔ labeì  witè  thå totaì matcheä filå counô storeä iî  thå  FILECNÔ variable®  Thå  LISTPOÓ labeì storeó thå nexô availablå lisô loaä Špoinô  durinç thå directorù scaî operation®  Thå searcè FC  useó thå  CP/Í  defaulô FC locatioî aô addresó 05CÈ anä  specifieó  á totaì wilä carä (*.*© match®  Thå "ex¢ bytå ió zeroeä beforå  thå searcè  firsô calì sï thaô onlù thå zerï extentó oæ thå fileó arå returned®  Thå  filå  nameó arå storeä iî thå lisô  iî  characteò stringó oæ 1¶ byteó eacè witè á preceedinç drivå designatoò  bytå anä paddeä tï thå righô witè ´ zerï bytes®  Pleaså notå thaô thió prograí  ió á segmenô onlù anä wilì noô directlù assemblå anä ruî aó á CP/Í .COÍ filå withouô á littlå addeä leaä iî anä erroò exiô coding. Listing 1. A DIRECTORY SCANNING PROGRAM BUFR EQU 80H+BASE ;DEFAULT CP/M BUFFER BDOS EQU 0005H ;ENTRY POINT FOR BDOS OPERATIONS ; SRCHF EQU 17 ;SEARCH DIR FOR FIRST OCCUR. SRCHN EQU 18 ;SEARCH DIR FOR NEXT OCCUR. STDMA EQU 26 ;SET DMA ADDRESS ; FC EQÕ 5CH+BASÅ ;DEFAULÔ FILÅ CONTROÌ BLOCK FCBEXT EQU FCB+12 ;EXTENT BYTE IN FCB FCBRNO EQU FCB+32 ;RECORD NUMBER IN FCB ; ; ;SETUP SIZE OF ELEMENTS IN THE FILE NAME LIST ; ITEMSZ EQU 16 ;EACH LIST ITEM IS 16 BYTES ; ; ;SETUP WILD CARD FILE IMAGE LIKE *.* ; LXI H,FCB+1 ;PLACE TO PUT WILD CARD IMAGE MVI B,11 ;SIZE TO SET ALFN: MVI M,'?' ;PUT IN A JOKER CHAR INX H ;BUMP FILL POINTER DCR B ;DCR BYTE COUNTER JNZ ALFN ; ; ;ZERO INITIAL TOTAL FILE COUNT ; LXI H,0000H SHLD FILECNT ; ; ;HERE IF NAME PROPERLY POSITIONED IN THE DEFAULT FCB AREA FOR LIST BUILD ; NAMEPRES: MVI C,STDMA ;INITIALIZE DMA ADDRESS TO DEFAULT BUFFER LXI D,BUFR CALL BDOS ; XRA A ;CLEAR APPROPIATE FIELDS OF SEARCH FCB Š STA FCBEXT ;EXTENT BYTE STA FCBRNO ;AND RECORD NUMBER ; LXI D,FCB ;USE DEFAULT FCB FOR SEARCH MVI C,SRCHF ;SEARCH FOR FIRST OCCURRANCE CALL BDOS CPI 0FFH ;SEE IF FOUND JNZ LOADLIST ;IF SOME FOUND THEN GO BUILD LIST ; ; ;PUT INSTRUCTIONS HERE TO HANDLE A SITUATION WHERE NO FILES ;MATCHING THE FCB WILD CARD IMAGE ARE FOUND. ; JMP ERROR$EXIT ;TO USER SUPPLIED ROUTINE ; ; ;BUILD UP LIST WITH ALL FOUND ENTRIES ; LOADLIST: LXI H,LIST ;INITIALIZE LIST POINTER PARAMETERS SHLD LISTPOS ;START = CURRENT POS OF LIST ; ; ;PUT CURRENTLY FOUND NAME TO LIST ;(A) = OFFSET IN DEFAULT BUFFER OF NAME ; ; NM2LST: ANI 3 ;ZERO BASED TWO BIT INDEX ADD A ;TIMES 32 TO MAKE POSITION INDEX ADD A ADD A ADD A ADD A MOV C,A ;PUT IN BC XRA B ;CLEAR HIGH ORDER LXI H,BUFR ;TO NAME POSITION IN DEFAULT BUFFER DAD B ;(HL) = CURRENT FOUND NAME POINTER LDA FCB ;PUT DISK DRIVE NUMBER INTO NAME PLACE MOV M,A ;INTO BUFFER XCHG LHLD LISTPOS ;POINTER TO CURRENT LOAD POINT IN LIST XCHG MVI B,12 ;MOVE DRIVE DESIGNATOR AND NAME TO LIST MOVLP: MOÖ A,Í ;GEÔ NAMÅ BYTÅ FROÍ DEFAULÔ BUFFER STAX D ;PLACE INTO LIST INX H ;BUMP POINTERS INX D DCR B ;CHECK MOVE BYTE COUNT JNZ MOVLP XCHG ;(DE) WAS LEFT WITH LEXT LOAD POINT ADDRESS ; MVI B,ITEMSZ-12 ;REMAINING LIST ITEM SPACES TO ZERO OUT FILZRO: Š MVI M,00H ;PUT IN A ZERO BYTE INX H DCR B ;ALL REST FILLED YET JNZ FILZRO ; SHLD LISTPOS ;KEEP NEXT LOAD POINT IN SAFE PLACE LHLD FILECNT ;INCREASE FILE COUNT FOR EACH FILE INX H SHLD FILECNT ; ; ;SEARCH FOR NEXT OCCURANCE OF SPECIFIED FILE NAME ; MVI C,SRCHN ;SEARCH NEXT FUNCTION CODE LXI D,FCB ;FILE NAME SPECIFICATION FIELD CALL BDOS CPI 0FFH ;SEE IF ALL THROUGH DIRECTORY YET JNZ NM2LST ;IF NOT GO PUT NAME INTO LIST ; ; ;PROGRAM EXECUTION TO HERE IF THE LIST CONTAINS SOME FILE NAMES ;FROM THE DISKETTE ; ;USER DOES HIS OWN THING FROM HERE ; ; ;DIRECTORY NAME LIST FOR STORAGE OF INPUT NAMES ; FILECNT: DÓ ² ;COUNTEÒ FOÒ NUMBEÒ OÆ FILEÓ LISTPOS: DÓ  ²  ;STORAGÅ FOÒ CURRENÔ LISÔ  ;LOAD POINTER ; LIST: DS 1 ;START POINT FOR FILE NAME LIST ; ;+++...END OF LISTING 1. .PA ŠOPEN FILE: Function 15. Aî  existinç  filå oî á disë maù noô bå reaä untiì thå  useò FC containó thå informatioî abouô wherå thå filå ió storeä  upoî thå  diskette®  Functioî 1µ provideó á meanó wherå thå useò filló iî  thå filå namå anä theî calló thå operatinç systeí tï geô  thå d1-dî byteó oæ thå FC filleä in®  Oncå thå filå ió OPEÎ theî  iô maù  bå  reaä becauså subsequenô calló tï thå BDOÓ tï  REAÄ  wilì "kno÷  where¢  thå filå ió located®  Thå OPEÎ functioî returnó  á valuå  oæ  0FFÈ iæ thå filå cannoô bå found¬  otherwiså  thå  (A© registeò containó á valuå oæ ° tï ³ tï indicatå thaô thå filå waó successfullù opened®  Tï opeî á filå thå programminç procedurå ió simply: ; ;OPEN FILE EXAMPLE ; OPEN EQU 15 ;OPEN FUNCTION CODE BDOS EQU 0005H ;SYSTEM ENTRY ORG 0100H ;START LXI D,FCB ;POINT AT FILE CONTROL BLOCK MVI C,OPEN ;FUNCTION CALL BDOS CPI 0FFH ;CHECK IF NOT FOUND JZ ERROR RET ;IF OPEN GO TO CCP ; ERROR: MVI C,9 ;PRINT ERROR MESSAGE LXI D,ERRMS CALL BDOS RET ; ERRMS: DB 'FILE NOT FOUND','$' ; ; ;FILE ACCESS FILE CONTROL BLOCK ; FCB: DB 00H ;SET TO USE DEFAULT DRIVE DB 'TEST DAT',0,0,0,0 DS 16 ;STORAGE FOR D1 TO DN BYTES DB 0 ;CURRENT RECORD BYTE ; END .pa Š CLOSE FILE: Function 16. Wheneveò  á  filå  ió  accesseä foò  writinç  ne÷  spacå  ió allocateä  foò thaô filå oî thå disk®  Thió implieó thaô thå useò FC  containó  disë grouð numberó thaô arå noô  storeä  upoî  thå diskettå  iî  thå  directorù  entrù foò  thå  file®  Functioî  1¶ provideó  á  meanó  wherå  thå useò completeó  thå  filå  writinç operatioî  anä  theî  calló  thå  operatinç  systeí  tï  seô  thå directorù  entrù  grouð allocatioî bytes¬  thå rã  bytå  anä  thå extenô bytå froí thå correspondinç byteó oæ thå FCB®  Á filå thaô haó beeî openeä foò readinç onlù neeä noô bå closeä becauså therå ió nï changå iî thå storeä disë directorù information®  Thå CLOSÅ functioî  returnó  á valuå oæ 0FFÈ iæ thå filå cannoô  bå  found¬ otherwiså thå (A© registeò containó á valuå oæ ° tï ³ tï indicatå thaô  thå  filå  waó successfullù closed®  Tï closå  á  filå  thå programminç procedurå ió simply: ; ;CLOSE FILE EXAMPLE ; CLOSE EQU 16 ;CLOSE FUNCTION CODE BDOS EQU 0005H ;SYSTEM ENTRY ORG 0100H ;START LXI D,FCB ;POINT AT FILE CONTROL BLOCK MVI C,CLOSE ;FUNCTION CALL BDOS CPI 0FFH ;CHECK IF NOT FOUND JZ ERROR RET ;IF CLOSED GO TO CCP ; ERROR: MVI C,9 ;PRINT ERROR MESSAGE LXI D,ERRMS CALL BDOS RET ; ERRMS: DB 'FILE NOT FOUND','$' ; ; ;FILE ACCESS FILE CONTROL BLOCK ; FCB: DB 00H ;SET TO USE DEFAULT DRIVE DB 'TEST DAT',0,0,0,0 DS 16 ;STORAGE FOR D1 TO DN BYTES DB 0 ;CURRENT RECORD BYTE ; END .PA Š DELETE FILE: Function 19. Ofteî  timå thå programmeò wilì creatå anä writå fileó whicè wilì subsequentlù noô bå needed® Thå filå oò fileó maù bå deleteä througè  uså  oæ  functioî  19®  Thå useò  setó  aî  FC  tï  thå appropiatå  filå  namå iî thå f1-f8¬  anä t1-t³ bytes®  Thå  BDOÓ functioî  theî removeó thå specifieä filå froí thå  directorù  oæ thå appropiatå disk®  Thå useò specifieä filå namå iî thå FC maù contaiî  ASCIÉ  questioî markó iî whicè caså thå deletå  functioî maù  deletå multiplå fileó iæ thå filå namå matcheó morå thaî onå filå oî thå disë witè thå name®  Thå "?¢ matcheó anù characteò aô thå positioî oæ itó occurrancå iî thå name®  Thå DELETÅ  functioî returnó á valuå oæ 0FFÈ iæ thå file(s© cannoô bå found¬ otherwiså thå  (A© registeò containó á valuå oæ ° tï ³ tï indicatå thaô thå filå waó successfullù deleted®  Tï deletå á filå thå  programminç procedurå ió simply: ; ;DELETE FILE EXAMPLE ; DELETE EQU 19 ;CLOSE FUNCTION CODE BDOS EQU 0005H ;SYSTEM ENTRY ORG 0100H ;START LXI D,FCB ;POINT AT FILE CONTROL BLOCK MVI C,DELETE ;FUNCTION CALL BDOS CPI 0FFH ;CHECK IF NOT FOUND JZ ERROR RET ;IF CLOSED GO TO CCP ; ERROR: MVI C,9 ;PRINT ERROR MESSAGE LXI D,ERRMS CALL BDOS RET ; ERRMS: DB 'FILE NOT FOUND','$' ; ; ;FILE ACCESS FILE CONTROL BLOCK ; FCB: DB 00H ;SET TO USE DEFAULT DRIVE DB 'TEST DAT',0,0,0,0 DS 16 ;STORAGE FOR D1 TO DN BYTES DB 0 ;CURRENT RECORD BYTE ; END .PA Š CREATE FILE: Function 22. Wheneveò  á ne÷ filå ió desireä iô musô firsô bå createä  sï thaô  therå  ió  á spoô iî thå directorù tï lateò savå  thå  filå allocatioî  informatioî  (seå closå  functioî  above)®  Thå  BDOÓ assumeó  thaô thå programmeò haó specifieä á filå namå thaô  doeó noô exisô upoî thå disk®  Iæ therå ió á chancå thaô á ne÷ filå ió desireä  thaô maù duplicatå thå namå oæ onå alreadù upoî thå disë thå  peviouslù describeä deletå functioî shoulä bå useä tï  eraså thå  olä  filå  beforå  creatinç  thå  ne÷  file®  Otherwiså  thå directorù  maù  contaiî twï fileó bù thå samå  name®  Thå  CREATÅ functioî  returnó  á  valuå oæ 0FFÈ iæ therå ió nï  rooí  iî  thå directorù tï storå thå freshlù createä directorù entry¬ otherwiså thå  (A© registeò containó á valuå oæ ° tï ³ tï indicatå thaô thå filå  waó  successfullù  created®  Á newlù createä  filå  maù  bå immediatelù writteî sincå thå BDOÓ prepareó thå useò FC tï  looë likå aî emptù file® Tï creatå á filå thå programminç procedurå ió simply: ; ;CREATE FILE EXAMPLE ; CREATE EQU 22 ;CREATE FUNCTION CODE BDOS EQU 0005H ;SYSTEM ENTRY ORG 0100H ;START LXI D,FCB ;POINT AT FILE CONTROL BLOCK MVI C,CREATE ;FUNCTION CALL BDOS CPI 0FFH ;CHECK IF DIRECTORY FULL JZ ERROR RET ;IF CLOSED GO TO CCP ; ERROR: MVI C,9 ;PRINT ERROR MESSAGE LXI D,ERRMS CALL BDOS RET ; ERRMS: DB 'DIRECTORY FULL','$' ; ; ;FILE ACCESS FILE CONTROL BLOCK ; FCB: DB 00H ;SET TO USE DEFAULT DRIVE DB 'TEST DAT',0,0,0,0 DS 16 ;STORAGE FOR D1 TO DN BYTES DB 0 ;CURRENT RECORD BYTE ; END .PA Š RENAME FILE: Function 23. Sometimeó  iô ió necessarù tï changå thå namå oæ á disë filå froí thaô alreadù existinç iî thå disë directory®  Witè  functioî 2³  thå  useò specifieó thå namå oæ aî existinç filå oî thå  disë witè  á standarä FC formaô excepô thaô oî callinç thå  BDOÓ  thå d1-dî  bytå  areá oæ thå FC arå seô tï thå ne÷ namå desireä  foò thå  file®  Alì occurranceó oæ thå existinç filå  namå  (ie®  alì extents© arå changeä tï matcè thå ne÷ name® Thå drivå selecô bytå specifieó  thå  drivå upoî whicè thå renamå operatioî  shoulä  bå done®  Thå  firsô bytå oæ thå seconä 1¶ byteó oæ thå FC (d0©  ió expecteä tï bå zero®  Thå RENAMÅ functioî returnó á valuå oæ 0FFÈ iæ  thå  olä  namå filå coulä noô bå  found¬  otherwiså  thå  (A© registeò containó á valuå oæ ° tï ³ tï indicatå thaô thå filå waó successfullù renamed®  Tï renamå á filå thå programminç procedurå ió simply: ; ;RENAME FILE EXAMPLE ; RENAME EQU 23 ;RENAME FUNCTION CODE BDOS EQU 0005H ;SYSTEM ENTRY ORG 0100H ;START LXI D,FCB ;POINT AT FILE CONTROL BLOCK MVI C,RENAME ;FUNCTION CALL BDOS CPI 0FFH ;CHECK IF DIRECTORY FULL JZ ERROR RET ;IF CLOSED GO TO CCP ; ERROR: MVI C,9 ;PRINT ERROR MESSAGE LXI D,ERRMS CALL BDOS RET ; ERRMS: DB 'FILE NOT FOUND','$' ; ; ;FILE ACCESS FILE CONTROL BLOCK ; FCB: DB 00H ;SET TO USE DEFAULT DRIVE DB 'TEST DAT',0,0,0,0 ;OLD NAME DB 00H ;BYTE ASSUMED TO BE ZERO DB 'NEWNAME DAT',0,0,0,0 ;NEW NAME DB 0 ;CURRENT RECORD BYTE ; END .PA ŠACCESSING FILE DATA Thå previouó sectioî showeä thå readeò ho÷ tï finä anä setuð fileó foò subsequenô I/O® Otheò file/directorù handlinç functionó werå  alsï presented®  Thió haó alì leä uð tï thå biç momenô wheî thå useró prograí ió finallù readù tï reaä oò writå datá  from/tï a disk file. So here it is at last... CP/Í  disë filå datá ió moveä betweeî thå disë anä memorù iî blockó oæ 12¸ byteó calleä logicaì recordó oò "sectors¢ iî  oldeò fashioneä  CP/Í  lingo®  Twï functionó tï bå presenteä  herå  arå includeä  iî  thå  CP/Í BDOÓ functioî codå  tï  allo÷  sequentiaì accesó  tï blockó oæ datá iî á file®  Thå REAÄ functioî startó aô thå beginninç oæ á filå anä readó datá blockó tilì thå enä oæ thå file®  Thå  opposinç WRITÅ operatioî moveó datá blockó tï  á  ne÷ disë filå anä writeó tilì thå enä oæ thå useró datá wheî thå filå ió  closeä  (oò thå disë ió fulì iæ thå programmeò haó  toï  mucè data)®  Thå BDOÓ includeó onå otheò functioî thaô allowó thå useò tï specifù thå areá iî hió prograí wherå thå 12¸ bytå disë recorä buffeò  ió  tï  bå located®  Theså threå functionó wilì  eacè  bå individually described below. SET DISK BUFFER ADDRESS: Function 26. Thå 12¸ bytå datá buffeò thaô ió tï bå useä bù thå BDOÓ  foò filå  I/Ï ió baseä aô aî addresó commonlù referreä tï aó thå "DMÁ ADDRESS"®  Thió addresó oò "buffeò pointer¢ ió passeä tï thå BDOÓ iî  thå (DE© registeró wheî performinç functioî 26®  Thå  prograí belo÷ simplù setó thå buffeò addresó tï "DATBF"¬  á storagå  areá after the end of the short program. ; ;SET BUFFER ADDRESS EXAMPLE ; STDMA EQU 26 ;SET BUFFER ADDRESS FUNCTION CODE BDOS EQU 0005H ;SYSTEM ENTRY ORG 0100H ;START LXI D,DATBF ;POINT AT DATA BUFFER MVI C,STDMA ;FUNCTION CALL BDOS RET ;BACK TO CCP ; DATBF: DS 128 ;SETUP 128 BYTE BUFFER ; END .pa ŠREAD AND WRITE DISK RECORDS: Functions 20 and 21. Thå  disë  reaä  anä  writå functionó arå  verù  similaò  iî operatioî  iî thaô botè movå 12¸ byteó oæ datá to/froí thå  useró program®  Thå REAÄ assumeó entrù witè (DE© pointinç tï aî  activå FC setuð bù thå opeî filå function® Thå reaä sequentiaì functioî readó  thå 12¸ bytå recorä specifieä bù thå "cr¢ fielä oæ thå FC intï  thå buffeò pointeò tï bù thå currenô disë  buffeò  address® Afteò  eacè  REAÄ operatioî thå "cr¢ fielä ió incrementeä tï  thå nexô recorä number®  Iæ thå "cr¢ fielä overflowó pasô thå enä  oæ thå extenô withouô encounterinç thå enä oæ thå filå theî thå BDOÓ automaticallù  openó thå nexô extenô iî preparatioî foò thå  nexô reaä  operation®  Thå REAÄ functioî returnó á 00È codå iî thå (A© registeò  iæ thå REAÄ waó performeä successfully®  Iæ thå enä  oæ filå ió encountereä á noî zerï valuå ió returneä iî (A). Thå WRITÅ functioî assumes¬  oî entrù tï thå BDOS¬  thaô thå (DE©  registeró  poinô aô á validlù openeä oæ  createä  FCB®  Thå WRITÅ  wilì movå 12¸ byteó oæ datá froí thå buffeò  specifieä  bù thå  currenô disë buffeò addresó tï thå disk®  Thå writteî recorä ió  placeä  aô thå "cr¢ recorä positioî oæ thå  extent®  Aó  eacè recorä  ió writteî thå "cr¢ fielä ió incrementeä  iî  preparatioî foò  thå nexô writå operation®  Similaò tï thå READ¬  iæ thå "cr¢ fielä  overflowó  pasô thå enä oæ thå currenô  extent¬  thå  BDOÓ automaticallù  closeó thå currenô extenô anä createó á ne÷ extenô iî  preparatioî foò thå nexô writå operation®  Thå WRITE  commanä maù  bå  performeä oî aî existinç file®  Iæ  thå  filå  currentlù containó  datá aô thå "cr¢ recorä theî thå WRITÅ wilì overlaù thå currenô  datá witè thå ne÷ 12¸ bytå record®  Thå  WRITÅ  functioî returnó  á  00È  valuå iî thå (A© registeò iæ  thå  operatioî  ió successful®  Á  non-zerï valuå ió returneä iæ thå writå  functioî was unsuccessful due to a full disk or directory. The small program below is designed to read the first record oæ  á  filå  'TEST.DAT'¬   anä  writå  iô  intï  thå  smalì  filå 'ONEREC.DAT'. The program should be reasonably self documenting. ; ;READ AND WRITE FUNCTION EXAMPLES ; READ EQU 20 ;READ FUNCTION CODE WRITE EQU 21 ;WRITE FUNCTION CODE OPEN EQU 15 ;OPEN FUNCTION CODE CLOSE EQU 16 ;CLOSE FUNCTION CODE DELETE EQU 19 ;DELETE FUNCTION CODE CREATE EQU 22 ;CREATE NEW FILE STDMA EQU 26 ;SET DISK BUFFER ADDRESS BDOS EQU 0005H ;SYSTEM ENTRY ORG 0100H ;START LXI D,DATBF ;POINT AT DATA BUFFER MVI C,STDMA ;FUNCTION CALL BDOS ; Š LXI D,FCBIN ;POINT AT AND OPEN INPUT FILE MVI C,OPEN CALL BDOS CPI 0FFH ;CHECK FOR OPEN ERROR JZ ERROR ; LXI D,FCBOUT ;DEFAULT DELETE OF NEW FILE MVI C,DELETE ;..IN CASE IT EXISTS ALREADY CALL BDOS LXI D,FCBOUT ;POINT AT FILE CONTROL BLOCK MVI C,CREATE ;FUNCTION TO MAKE NEW FILE CALL BDOS CPI 0FFH ;CHECK IF DIRECTORY FULL JZ ERROR XRA A ;CLEAR THE INPUT CR FIELD TO READ STA INCR ;..FIRST RECORD LXI D,FCBIN ;READ FIRST FILE MVI C,READ CALL BDOS ORA A ;CHECK IF READ WAS O.K. JNZ ERROR LXI D,FCBOUT ;WRITE TO OUTPUT FILE MVI C,WRITE CALL BDOS ORA A ;CHECK THAT DISK WASNT FULL JNZ ERROR ; LXI D,FCBOUT ;CLOSE THE OUTPUT FILE MVI C,CLOSE CALL BDOS CPI 0FFH ;CHECK CLOSE STATUS RNZ ;BACK TO CCP IF NO ERROR ; ERROR: MVI C,9 ;PRINT ERROR MESSAGE LXI D,ERRMS CALL BDOS RET ; ERRMS: DB 'PROGRAM FILE ERROR','$' ; ; ;FILE ACCESS FILE CONTROL BLOCKS ; FCBIN: DB 00H ;SET TO USE DEFAULT DRIVE DB 'TEST DAT',0,0,0,0 DS 16 ;STORAGE FOR D1 TO DN BYTES INCR: DB 0 ;CURRENT RECORD BYTE ; FCBOUT: DB 00H ;SET TO USE DEFAULT DRIVE DB 'ONEREC DAT',0,0,0,0 Š DS 16 ;STORAGE FOR D1 TO DN BYTES DB 0 ;CURRENT RECORD BYTE ; DATBF: DS 128 ;SETUP 128 BYTE BUFFER ; END SEQUENTIAL FILE I/O PROGRAMMING EXAMPLE Thå   assemblù  languagå  codå  oæ  Listinç  ²  presentó   á comprehensivå  seô oæ I/Ï routineó thaô allo÷ eitheò aî inpuô  oò outpuô  sequentiaì filå tï bå processeä oî á bytå bù bytå  basis® Thå routineó perforí alì necessarù sectoò buffering®  Thå  readeò ió  encourageä tï fullù studù thå codå anä gaiî aî  understandinç oæ ho÷ iô alì works®  Thå prograí useó mosô oæ thå BDOÓ functionó presented in this turorial. Listing 2. CHARACTER BY CHARACTER DISK I/O ROUTINES ;**************************************************************** ; ; DEMONSTRATION SEQUENTIAL CP/M FILE CHARACTER BY ; CHARACTER I/O ROUTINES. NOTE THAT THE MAIN BODY ; OF THIS PROGRAM IS NOT DESIGNED TO RUN AS IS IN ; ANY NORMAL MANNER. ; ; MANY THANKS ARE DUE TO WARD CHRISTENSEN WHO PREPARED THE ; ORIGINAL SET OF SIMILAR I/O ROUTINES BURIED INSIDE OF ; THE CP/M USERS GROUP MODEM PROGRAM THAT HAS BECOME SO ; VERY POPULAR. THANKS AGAIN WARD. ; ;****************************************************************** ; ; ;CP/M BDOS EQUATES ; RDCON EQU 1 WRCON EQU 2 PRINT EQU 9 OPEN EQU 15 ;OPEN FILE CLOSE EQU 16 ;CLOSE FILE SRCHF EQU 17 ;SEARCH FOR FIRST ERASE EQU 19 ;DELETE FILE READ EQU 20 ;READ FILE RECORD WRITE EQU 21 ;WRITE FILE RECORD MAKE EQU 22 ;CREATE NEW FILE STDMA EQU 26 ;SET DATA BUFFER POINTER BDOS EQU 0005H ;SYSTEM I/O ENTRY POINT FCB EQU 5CH ;SYSTEM FCB ŠFCBEXT EQU FCB+12 ;FILE EXTENT FCBSNO EQU FCB+32 ;SECTOR # FCB2 EQU 6CH ;SECOND FCB DSKBUF EQU 080H ;DEFAULT DISK BUFFER ADDRESS SECSIZ EQU 080H ;CP/M SECTOR SIZE ; WBOOT EQU 00 ;CP/M WARM BOOT ENTRY ADDRESS ; ; ;DEFINE ASCII CHARACTERS USED ; LF EQU 10 ;LINEFEED CR EQU 13 ;CARRIAGE RETURN EOFCHR EQU 01AH ;CP/M END OF FILE CHAR ; ; ;START OF EXECUTABLE CODE ; ORG 100H LXI SP,STACK ;SETUP A STACK TO USE ; ; ;SEQUENTIAL I/O WRITE OF CP/M FILE ENABLED BY USING THIS SEQUENCE ;OF SUBROUTINE CALLS. THE FILE CONTROL BLOCK IS ASSUMED TO BE ;STORED AT THE DEFAULT LOCATION AT 05CH IN THE BASE PAGE OF ;CP/M MEMORY MAP. ; SIOWR: CALL ERASFIL ;ERASE RECIEVED FILE CALL MAKEFIL ;ESTABLISH NEW FILE CALL INITWR ;INITIALIZE FILE WRITE PARAMETERS ; ; ;MAKE FOLLOWING CALL TO PLACE A CHARACTER FROM THE (A) REGISTER ;INTO THE CP/M FILE. LOOP DOING THIS TILL YOU HAVE ALL IN FILE THAT ;IS NEEDED. ; CALL WRCHAR ;PUT CHAR IN FILE ; CALL WREOF ;FLUSH LAST SECTOR TO CP/M FILE CALL CLOSFIL ;CLOSE IT UP ; ; ;SEQUENCE OF COMMAND CALLS TO OPEN AND USE A SEQUENTIAL CHARACTER ;FILE FOR READING. THE FILE CONTROL BLOCK IS ASSUMED TO BE LOCATED ;AT THE DEFAUT LOCATION OF 05CH IN THE BASE CP/M PAGE. ;ONCE THE FILE IS INITIALIZED THE CHARACTERS CAN BE READ ONE BY ;ONE UNTIL THE RDCHAR SUBROUTINE RETURNS A SET CARRY FLAG ;INDICATING A END OF PHYSICAL FILE CONDITION. EOF IS SENSED AS ;PHYSICAL END OR 01AH CHARACTER WHICHEVER COMES FIRST ; SIORD: CALL OPENFIL ;OPEN THE CP/M FILE CALL INITRD ;GO INIT FOR FILE READ CALL RDCHAR ;GET CHAR FROM CP/M FILE Š JC EOF ;CHECK FOR EOF ; EOF: ; PLACE CODE HERE FOR END OF FILE HANDLING ; ;I/O HANDLING SUBROUTINES ; ; ; ;>--> ERASFIL: ERASE THE INCOMING FILE. ; ;IF IT EXISTS, ASK IF IT MAY BE ERASED. ; ERASFIL: LXI D,FCB ;POINT TO CTL BLOCK MVI C,SRCHF ;SEE IF IT.. CALL BDOS ;..EXISTS INR A ;FOUND? RZ ;..NO, RETURN CALL ILPRT ;PRINT: DB '++CP/M FILE EXISTS, TYPE Y TO ERASE: ',0 CALL KEYIN ;GET A CHARACTER FROM CONSOLE ANI 5FH ;MAKE UPPER CASE CPI 'Y' ;WANT ERASED? JNZ EXIT ;QUIT IF NOT ERASE CALL CRLF ;BACK TO START OF LINE ; ; ;ERASE OLD FILE ; LXI D,FCB ;POINT TO FCB MVI C,ERASE ;GET BDOS FNC CALL BDOS ;DO THE ERASE RET ;FROM "ERASFIL" ; ; ;>--> MAKEFIL: MAKES THE FILE TO BE RECEIVED ; MAKEFIL: LXI D,FCB ;POINT TO FCB MVI C,MAKE ;GET BDOS FNC CALL BDOS ;TO THE MAKE INR A ;FF=BAD? RNZ ;OPEN OK ; ; ;DIRECTORY FULL - CAN'T MAKE FILE ; CALL ERXIT DB '++ERROR - CANNOT MAKE FILE',CR,LF DB '++DIRECTORY MUST BE FULL',CR,LF,'$' ; ; ;>--> OPENFIL: OPENS THE FILE TO BE SENT ; ŠOPENFIL: LXI D,FCB ;POINT TO FILE MVI C,OPEN ;GET FUNCTION CALL BDOS ;OPEN IT INR A ;OPEN OK? RNZ ;FILE OPENED OK CALL ERXIT ;..NO, ABORT DB '++CANNOT OPEN CP/M FILE','$' ; ; ;>--> CLOSFIL: CLOSES THE RECEIVED FILE ; CLOSFIL: LXI D,FCB ;POINT TO FILE MVI C,CLOSE ;GET FUNCTION CALL BDOS ;CLOSE IT INR A ;CLOSE OK? RNZ ;..YES, RETURN CALL ERXIT ;..NO, ABORT DB '++CANNOT CLOSE CP/M FILE','$' ; ; ;>--> INITRD: INITIALIZES FILE READ PARAMETERS ; INITRD: MVI A,00H ;SET THE BUF CNT TO EMPTY STA CHRINBF LXI D,DSKBUF ;SET THE DMA BUFFER POINTER PUSH D MVI C,STDMA CALL BDOS POP D XCHG ;SET SECTOR POINTER SHLD SECPTR RET ; ; ;>--> RDCHAR: READS A CHARACTER FROM FILE ; ;RETURN IS WITH DESIRED CHARACTER IN ;THE A REGISTER. IF EOF, THEN ;RETURN IS WITH THE CARRY FLAG SET. ; RDCHAR: LDA CHRINBF ;GET NUMBER OF CHAR IN BUF ORA A ;CHECK IF BUFFER EMPTY JZ RDBLOCK ;GO GET A SECTOR IF EMPTY DCR A ;DECREMENT STA CHRINBF LHLD SECPTR ;GET BUFFER POINTER MOV A,M ;GET CHARACTER FOR CALLER INX H ;INCREMENT POINTER SHLD SECPTR CPI EOFCHR ;CHECK FOR LOGICAL CP/M EOF STC Š RZ ;RETURN EXIT FOR LOGICAL EOF CMC ;CLEAR CARRY SO EOF NOT INDICATED ;ON NORMAL RETURN RET ;FROM "RDCHAR" ; ; ;BUFFER IS EMPTY - READ IN ANOTHER SECTOR ; RDBLOCK: LXI D,FCB MVI C,READ CALL BDOS ORA A ;READ OK? JZ RDBFULL ;YES DCR A ;EOF? JZ REOF ;GOT EOF ; ; ;READ ERROR ; CALL ERXIT DB '++CP/M FILE READ ERROR','$' ; REOF: STC ;SET CARRY FLAG FOR EOF EXIT RET ; ; ;BUFFER IS FULL ; RDBFULL: MVI A,SECSIZ ;INIT BUF CHAR COUNT STA CHRINBF LXI H,DSKBUF ;INIT BUFFER.. SHLD SECPTR ;..POINTER JMP RDCHAR ;PASS CHAR TO CALLER ; ; ;>--> INITWR: INITIALIZES FILE WRITE PARAMETERS ; INITWR: MVI A,00H ;SET THE BUF CNT TO EMPTY STA CHRINBF LXI D,DSKBUF ;SET THE DMA BUFFER POINTER PUSH D MVI C,STDMA CALL BDOS POP D XCHG ;SET SECTOR POINTER SHLD SECPTR RET ; ; ;>--> WRCHAR: WRITE A CHARACTER TO FILE ; Š;ENTRY IS WITH CHARACTER IN A ;ENTRY AT WREOF FILLS REMAINING BYTES ;OF SECTOR WITH 01AH PER CP/M CONVENTION. ; WRCHAR: LHLD SECPTR ;PUT CHAR IN BUFFER MOV M,A INX H ;BUMP POINTER SHLD SECPTR LDA CHRINBF ;INCR CHAR COUNT INR A STA CHRINBF CPI SECSIZ ;CHECK IF SECTOR FULL RNZ ;GO BACK IF OK ; WRBLOCK: LXI D,FCB ;IF FULL THEN WRITE MVI C,WRITE ;..THE.. CALL BDOS ;..BLOCK ORA A JNZ WRERR ;OOPS, ERROR MVI A,00H ;RESET THE CHAR CNT STA CHRINBF LXI H,DSKBUF ;RESET BUFFER.. SHLD SECPTR ;..POINTER RET ; WRERR: CALL ERXIT ;EXIT W/MSG: DB '++ERROR WRITING CP/M FILE',CR,LF,'$' ; WREOF: LDA CHRINBF ;FILL REST OF SECTOR WITH 01AH LHLD SECPTR MVI B,EOFCHR WREND: MOV M,B ;PUT IN THE CP/M EOF CODE INX H INR A ;INC THE CHAR CNT CPI SECSIZ ;BUFFER FULL YET JNZ WREND JMP WRBLOCK ;GO PUT FILLED BLOCK ON DISK ; ; ;>--> KEYIN: GETS A KEY CODE IN FROM CONSOLE ; KEYIN: PUSH B ;SAVE.. PUSH D ;..ALL.. PUSH H ;..REGS MVI C,RDCON ;GET CON CHAR FUNCTION CODE CALL BDOS ;GET CHARACTER MOV A,E POP H ;RESTORE.. POP D ;..ALL.. Š POP B ;..REGS RET ; ; ;>--> CTYPE: TYPES VIA CP/M SO TABS ARE EXPANDED ; CTYPE: PUSH B ;SAVE.. PUSH D ;..ALL.. PUSH H ;..REGS MOV E,A ;CHAR TO E MVI C,WRCON ;GET BDOS FNC CALL BDOS ;PRIN THE CHR POP H ;RESTORE.. POP D ;..ALL.. POP B ;..REGS RET ;FROM "CTYPE" ; ; ;>--> CRLF: TYPE A CARRAGE RETURN LINE FEED PAIR AT CONSOLE ; CRLF: MVI A,CR CALL CTYPE MVI A,LF CALL CTYPE RET ; ; ;>--> ILPRT: INLINE PRINT OF MSG ; ;THE CALL TO ILPRT IS FOLLOWED BY A MESSAGE, ;BINARY 0 AS THE END. BINARY 1 MAY BE USED TO ;PAUSE (MESSAGE 'PRESS RETURN TO CONTINUE') ; ILPRT: XTHL ;SAVE HL, GET HL=MSG ILPLP: MOV A,M ;GET CHAR ORA A ;END OF MSG? JZ ILPRET ;..YES, RETURN CPI 1 ;PAUSE? JZ ILPAUSE ;..YES CALL CTYPE ;TYPE THE CHARACTER OF MESSAGE ILPNEXT: INX H ;TO NEXT CHAR JMP ILPLP ;LOOP ; ; ;PAUSE WHILE TYPING HELP SO INFO DOESN'T ; SCROLL OFF OF VIDEO SCREENS ; ILPAUSE: CALL ILPRT ;PRINT: Š DB CR,LF,'PRESS RETURN TO CONTINUE OR ^C TO EXIT' DB CR,LF,0 CALL KEYIN ;GET ANY CHAR CPI 'C'-40H ;REBOOT? JZ EXIT ;YES. JMP ILPNEXT ;LOOP ; ILPRET: XTHL ;RESTORE HL RET ; & RETURN ADDR PAST MESSAGE ; ; ;>--> PRTMSG: PRINTS MSG POINTED TO BY (DE) ; ;A '$' IS THE ENDING DELIMITER FOR THE PRINT. ;NO REGISTERS SAVED. ; PRTMSG: MVI C,PRINT ;GET BDOS FNC JMP BDOS ;PRINT MESSAGE, RETURN ; ; ;>--> ERXIT: EXIT PRINTING MSG FOLLOWING CALL ; ERXIT: POP D ;GET MESSAGE CALL PRTMSG ;PRINT IT ; EXIT: LXI D,080H ;RESET DEFAULT DMA ADDRESS FOR EXIT MVI C,STDMA CALL BDOS LHLD STACK ;GET ORIGINAL STACK SPHL ;RESTORE IT JMP WBOOT ;GO DO A WARM BOOT OF CP/M TO BRING ;BACK IN CCP ; ; ;FOLLOWING 2 USED BY THE CP/M DISK BUFFERING ROUTINES ; SECPTR DW DSKBUF ;POINTER TO DISK BUFFER POS CHRINBF DB 0 ;# OF CHARACTERS IN BUFFER ; ; ;SETUP A STACK AREA ; DS 38 ;STACK AREA STACK DS 2 ;STACK POINTER ; ; -------------- ; END ; ;+++...END OF LISTING 2 Š Thå  readeò  ió inviteä tï bå witè uó agaiî nexô montè  wheî thå  tutoriaì  continueó  intï itó  thirä  anä  finaì  part®  Thå functionó  oæ  randoí  recorä  filå I/Ï wilì  bå  presenteä  witè completå  programminç  exampleó  tï sho÷ ho÷  randoí  I/Ï  works® Severaì speciaì filå I/Ï trickó wilì bå showî thaô permiô  uniquå problemó  tï  bå solveä undeò thå CP/Í operatinç system®  Onå  oæ theså  wilì bå á prograí thaô doeó "update¢ oî aî exisitinç  filå withouô  thå uså oæ thå randoí recorä I/Ï capabilities®  Sï  lonç tilì Januarù anä É hopå thaô alì Lifå Lineó readeró havå á joyouó holiday season.