SLIDING INTO BDOS (Part III) UNDERSTANDING RANDOM FILES by: Michael J. Karas 2468 Hansen Court Simi Valley, CA 93065 (805) 527-7922 Thå timå haó arriveä tï completå thå thirä anä finaì parô oæ thió  serieó oî thå operatioî oæ thå CP/Í BDOÓ aó vieweä froí thå assemblù  languagå  programmeró perspective®  Presentlù  wå  wilì builä upoî thå extensivå treatmenô oæ sequentiaì fileó  presenteä iî Parô IÉ oæ thå serieó tï providå á basió foò understandinç thå CP/Í  2.² randoí filå I/Ï capability®  Pleaså notå thaô functionó oæ thå BDOÓ presenteä herå arå specifiã tï CP/Í Versionó 2.²  anä 3.0® Oldeò CP/Í systemó usinç Versioî 1.´ dï noô directlù supporô randoí  accesó  filå I/Ï anä aó sucè arå noô compatiblå witè  thå programminç exampleó presenteä below. WHY RANDOM FILE I/O ANYWAY Iî  thå  beginninç  oæ thå CP/Í  era¬  sometimå  arounä  thå releaså  oæ  Versioî 1.³ bù Digitaì Research¬  smalì  inexpensivå single-useò  micrï  processoò  systemó werå  typicallù  useä  foò simple-mindeä  datá  processinç  applications®   Mosô   computinç operationó  werå lineaò witè respecô tï thå datá handlinç bù  thå CPU®  Datá entereä froí papeò tape¬  cassette¬  carä readers¬  oò humaî  entrù froí á keyboarä tendeä tï bå limiteä tï á sequentiaì processinç  froí starô tï finish®  Thå usagå oæ sucè datá bù  thå computeò  iî  datá  analysis¬  prograí  compilation¬  oò  logginç applicationó waó alsï largelù sequential® Finallù thå datá outpuô operationó  baseä  upoî  thå needó  oæ  harä  copy¬  backup¬  anä transmissioî  froí  micrï tï micrï werå relegateä  tï  sequentiaì processinç applications. Anticipateä applicationó oæ micrï typå computeò hardwarå  bù operatinç systeí designers¬  aô thaô time¬ seemeä tï dictatå thaô thå  disë  filå  structureó oæ thå operatinç  systemó  shoulä  bå sequentiaì iî nature®  Thió waó truå foò thå earliesô releaseó oæ CP/Í  anä Intel'ó ISIÓ IÉ operatinç system®  Otheò simplå  floppù disë operatinç systemó likå PERTEC'ó FDOÓ anä MITS§ Disë Extendeä Basiã  operatinç  systemó  werå alsï strictlù sequentiaì  iî  thå treatmenô oæ thå disë filå allocatioî anä storage® However¬ theså twï  systemó permitteä randoí recorä I/Ï withiî thå boundó oæ  aî alreadù existnç filå provideä thå spacå tï storå thå recordó  waó Špreviouslù  pre-allocateä  aó contiguouó disë spacå iî  thå  filå structure®  Thå procesó oæ randoí I/Ï waó theî easù aó á relativå offseô  betweeî thå beginninç recorä numbeò foò thå filå anä  thå offseô desireä withiî thå file® Aó thå micrï processoò applicationó markeô openeä uð iî  thå latå  1970'ó  iô  seemeä thaô ne÷ useó foò computeró  werå  beinç founä  weekly®  Iô haó gottoî tï thå poinô thaô  micrï  processoò computeò  useró havå á largå arraù oæ verù sophisticateä softwarå packageó  tï chooså froí anä utilizå iî theiò businesó anä  hobbù activities®  Thå maiî thinç thaô caî bå pointeä ouô abouô manù oæ theså  packageó  ió thaô thå processeó theù  perforí  arå  hardlù lineaò witè respecô tï thå handlinç oæ data® Interactivå programó likå worä processors¬  datá baså managers¬ spellinç checkers¬ anä spreaä  sheeô analysió programó maù verù welì neeä tï bå ablå  tï storå  oò accesó datá to/froí á disë filå iî á manneò thaô cannoô bå   handleä  iî  thå  olä  sequentiaì  manner®   Thå  sequentiaì philosophù generallù limiteä filå updatå tï appendinç tï thå  enä oæ thå filå anä reaä accesó tï á particulaò recorä haä tï reaä N- ±  recordó froí thå beginninç oæ thå filå prioò tï beinç ablå  tï reaä recorä N. Randoí   accesó   filå  I/Ï  withiî  aî   operatinç   systeí anticipateó  thå requirementó oæ non-sequentiaì I/Ï bù permittinç accesó  tï  variouó  recordó  directly®   Anù  recorä  thaô   waó previouslù  writteî  maù  bå  reaä  upoî  demand®   Likewiså  thå user/programmeò  maù  writå  anù  recorä  desired®   Thå  Digitaì Researcè  CP/Í  operatinç systeí supportó thió typå oæ I/Ï  iî  á powerfuì  yeô elegantlù simplå manneò througè á seô oæ fouò  BDOÓ systeí  functions®  Theså calló allo÷ randoí accesó disë fileó tï bå   implementeä  withiî  thå  standarä  CP/Í   compatiblå   filå structure® RANDOM FILE STRUCTURE UNDER CP/M 2.2 Thå  structurå  oæ  randoí fileó undeò  thå  CP/Í  operatinç systeí is mucè thå samå aó thaô foò sequentiaì files® Parô IÉ oæ thió serieó (Lifelineó, January  1982© describeä anä  illustrateä thå  sequentiaì structurå iî detail®  Thå readeò wilì recalì that CP/Í  treató  disë  datá iî fixeä recordó  oæ  12¸  bytes®  Theså recordó  arå collecteä togetheò intï "groups¢ thaô arå  storåd oî thå  disë  aó aî allocateä group®  Thå disë spacå reserveä foò  á giveî file¬ iî itó directorù entry¬ ió alwayó marked¬ identified¬ anä  allocateä  iî thå eveî multipleó oæ  thå  "allocatioî  grouð size". É  previouslù  mentioneä twï oldeò  operatinç  systemó  thaô supporteä  randoí filå I/Ï withiî thå confineó oæ á pre-allocateä file®  Thió  systeí  requireó thaô alì oæ thå spacå  foò  aî  "N¢ recorä filå bå reserveä aó contiguouó disë spacå eveî iæ thå filå onlù  containó  twï recordó (#° anä #N)®  Makinç á randoí  accesó filå biggeò thaî thå prå allocateä sizå waó virtuallù impossible® Thå  CP/Í  Veò  2.² randoí filå accesó systeí  haó  overcomå  thå problemó describeä above®  Á randoí filå undeò CP/Í containó onlù thå  numbeò  oæ  allocateä groupó requireä  tï  holä  thå  storeä Šrecords®  Thå  holeó  betweeî thå defineä recordó dï noô  consumå unuseä disë space. Iæ á filå undeò CP/Í ió createä witè onlù randoí recorä ° oæ thå  filå writteî theî thaô filå containó 12¸ byteó oæ reaì  datá anä  consumeó onå allocatioî grouð oæ disë space®  Thå allocatioî grouð consumeä alsï maù contaiî otheò adjacenô randoí recordó  tï filì ouô thå sizå oæ thå group®  Foò instance¬  oî singlå densitù 8¢  diskó  witè á 102´ bytå allocatioî grouð size¬  á onå  recorä (#0©  filå  woulä bå ablå tï bå writteî  witè  additionaì  recorä numberó  ± tï · withiî thå samå allocatioî group®  Likewiså iæ  á singlå recorä filå waó createä witè onlù recorä numbeò ¹ written¬ thaô  filå woulä consumå onlù onå allocatioî grouð oæ disë space® Additionaì recorä numberó 8¬  anä 1° tï 1µ coulä theî bå  writteî withouô requirinç additionaì disë space. RANDOM FILE I/O SYSTEM CALLS Leô uó nexô investigatå thå five BDOÓ systeí calló thaô CP/Í supportó  foò randoí I/Ï withiî files®  Thå charô oæ Figurå ±  oî thå  followinç  pagå  detailó thå looë oæ á  randoí  accesó  filå controì  block®  Notå thaô thå filå controì blocë containó  threå byteó aô thå enä thaô arå useä tï storå thå randoí recorä  numbeò thaô  wilì currentlù bå accessed®  Thå randoí accesó systeí calló alì  utilizå thió fielä tï determinå thå portioî oæ thå  filå  tï access at read/write time. Á  CP/Í  randoí  filå maù contaiî uð tï 64Ë recordó  oæ  12¸ byteó  numbereä froí ° tï 65535®  Twï byteó oæ thå  filå  controì blocë  holä thió recorä number¬  r° aó thå lo÷ bytå anä r± ás thå higè byte® Thió provideó accessabilitù tï recordó uð tï á maximuí filå  sizå oæ ¸ megabytes®  Thå r² bytå oæ thå filå controì blocë ió  noô useä excepô aó thå overflo÷ oò carrù ouô oæ thå r±  byte® Iæ  bytå  r²  eveò containó á valuå thaô ió non-zerï  thå  recorä numbeò ió beyonä thå enä oæ thå ¸ megabytå limiô foò thå file. Tï  accesó  á randoí file¬  iô musô firsô bå openeä  iî  thå normaì manneò witè thå "open¢ BDOÓ functioî call®  Iî thå caså oæ creatinç á ne÷ randoí filå thå makå filå BDOÓ calì ió  sufficienô iî  thaô thå thå resultó oæ thå makå operatioî arå equivalenô  tï thå opeî functioî oî á zerï lengtè file. READ RANDOM RECORD: Function 33. Thió  systeí  calì  ió  madå witè  thå  (DE©  registeò  paiò pointinç tï á 3¶ bytå filå controì block®  Byteó r0-r² arå set uð witè  thå  randoí  recorä  tï read®  Thå BDOÓ  theî  fetcheó  thå addresseä  recorä  froí  thå filå anä placeó iô  iî  thå  calleró recorä buffeò pointeä tï bù thå lasô seô buffeò addresó  functioî .pa Š Figurå 1® FILÅ CONTROÌ BLOCË 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 Šcall®  Thå r0-r² fieldó oæ thå filå controì blocë arå noô changeä aó  á  resulô oæ thå randoí reaä functioî sucè thaô á  subsequenô randoí reaä operatioî woulä reaä thå samå record® Thå randoí reaä function may return a number of error codes as described below: Error Codå  0°  - Thå randoí reaä  functioî  workeä  withouô           erroò and the user buffer contains the desired data. Error Codå 0± - Thå randoí reaä operatioî addresseó á recorä           thaô  ió  containeä  iî  á disë  allocatioî  grouð  noô           allocateä tï thå file®  Thió meanó thaô thå grouð fielä           numbeò sloô oæ thå appropriatå extenô oæ thå filå  thaô           shoulä contaiî thå recorä ió equaì tï 0. Error Codå  0³  - Thå randoí reaä operatioî  jusô  requesteä           requireä  thaô á differenô extenô descriptoò  directorù           entrù  haä  tï  bå opeî foò  thå  impendinç  operation¬           howeveò  prioò  tï openinç thå ne÷ extenô  thå  currenô           extenô coulä noô bå closeä duå tï disë read/onlù statuó           oò á disë change. Erroò  Codå  0´ - Thå randoí reaä operatioî  jusô  requesteä requireä  accesó tï aî extenô oæ thå filå thaô doeó noô           exist on the disk. Error Codå  0¶  - Thå randoí reaä operatioî  jusô  requesteä           requireä accesó tï á recorä numbeò beyonä thå boundó oæ           thå  disë  drive¬  iå  thå disë drivå ió  lesó  thaî  ¸           megabyteó   anä  thå  recorä  requesteä  ió  withiî  aî           allocatioî grouð beyonä thå enä oæ thå disk. WRITE RANDOM RECORD: Function 34. Thió  systeí  calì  ió  madå witè  thå  (DE©  registeò  paiò pointinç tï á 3¶ bytå filå controì block®  Byteó r0-r² arå set uð witè thå randoí recorä tï write®  Thå BDOÓ theî moveó thå datá iî thå  calleró  recorä  buffeò pointeä tï bù thå  lasô  seô  buffeò addresó  functioî calì tï thå addresseä recorä iî thå  file®  Thå r0-r²  fieldó  oæ  thå filå controì blocë arå noô  changeä  aó  á resulô oæ thå randoí writå functioî sucè thaô á subsequenô randoí writå  operatioî  woulä writå thå samå record®  Thå randoí  writå functioî maù returî á numbeò oæ erroò codeó aó describeä below: Error Codå  0°  - Thå randoí writå functioî  workeä  withouô           erroò anä thå useò buffeò containó thå desireä data. Error Codå  0³ - Thå randoí writå operatioî  jusô  requesteä           requireä  thaô á differenô extenô descriptoò  directorù           entrù  haä  tï  bå opeî foò  thå  impendinç  operation¬           howeveò  prioò  tï openinç thå ne÷ extenô  thå  currenô           extenô coulä noô bå closeä duå tï disë read/onlù statuó           oò á disë change. Š Error Codå  0µ - Thå randoí writå operatioî  jusô  requesteä           requireä  accesó tï aî extenô oæ thå filå thaô doeó noô           exisô oî thå disk®  Iî thå procesó oæ creatinç thå  ne÷           extenô thå disë directorù waó founä tï bå full. Error Codå  0¶  - Thå randoí writå operatioî jusô  requesteä           requireä accesó tï á recorä numbeò beyonä thå boundó oæ           thå  disë  drive¬  iå  thå disë drivå ió  lesó  thaî  ¸           megabyteó  anä  thå  recorä  requesteä  ió  withiî   aî           allocatioî grouð beyonä thå enä oæ thå disk. WRITE RANDOM RECORD WITH ZERO FILL: Function 40. Thió  systeí  calì  ió  madå witè  thå  (DE©  registeò  paiò pointinç tï á 3¶ bytå filå controì block®  Byteó r0-r² arå seô uð witè thå randoí recorä tï write®  Thå BDOÓ theî moveó thå datá iî thå  calleró  recorä buffer¬  pointeä tï bù thå lasô  seô  buffeò addresó functioî call¬  tï thå addresseä recorä iî thå file®  Thå r0-r²  fieldó  oæ  thå filå controì blocë arå noô  changeä  aó  á resulô oæ thå randoí writå functioî sucè thaô á subsequenô randoí filå operatioî woulä accesó thå samå record®  Iæ thå randoí writå operatioî  causeä  á ne÷ allocatioî grouð tï bå allocateä tï  thå filå  thå otheò recordó oæ thå samå blocë arå filleä witè  zeros® Thå  randoí writå witè zerï filì functioî maù returî á numbeò  oæ erroò  codeó identicaì tï thoså describeä foò functioî numbeò  3´ above. COMPUTE FILE SIZE: Function 35. Thió  systeí calì determineó thå numbeò oæ 12¸ bytå  recordó iî á filå anä setó thå numbeò oæ recordó intï thå r° anä r± byteó oæ  thå 3¶ bytå filå controì blocë addresseä bù thå (DE© registeò pair® Thå returneä sizå ió á virtuaì sizå iî thaô iæ thå filå waó createä bù randoí writå operationó anä thå filå containó  "holes¢ thå  filå  sizå  functioî doeó noô takå thå holeó  intï  account® Anotheò  waù oæ lookinç aô thió ió tï thinë oæ thió  functioî  aó returninç  á  recorä numbeò thaô ió onå greateò thaî thå  maximuí recorä numbeò currentlù iî thå file®  Iæ thå filå haä nï  "holes¢ oò  iô  haä beeî writteî iî thå conventionaì sequentiaì  fashion¬ theî  thå  filå sizå reporteä bù thió functioî ió thå  reaì  filå size® Thió functioî provideó á convenienô functioî oæ positioninç á filå aô itó enä sï thaô subsequenô sequentiaì oò randoí  updatå could be performed. SET RANDOM RECORD: Function 36: Thå  (DE©  registeò paiò ió seô tï poinô tï á 3¶  bytå  filå controì  blocë thaô haó previouslù beeî useä tï referencå á  filå Šiî thå sequentiaì mode®  Upoî referencå witè thió systeí calì thå r°  tï r² fieldó arå filleä iî witè thå randoí recorä numbeò thaô correspondó  tï  thå currenô filå position¬  iå thå  BDOÓ  simplù computeó thå reaì currenô recorä numbeò aó follows: Thå currenô extenô numbeò ió multiplieä bù 128¬  thå  numbeò      oæ  recordó  peò extent¬  anä tï thió producô ió  addeä  thå      numericaì  valuå  oæ thå CÒ field¬  currenô recorä  iî  thió      extent®  Thå finaì resulô ió placeä intï thå r0-r² fieldó oæ      the FCB. LOOKING AT SOME EXAMPLES Thå  followinç simplå assemblù languagå prograí ió  designeä tï  writå recorä numberó ° anä 14³ intï á filå oî thå  disk®  Thå writå  randoí functioî ió useä tï writå thå firsô recorä witè alì A's and the second record, # 143, with all B's. ; ; ;RANDOM RECORD I/O DEMONSTRATION FOR CP/M 2.2 ; ; THIS FIRST LEVEL DEMONSTRATION IS DESIGNED TO ; SHOW HOW TO INITIALLY SET UP A FILE TO BE A RANDOM FILE ; AND TO WRITE TWO RECORDS INTO THE FILE SUCH THAT THE ; FIRST RECORD (RECORD NUMBER 0) AND THE SEVENTEENTH ; RECORD OF THE SECOND EXTENT (RECORD NUMBER 143) BOTH ; CONTAIN DATA. THE PURPOSE IS TO DEMONSTRATE THE ; RESULTING DISK DIRECTORY ENTRIES THAT RESULT FROM ; AN INCOMPLETE FILE. THIS DEMO PROGRAM DOES NO RANDOM ; WRITE ERROR CHECKING. ; ; ;SYSTEM LEVEL INTERFACE EQUATES ; BDOS EQU 0005H ;SYSTEM INTERFACE VECTOR MAKE EQU 22 ;MAKE NEW FILE FUNCTION SBADDR EQU 26 ;SET DISK BUFFER ADDR OPEN EQU 15 ;OPEN FILE FUNCTION CLOSE EQU 16 ;FILE CLOSE FUNCTION DELETE EQU 19 ;DELETE FILE FUNCTION RRAND EQU 33 ;READ RANDOM FUNCTION WRAND EQU 34 ;WRITE RANDOM FUNCTION WRANDF EQU 40 ;WRITE RANDOM WITH 00 FILL ; ; ORG 0100H ;START OF A PROGRAM ; XRA A ;ZERO BYTES OF THE FCB STA EXT ;EXTENT FIELD STA CR ;CURRENT RECORD COUNT Š STA RR+2 ;AND THE R2 FIELD LXI H,0000H ;ALSO ZERO RANDOM RECORD FIELED SHLD RR ; LXI D,BUFFER ;SET DISK BUFFER ADDRESS MVI C,SBADDR CALL BDOS ; LXI D,RANDFCB ;POINT AT OUR FCB MVI C,DELETE ;ERASE TEST FILE IF IT ALREADY EXISTS CALL BDOS ; LXI D,RANDFCB ;MAKE A NEW FILE FOR TEST MVI C,MAKE CALL BDOS ; MVI A,'A' ;FILL FIRST RECORD WITH A'S CALL FILL ;GO FILL LXI H,0000H ;SET RECORD NUMBER TO WRITE A'S INTO SHLD RR LXI D,RANDFCB ;WRITE RECORD OF A'S MVI C,WRAND ;NORMAL WRITE RANDOM FUNCTION CALL BDOS ; MVI A,'B' ;FILL NEXT RECORD WITH B'S CALL FILL ;GO FILL LXI H,143 ;SET RECORD NUMBER TO WRITE B'S INTO SHLD RR LXI D,RANDFCB ;WRITE RECORD OF B'S MVI C,WRAND ;NORMAL WRITE RANDOM FUNCTION CALL BDOS ; LXI D,RANDFCB ;CLOSE JUST WRITTEN FILE MVI C,CLOSE CALL BDOS ; ; RET ;BACK TO CCP BY IMMEDIATE RETURN ; ; ;SUBROUTINE TO FILL BUFFER WITH A PATTERN ; ; ENTRY WITH (A) CONTAINING BYTE TO FILL BUFFER WITH ; FILL: LXI H,BUFFER ;POINT AT BUFFER FOR FILL MVI B,128 ;FILL BYTE COUNTER FILLP: MOV M,A ;PUT A BYTE INTO BUFFER INX H ;BUMP POINTER DCR B ;DECREMRNT BYTE COUNT JNZ FILLP ;CONTINUE TILL BUFFER FULL RET ; ; Š;RANDOM FILE TEST DATA AREA ; RANDFCB: DB 00 ;USE CURRENT LOGGED DRIVE FOR TEST DB 'RANDFILE' ;NAME OF FILE TO PLAY WITH DB 'TST' ;..AND THE EXTENSION NAME EXT: DB 00,00,00,00 ;EXTENT, S1, S2, AND FCBSZ BYTES DS 16 ;STORAGE FOR THE ALLOCATION NUMBERS CR: DS 1 ;CURRENT RECORD BYTE RR: DS 2 ;RANDOM RECORD NUMBER (R0,R1) DS 1 ;RANDOM RECORD OVERFLOW BYTE (R2) ; ; ;RANDOM DISK I/O DATA BUFFER ; BUFFER: DS 128 ;ONE RECORD BUFFER ; END Thå  abovå  prograí waó assembleä anä causeä tï  ruî  oî  aî emptù  singlå  densitù  disë  iî  thå  defaulô  disë  drive®  Thå followinç  displaù  showó ho÷ thå directorù upoî thå disë  lookeä afteò runninç thå program® Noticå thaô thå filå onlù consumeó twï allocateä groups®  Duå tï thå facô thaô thió waó á singlå densitù disë witè 102´ bytå allocatioî groupó oæ ¸ recordó each¬  theî iæ recorä  numbeò ¸ waó subsequentlù writteî thå  directorù  entrieó woulä  changå tï includå aî allocatioî blocë numbeò iî thå seconä grouð numbeò sloô oæ thå firsô extenô oæ thå file. G=00:00, T=2, S=1, PS=1 00 0052414E 4446494C 45545354 00000001 *.RANDFILETST....* 10 02000000 00000000 00000000 00000000 *................* 20 0052414E 4446494C 45545354 01000010 *.RANDFILETST....* 30 00030000 00000000 00000000 00000000 *................* 40 E5E5E5E5 E5E5E5E5 E5E5E5E5 E5E5E5E5 *eeeeeeeeeeeeeeee* 50 E5E5E5E5 E5E5E5E5 E5E5E5E5 E5E5E5E5 *eeeeeeeeeeeeeeee* 60 E5E5E5E5 E5E5E5E5 E5E5E5E5 E5E5E5E5 *eeeeeeeeeeeeeeee* 70 E5E5E5E5 E5E5E5E5 E5E5E5E5 E5E5E5E5 *eeeeeeeeeeeeeeee* Thå  followinç  twï sectoò displayó ofæ thå  singlå  densitù disë sho÷ thå A'ó anä B'ó writteî bù thå prograí above® Alì otheò sectoró  iî thå grouð numberó 0² anä 0³ werå empty¬  iå containeä whateveò datá thaô useä tï bå there®  Thió bringó uð thå  subjecô oæ  thå writå randoí witè zerï filì function®  Á smalì segmenô oæ .pa ŠG=02:00, T=2, S=17, PS=20 00 41414141 41414141 41414141 41414141 *AAAAAAAAAAAAAAAA* 10 41414141 41414141 41414141 41414141 *AAAAAAAAAAAAAAAA* 20 41414141 41414141 41414141 41414141 *AAAAAAAAAAAAAAAA* 30 41414141 41414141 41414141 41414141 *AAAAAAAAAAAAAAAA* 40 41414141 41414141 41414141 41414141 *AAAAAAAAAAAAAAAA* 50 41414141 41414141 41414141 41414141 *AAAAAAAAAAAAAAAA* 60 41414141 41414141 41414141 41414141 *AAAAAAAAAAAAAAAA* 70 41414141 41414141 41414141 41414141 *AAAAAAAAAAAAAAAA* G=03:07, T=3, S=6, PS=5 00 42424242 42424242 42424242 42424242 *BBBBBBBBBBBBBBBB* 10 42424242 42424242 42424242 42424242 *BBBBBBBBBBBBBBBB* 20 42424242 42424242 42424242 42424242 *BBBBBBBBBBBBBBBB* 30 42424242 42424242 42424242 42424242 *BBBBBBBBBBBBBBBB* 40 42424242 42424242 42424242 42424242 *BBBBBBBBBBBBBBBB* 50 42424242 42424242 42424242 42424242 *BBBBBBBBBBBBBBBB* 60 42424242 42424242 42424242 42424242 *BBBBBBBBBBBBBBBB* 70 42424242 42424242 42424242 42424242 *BBBBBBBBBBBBBBBB* thå  firsô demonstratioî prograí waó changeä tï causå thå  seconä writå operatioî tï bå donå witè zerï fill® Thå changeä portioî oæ the program is shown below: LXI D,RANDFCB ;WRITE RECORD OF A'S MVI C,WRAND ;NORMAL WRITE RANDOM FUNCTION CALL BDOS ; MVI A,'B' ;FILL NEXT RECORD WITH B'S CALL FILL ;GO FILL LXI H,143 ;SET RECORD NUMBER TO WRITE B'S INTO SHLD RR LXI D,RANDFCB ;WRITE RECORD OF B'S MVI C,WRANDF ;WRITE RANDOM ZERO FILL FUNCTION CALL BDOS ; LXI D,RANDFCB ;CLOSE JUST WRITTEN FILE Notå  froí  thå  directorù displaù belo÷ thaô  therå  ió  nï changå  iî thå appearancå oæ thå entrieó froí thå firsô  example® Thió timå thå onlù thinç thaô changeä waó thå datá iî  allocatioî grouð 3® Duå tï thå seconä writå thió allocatioî grouð containó á sectoò  oæ B'ó aô GROUP=03:0· witè thå otheò seveî sectoró oæ thå grouð  no÷ containinç zeroeó froí thå zerï  filì  operation®  Thå functioî  oæ  zerï  filì  ió tï leavå á cleaî  slatå  oî  recordó numberó  subsequentlù reaä froí thå samå  allocatioî  block®  Thå BDOÓ  ió  capablå oæ reportinç unwritteî recorä  informatioî  foò recordó  thaô corresponä tï grouð numbeò slotó iî  thå  directorù entrieó thaô contaiî á '00§ bytå indicatinç unallocated®  Howeveò Šoncå  á  grouð  ió  allocateä  foò onå  recorä  thå  BDOÓ  cannoô determinå  iæ  otheò sectoró oæ thaô grouð havå beeî  writteî  oò not®  Thuó  erï  functioî maù bå issueä wheî  creatinç  á  randoí accesó  filå  foò thå firsô time®  Thå programmeò maù theî uså  á recorä  oæ 12¸ zeroeó tï indicatå thaô thå recorä ió noô useä  aó opposeä  tï  accidentallù  mistakinç thå garbagå  datá  froí  un- initializeä sectoró writteî withouô zerï filì aó reaì data. G=00:00, T=2, S=1, PS=1 00 0052414E 4446494C 45545354 00000001 *.RANDFILETST....* 10 02000000 00000000 00000000 00000000 *................* 20 0052414E 4446494C 45545354 01000010 *.RANDFILETST....* 30 00030000 00000000 00000000 00000000 *................* 40 E5E5E5E5 E5E5E5E5 E5E5E5E5 E5E5E5E5 *eeeeeeeeeeeeeeee* 50 E5E5E5E5 E5E5E5E5 E5E5E5E5 E5E5E5E5 *eeeeeeeeeeeeeeee* 60 E5E5E5E5 E5E5E5E5 E5E5E5E5 E5E5E5E5 *eeeeeeeeeeeeeeee* 70 E5E5E5E5 E5E5E5E5 E5E5E5E5 E5E5E5E5 *eeeeeeeeeeeeeeee* Thå  nexô examplå prograí ió includeä herå tï sho÷ á  cleveò meanó  oæ  implementinç arbitrarù recorä selectioî I/Ï  withiî  á filå  withouô resortinç tï randoí filå I/O®  Thå intenô ió noô tï indicatå thaô thå followinç schemå ió thå preferreä  method®  Thå prograí  belo÷  waó  developeä witè thå CP/Í  Veò  1.´  operatinç systeí iî mind® Howeveò thå algorithí workó finå witè CP/Í 2.² aó well®  Thå  techniquå  useä tï plaù witè randoí recordó bù  usinç sequentiaì  reaä anä writå operationó ió tï manipulatå  thå  "cr¢ fielä oæ á standarä 3³ bytå filå controì block®  Thå "cr¢ bytå ió thå  onlù meanä thaô thå BDOÓ useó tï indicatå thå nexô recorä tï access®  Thå  programmeò maù changå thió bytå valuå tï forcå  thå BDOS to go to any record within the current extent. Iæ  thå  firsô  extenô  oæ  á  filå  ió  opened¬  thå  grouð allocatioî valueó foò thaô extenô liå iî thå filå controì  block® Iæ thå techniquå oæ performinç "youò own¢ randoí I/Ï ió done¬ thå codå  musô accesó recorä numberó noô tï excedå 07fè withouô firsô closinç thå currenô extenô anä openinç thå next® Thió caî bå donå witè  eitheò  thå conventionaì opeî anä closå operationó  oò  thå programmer¬  wheî  donå workinç witè thå currenô extenô maù  opeî nexô  automaticallù bù performinç á dummù reaä oæ recorä 080È  oæ thå currenô extent®  Thå programminç examplå belo÷ useó thå "rolì youò  own¢ techniquå buô doeó noô anticipatå á filå sizå  greateò than 16K (one extent size). Thå  prograí  belo÷ ió á skeletoî structurå oæ á  .COÍ  filå serializatioî procedure®  Thå ideá ió tï inserô á siø bytå seriaì numbeò  strinç  intï thå targeô filå PROG.COÍ oî  drivå  B:®  Thå seriaì  numbeò ió inserteä intï thå filå aô thå placeó  specifieä bù  thå labeló iî thå tablå aô thå starô oæ  thå  listing®  Theså valueó  arå strippeä ouô oæ thå symboì tablå thaô ió generateä aô thå  assemblù  oæ thå PROG.ASÍ file®  Iæ thå assembleò  doeó  noô generatå  á symboì tablå theî thå labeì valueó maù bå pulleä  ofæ thå .PRÎ listinç output®  Thå inserô pointó arå placeó withiî thå Š"tï  bå serialized¢ prograí wherå thå programmeò  haó  determineä thaô hå woulä likå tï placå thå seriaì numbeò string®  Withiî thå filå itself¬ thå labeló poinô tï thå placå wherå thå strinç ió tï bå inserteä witè respecô tï ruî timå loaä address®  Thå reaì filå offseô  ió  0100È byteó less®  Iî addition¬  thå schemå doeó  noô inserô  alì  siø  byteó  oæ thå prograí  seriaì  numbeò  aô  eacè location®  Thå  bytå aô eacè labeì addresó minuó onå  containó  á valuå  betweeî  ± anä ¶ oæ thenumbeò oæ seriaì numbeò byteó  thaô should actually be inserted at seralization time. Thå  lisô  oæ labeì valueó iî thå prograí belo÷ ió  useä  tï build¬  aô  assemblù time¬  á tablå oæ recorä numberó  wherå  thå specifiã seriaì numbeò stringó arå tï bå inserted®  Thió tablå ió theî  useä tï filì iî thå "cr¢ bytå oæ thå filå controì blocë  aó eacè seriaì numbeò ió tï bå inserted® Thå tablå alsï containó thå bytå offseô withiî thå recorä wherå thå inserô poinô ió tï start® Aó eacè seriaì numbeò ió tï bå inserteä thå appropriatå recorä ió read¬  thå numbeò ió inserteä (witè lengtè specifieä bù thå valuå froí  thå filå recorä jusô accessed)¬  anä thå recorä ió  writteî bacë  tï thå disk®  Sequentaiì reaä anä writå operationó arå useä foò  botè operations®  Logiã withiî thå codå listinç  belo÷  alsï provideó  foò  thå occurrancå thaô thå seriaì numbeò  strinç  maù crosó  thå enä oæ thå firsô recorä anä flo÷ intï thå nexô record® Iî  thió caså thå firsô ió rewritteî followeä bù readinç  oæ  thå nexô  witè  thå  remaindeò  oæ thå  inserô  proceedinç  froí  thå beginninç oæ thå seconä record® Pleaså  notå thaô thå prograí examplå ió giveî aó á skeletoî onlù anä thå seriaì numbeò entrù process¬  incremenô process¬ anä thå disë I/Ï erroò exiô pointó arå lefô foò thå reader/programmeò to fill in with code of his own choosing. .po0 ; ; ;PROGRAM SERIAL NUMBER INSERTION EQUATES ; EACH ADDRESS IS A VALUE INSIDE OF THE "PROG.COM" ; FILE THAT IS THE PLACE TO PUT THE SERIAL NUMBER. ; SERA EQU 0132H SERB EQU 01E9H SERC EQU 0278H SERD EQU 039AH SERE EQU 06FFH SERF EQU 0732H SERG EQU 0BBCH SERH EQU 0C08H ; ; ;CP/M BDOS SYSTEM CALLS FUNCTION NUMBERS ; BOOT EQU 0000H ;REBOOT LOCATION ENTRY POINT BDOS EQU 0005H ;BDOS FUNCTION ENTRY POINT RESET EQU 13 ;RESET DISK SYSTEM OPEN EQU 15 ;OPEN FILE FUNCTION ŠCLOSE EQU 16 ;CLOSE FILE FUNCTION DMAADR EQU 26 ;SET DATA BUFFER ADDRESS READ EQU 20 ;READ SEQUENTIAL WRITE EQU 21 ;WRITE SEQUENTIAL ; ; ;DEFINE BASE EXECUTION AREA FOR THIS PROGRAM ; START EQU 0100H ; ; ORG START ;BASE OF EXECUTION AREA ; ; ;START UP HERE WITH PROGRAM INITIALIZATION AND ;DEFINE PROCEDURE TO FETCH IN SERIAL NUMBER TO INSERT INTO ;THE FILE ; SERASK: ; ;ENTER APPROPIATE CODE HERE TO PUT A SIX BYTE SERIAL NUMBER ;INTO VARIABLE "SERSTR" ; ; ; ;SERIAL NUMBER INSERT POINT PROCESSING ; ; SERCOPY: MVI C,RESET ;RESET DISK SYSTEM UPON INSERT CALL BDOS LXI D,PROGFCB ;SET TO OPEN THE PROG.COM FILE MVI C,OPEN CALL BDOS INR A ;CHECK IF OPEN ERROR JNZ SERCP1 ;OPEN SO GO START WRITE ; ;PRINT ERROR MESSAGE HERE AS TO INDICATE THAT THE FILE ;"PROG.COM" IS NOT PRESENT ON DRIVE B:. ; JMP SERASK ;IF ERROR BACK TO GET A NEW SERIAL ;..NUMBER OR TO EXIT SERCP1: MVI B,00H ;INDEX COUNTER FOR TABLE VALUES SERIST: MOV L,B MVI H,00H DAD H ;DOUBLE TO WORDS LXI D,INSTAB ;INTO TABLE DAD D Š MOV A,M ;GET RECORD NUMBER FOR PLACE STA PROGFCB+32 ;SET TO READ THIS RECORD INX H MOV C,M ;GET BYTE LOCATION OF COUNTER PUSH B LXI D,PROGFCB ;USE PROG FCB TO READ MVI C,READ CALL BDOS ;GO READ SECTOR POP B ;INDEX TO LENGTH MOV L,C MVI H,0 LXI D,080H ;BASE OF DEFAULT BUFFER DAD D MOV C,M ;GET LENGTH INX H ;POINT TO NEXT BUFFER BYTE LXI D,SERSTR ;POINT (DE) TO SERIAL LOCATION ; MOVLP: MOV A,H ;SEE IF PAST THE END OF BUFFER CPI 01H JNZ SAMSEC ;STILL IN THE SAME SECTOR ; MVI H,0 ;RESET TO NEXT SECTOR BASE PUSH B PUSH H PUSH D LXI H,PROGFCB+32 ;DECREASE RECORD FOR WRITE DCR M LXI D,PROGFCB MVI C,WRITE ;WRITE LAST SECTOR CALL BDOS LXI D,PROGFCB MVI C,READ ;READ NEXT SECTOR CALL BDOS POP D POP H POP B ; SAMSEC: PUSH B LDAX D ;GET A SERIAL NUMBER BYTE MOV M,A ;AND SLAM INTO BUFFER POP B INX H INX D DCR C ;DONE ALL BYTES HERE YET JNZ MOVLP ; PUSH B LXI H,PROGFCB+32 ;SET BACK CURRENT RECORD FOR WRITE DCR M LXI D,PROGFCB MVI C,WRITE ;REWRITE THIS SECTOR CALL BDOS POP B Š INR B ;BUMP TABLE SCAN INDEX LDA TABLEN ;CHECK FOR DONE CMP B JNC SERIST ;GO FOR NEXT TABLE ENTRY ; ;PUT IN LOGIC HERE TO SPECIFY THE NEXT OF SEQUENTIAL SERIAL NUMBERS ;OR TO GO BACK TO THE TOP OF THE PROGRAM TO GET A NEW SERIAL NUMBER. ; ; ; ;PARAMETER DATA AREA FOR SERAL NUMBER PROGRAM ; ; ;"PROG.COM" FILE ACCESS CONTROL BLOCK ; PROGFCB: DB 'B'-040H ;DISK DRIVE B: ALL THE TIME DB 'PROG COM',0,0,0,0 DS 17 ;ALLOCATION SPACE ; ; ; ;SERIAL NUMBER INSERTION POINT REFERENCE TABLE ; INSTAB: DB ((SERA-0100H-1)/128) ;RECORD NUMBER DB ((SERA-0100H-1) AND 07FH) ;BYTE OFFSET DB ((SERB-0100H-1)/128) ;RECORD NUMBER DB ((SERB-0100H-1) AND 07FH) ;BYTE OFFSET DB ((SERC-0100H-1)/128) ;RECORD NUMBER DB ((SERC-0100H-1) AND 07FH) ;BYTE OFFSET DB ((SERD-0100H-1)/128) ;RECORD NUMBER DB ((SERD-0100H-) AND 07FH) ;BYTE OFFSET DB ((SERE-0100H-1)/128) ;RECORD NUMBER DB ((SERE-0100H-1) AND 07FH) ;BYTE OFFSET DB ((SERF-0100H-1)/128) ;RECORD NUMBER DB ((SERF-0100H-1) AND 07FH) ;BYTE OFFSET DB ((SERG-0100H-1)/128) ;RECORD NUMBER DB ((SERG-0100H-1) AND 07FH) ;BYTE OFFSET DB ((SERH-0100H-1)/128) ;RECORD NUMBER DB ((SERH-0100H-1) AND 07FH) ;BYTE OFFSET ; TABLEN: DB (($-INSTAB)/2)-1 ;NUMBER OF TABLE ENTRIES ; ;..MINUS 1 FOR LOOP EASE SERSTR: DS 10H ;PLACE TO KEEP BINARY SERIAL NUMBER ; ; END ; ; ;...END OF SERIAL NUMBER INSERT PROGRAM Š .po8 Thå  nexô  anä finaì examplå ió á fullù  functionaì  prograí thaô useó randoí recorä I/Ï undeò CP/Í 2.² tï perforí á  "useful¢ function®  Thå  prograí  mixeó  uð thå recordó oæ á  filå  iî  aî ordereä  yeô  bizarrå waù iî ordeò thaô thå filå contentó maù  bå encodeä   tï  prevenô  itó  uså  untiì  sucè  timå  thaô  iô   ió unscrambled®  Thå  unmixinç  procesó  ió alsï  performeä  bù  thå prograí below® Thå recordó oò "sectors¢ oæ thå filå arå mixeä anä unmixeä iî placå oî thå disë iî thaô thå disë filå ió noô copied® Randoí  accesó  filå I/Ï ió useä tï swað  recordó  directly®  Thå commenô blocë aô thå beginninç oæ thå prograí listinç containó aî explanatioî  oæ  thå  prograí  "intent¢  anä  thå  recorä  mixinç algorithí  chosen®  Operatioî oæ thå program¬  shoulä thå  readeò wisè tï utilizå thå encodinç anä decodinç functionó provided¬  ió alsï describeä iî thå listing. Thió  examplå prograí ió presenteä aó á workinç  examplå  oæ randoí  filå  I/Ï iî use®  Detaileä descriptioî oæ  thå  internaì workingó oæ thå prograí arå beyonä thå scopå oæ thió tutoriaì buô maù  bå  inferreä bù studyinç thå listinç anä readinç thå  ratheò prolifiã commenô statements® Foò readeró thaô woulä likå tï avoiä thå  aggravatioî  oæ typinç iî thå sourcå codå  foò  thå  prograí belo÷  oò foò thå otheò programó presenteä iî thió BDOÓ  tutoriaì series¬  Parô  É  iî  Lifelines¬  Novembeò 198² anä  Parô  IÉ  iî Lifelines¬  Januarù  1983¬  á machinå readablå copù oæ thå sourcå codå  fileó  oî  aî eighô incè singlå  densitù  diskettå  maù  bå obtaineä froí Michaeì J®  Karas¬  246¸ Hanseî Court¬ Simé Valley¬ Californiá 93065® Pleaså senä disketteó preformatted¬ labeleä anä iî  á returnablå maileò oæ somå sort®  Alsï includå eitheò stampó oò  moneù foò returî postagå (nï postagå meteò tapes¬  thoså  arå accepteä oî datå oæ printinç only© foò youò returî package. .pa Š.po0 ‚LISTINÇ FOÒ SECRET.ASÍ Á RANDOÍ I/Ï PROGRAÍ EXAMPLE ; ; ;RANDOM RECORD I/O DEMONSTRATION FOR CP/M 2.2 ; ; THIS THIRD LEVEL DEMONSTRATION PROGRAM IS DESIGNED TO ; DEMONSTRATE RANDOM FILES BY DEVELOPING A 'NOT NECESSARILY ; PRACTICAL' ALGORITHM FOR ENCODING A PROGRAM FILE ON A DISK. ; THE INTENT IS TO MAKE THE TRANSMISSION OF AN OBJECT FILE ; ARBITRARILY SCRAMBLED ON A 128 BYTE BY 128 BYTE RECORD BASIS ; SUCH THAT IF THE TRANSMITTED FILE, EITHER ON FLOPPY DISKETTE ; OR ON THE PHONE LINE WERE INTERCEPTED BY AN ILLICIT THIRD ; PARTY, THEN THE THIRD PARTY WOULD RECEIVE GARBAGE UNLESS ; HE HAD POSSESSION OF THE DECODING ALGORITHM. ; ; THIS PROGRAM WILL IMPLEMENT SUCH AN ALGORITHM IN BOTH AN ; ENCODING AND DECODING FORMAT. HERE IS THE ALGORITHM USED. ; (OBVIOUSLY DUE TO THE FACT THAT THIS APPEARS IN THE ; PUBLIC IMAGE AS A MAGAZINE ARTICLE WILL PREVENT THE FOLLOWING ; ALGORITHM TO BE OF 'SECRET' USE). ; ; THE OPERATOR ENTERS THE COMMAND TO RUN THE PROGRAM AS: ; ; A>SECRET filename.typ E ; ; where filename.typ is the ; file to encode. And "E" ; indicates to encode the file ; ; or: ; ; A>SECRET filename.typ D ; ; where filename.typ is the ; file to decode. And "D" ; indicates to decode the file ; ; THE ENCODING PROCESS WRITES THE ENCODED FILE RIGHT IN PLACE ; WITHIN THE USER SPECIFIED FILE. NO MEANS IS USED TO SPECIFY ; IN THE ENCODED FILE THAT IT IS ENCODED. ; ; THE DECODE PROCESS READS AND DECODES THE FILE RIGHT IN PLACE ; WITHIN THE USER SPECIFIED FILE NAME. ; ; THE ALGORITHM LEAVES THE FIRST RECORD OF THE FILE INTACT AND ; DOES NOT ENCODE THE PART OF A FILE BEYOND 128 RECORDS IN SIZE. ; FOR FILES LARGER THAN 128 RECORDS THE FINAL RECORDS BEYOND THE ; 128'TH ARE LEFT UNTOUCHED. THE BDOS IS CALLED TO DETERMINE THE ; SIZE OF THE FILE SO THE NUMBER OF RECORDS IN THE FILE ARE ; KNOWN. THIS NUMBER OF RECORDS WILL BE REFERRED TO HERE AS "NR". ; IF "NR" IS GREATER THAN 128 THEN "NR" IS SET TO 128. THEN THE ; FIRST "NR-1" BYTES OF THE FIRST RECORD ARE READ SEQUENTIALLY ; TO MAKE A LIST OF ONE BYTE BINARY NUMBERS WITH A NUMBER OF Š; ENTRIES EQUAL TO THE NUMBER OF RECORDS IN THE FILE MINUS ONE, ; UP TO A MAXIMUM OF 127 NUMBERS. ; ; THIS LIST IS THEN PROCESSED TO CONVERT ALL OF THE NUMBERS IN THE ; LIST TO BE WITHIN THE RANGE OF 1 TO "NR-1". THIS CONVERSION IS ; DONE BY FIRST "ANDING" EACH OF THE BYTES IN THE LIST WITH A MASK. ; THE MASK HAS A NUMERICAL VALUE EQUAL TO "NR-1" ROUNDED UP TO ; THE NEXT BIGGEST [(2 ^ N) - 1] VALUE, IE IF THE FILE HAS 5 ; RECORDS THE MASK IS 07H. IF THE FILE HAS 59 RECORDS THE MASK ; HAS A VALUE OF 3FH. THE LIST IS THEN SCANNED FOR VALUES THAT ; ARE GREATER THAN "NR-2". EACH VALUE THAT IS GREATER THAN ; "NR-2" IS DIVIDED BY TWO IGNORING THE REMAINDER. FINALLY EACH ; LIST VALUE IS INCREMENTED BY ONE TO MAKE A REAL FILE READABLE ; RECORD NUMBER. ; ; THE LIST IS THEN USED AS A RECORD SCRAMBLE/UNSCRAMBLE LIST. ; FOR SCRAMBLING IT IS SCANNED FROM THE BEGINNING WHILE ; UNSCRAMBLING SCANS THE LIST FROM THE END. SCRAMBLING PROCEDES ; AS FOLLOWS (THE UNSCRAMBLE PROCESS IS THE REVERSE): ; ; THE SECOND FILE RECORD IS NOW INTERCHANGED IN ; POSITION WITH THE RECORD POINTED BY THE FIRST ; NUMBER IN THE LIST. THE THIRD FILE RECORD IS ; INTERCHANGED WITH THE RECORD POINTED TO BY THE ; SECOND LIST VALUE. THIS PROCESS CONTINUES UNTIL ; THE END OF THE LIST. DURING THE PROCESS OF ; INTERCHANGING THE FILE SECTORS IN THIS RATHER ; BIZARRE MANNER, EACH TIME A LIST VALUE IS FOUND ; TO HAVE A LEAST SIGNIFICANT BIT THAT IS EQUAL ; TO "1" THEN THAT RECORD HAS EACH BYTE XOR'ED ; WITH THE RECORD NUMBER. ; ; WRITTEN BY: ; MICHAEL J. KARAS » 246¸ HANSEN COURT ; SIMI VALLEY, CA 93065 ; (805) 527-7922 ; ; ; ;SYSTEM LEVEL INTERFACE EQUATES ; BDOS EQU 0005H ;SYSTEM INTERFACE VECTOR MAKE EQU 22 ;MAKE NEW FILE FUNCTION SBADDR EQU 26 ;SET DISK BUFFER ADDR OPEN EQU 15 ;OPEN FILE FUNCTION CLOSE EQU 16 ;FILE CLOSE FUNCTION DELETE EQU 19 ;DELETE FILE FUNCTION RRAND EQU 33 ;READ RANDOM FUNCTION WRAND EQU 34 ;WRITE RANDOM FUNCTION WRANDF EQU 40 ;WRITE RANDOM WITH 00 FILL PRINT EQU 9 ;PRINT STRING TILL $ FSIZE EQU 35 ;COMPUTE FILE SIZE FUNCTION DEFCB EQU 05CH ;DEFAULT FILE CONTROL BLOCK DEFBUF EQU 080H ;DEFAULT BUFFER LOCATION Š; EXEC EQU 08000H ;EXECUTE SPOT FOR SMALL PROGRAM BOOT EQU 00000H ;SYSTEM REBOOT ENTRY POINT ; ; ;ASCII CHARACTER DEFINITIONS ; CR EQU 0DH ;CARRIAGE RETURN LF EQU 0AH ;LINE FEED ; ; ORG 0100H ;START OF A PROGRAM LXI SP,STACK ;SETUP A STACK FOR EXECUTION LXI D,SNGMSG ;PRINT SIGNON MESSAGE MVI C,PRINT CALL BDOS ; ; ;CHECK IF THERE WAS A COMMAND LINE FILE NAME ; LDA DEFCB+1 ;IF FIRST BYTE 20 THEN NO NAME CPI ' ' JZ CMDERR ;IF NO FILE NAME PRINT ERROR LDA DEFCB+17 ;GET OPTION CHARACTER CPI 'E' ;CHECK FOR ENCODE JZ PROCESS ;GO TO PROCESS IF ENCODE CPI 'D' ;CHECK IF DECODE JZ PROCESS ;GO PROCESS OF DECODE ; CMDERR: LXI D,ERRM1 ;PRINT ERROR MESSAGE MVI C,PRINT CALL BDOS JMP BOOT ;EXIT IF NO FILE NAME OR OPTION ; ; ;HERE IF AN ENTRY FILE NAME AND A VALID OPTION ; PROCESS: STA OPTION ;SAVE OPTION CHAR FOR LATER ;...REFERENCE XRA A ;SETUP FCB FOR OPEN STA DEFCB+12 ;ZERO EXTENT BYTE STA DEFCB+32 ;ZERO CURRENT RECORD BYTE STA DEFCB+35 ;ZERO R2 BYTE LXI H,0000H SHLD DEFCB+33 ;ZERO RANDOM RECORD NUMBER ; MVI C,OPEN ;OPEN FILE USER SPECIFIED LXI D,DEFCB ;USE DEFAULT FCB BUILT BY CCP CALL BDOS ;GO ATTEMPT OPEN INR A ;CHECK IF FOUND JNZ FOUND ; MVI C,PRINT ;PRINT NOT FOUND ERROR Š LXI D,ERRM2 CALL BDOS JMP BOOT ;EXIT ; ; ;FOUND FILE SO LETS NEXT COMPUTE ITS FILE SIZE ; FOUND: LXI D,DEFCB ;THAT SAME FCB AGAIN MVI C,FSIZE CALL BDOS ;GET THE FILES SIZE IN RECORDS LHLD DEFCB+33 ;GET SIZE OF THE FILE MOV A,H ;CHECK IF GREATER THAN 128 RECORDS ORA A JNZ TOBIG MOV A,L ORA A ;CHECJ IF FILE EMPTY OR ONLY ONE RECORD JZ TOSMALL CPI 1 JZ TOSMALL CPI 129 JC SIZINA ;WE HAVE SIZE IN (A) TOBIG: MVI A,128 ;SET SIZE TO 128 DEFAULT SIZINA: STA NR ;SAVE NUMBER OF RECORDS JMP READFST ; TOSMALL: MVI C,PRINT ;PRINT FILE SIZE ERROR MESSAGE LXI D,ERRM3 CALL BDOS JMP BOOT ; ; ;READ FIRST RECORD INTO LIST BUFFER ; READFST: LXI D,LIST ;SET DMA ADDRESS TO LIST BUFFER MVI C,SBADDR CALL BDOS LXI H,0000H ;SET FIRST RECORD SHLD DEFCB+33 XRA A STA DEFCB+35 ;CLEAR R2 BYTE MVI C,RRAND ;READ RANDOM FIRST RECORD LXI D,DEFCB CALL BDOS ;NO NEED TO CHECK READ ERROR BECAUSE ;..WE KNOW THAT THESE RECORDS EXIST ; ; ;HERE TO PROCESS LIST INTO A SET OF NUMBERS THAT FIT OUT FILE ;RECORD COUNT RANGE. ; LDA NR ;FETCH NUMBER OF RECORDS Š DCR A ;SET NR-1 ; MVI B,0FFH ;INITIAL MASK VALUE MVI C,07H ;NUMBER OF TIMES TO ROTATE FOR MASK ; MKLP: RAL ;CHECK FOR ZERO BIT IN NR-1 JC HMSK ;EXIT WE HAVE OUR MASK ONE BIT FROM (A) PUSH PSW MOV A,B ;PUT A ZERO BIT INTO MASK ORA A ;CLEAR CARRY RAR ;PUT ZERO IN MOV B,A POP PSW DCR C ;DEBUMP SHIFT COUNT JNZ MKLP ; HMSK: ;HERE IF (B) HAS LIST MASK VALUE LDA NR ;GET NUMBER OF VALUES IN LIST DCR A MOV C,A ;PUT LOOP COUNTER INTO (C) MOV D,A ;SAVE NR-1 IN (D) LXI H,LIST ;POINT AT LIST LSTPROC: MOV A,M ;GET A LIST BYTE ANA B ;MASK IT CMP D ;IS RESULT GREATER THAN NR-2 JC VALOK ;VALUE IS OK ORA A ;DIVIDE BY TWO IF TOO BIG RAR VALOK: INR A ;SET VALUES TP FOR REAL RECORD NUMBERS MOV M,A ;PUT CONVERTED NUMBER INTO LIST AGAIN INX H ;BUMP LIST POINTER DCR C ;DEC LOOP COUNTER JNZ LSTPROC ;DO ALL BYTES OF LIST ; ; ;ENCODE/DECODE THE FILE HERE ; ENCODE: LXI H,LIST ;KEEP A POINTER TO THE LIST LDA OPTION ;IF OPTION IS 'E' WE GO FORWARD CPI 'E' MVI A,1 ;DEFAULT FORWARD CURRENT RECORD JZ FORWA ;GO FORWARD LDA NR ;INDEX TO END OF LIST FOR DECODE DCR A ;SET START RECORD FOR DECODE MOV E,A DCR E ;ZERO BASE INDEX MVI D,0 DAD D ; FORWA: SHLD LISTP ;SAVE LIST POINTER Š STA CURR ;SET CURRENT RECORD NUMBER TO START LDA NR DCR A STA CNTR ;SET NUMBER OF SWAPS ; ENCLP: LXI D,BUF1 ;SET BUFFER ONE AS DMA ADDRESS MVI C,SBADDR CALL BDOS LDA CURR ;READ CURRENT RECORD MOV L,A MVI H,00 SHLD DEFCB+33 ;SET RECORD NUMBER LXI D,DEFCB MVI C,RRAND ;READ THAT RECORD CALL BDOS ORA A ;CHECK ERROR JNZ DSKERR ; LXI D,BUF2 ;SET BUFFER 2 AS DMA ADDRESS MVI C,SBADDR CALL BDOS LHLD LISTP ;GET SWAP POSITION MOV L,M MVI H,00 SHLD DEFCB+33 ;SET SWAP RECORD NUMBER LXI D,DEFCB MVI C,RRAND ;READ SWAP RECORD CALL BDOS ORA A ;CHECK ERROR JNZ DSKERR ; LHLD LISTP ;IS SWAP RECORD AN ODD NUMB MOV B,M ;SABE XOR PATTERN IN (B) MOV A,M RAR JNC SWRT ;GO DO SWAP WRITE DIRECTLY IF EVEN LDA OPTION ;WHICH BUFFER TO XOR LXI H,BUF2 ;DEFAULT FOR 'E' CPI 'E' JZ INB2 ;USE BUFFER 2 LXI H,BUF1 ;IF DECODE USE BUFFER 1 INB2: MVI C,128 ;BUTE COUNT OF XOR XORLP: MOV A,M ;GET A BYTE TO XOR XRA B MOV M,A ;PUT BYTE BACK INX H ;BUMP BUFFER POINTER FOR XORING DCR C ;DEC BYTE COUNT JNZ XORLP ; SWRT: LXI D,BUF1 ;SET BUFFER ONE AS DMA ADDRESS MVI C,SBADDR Š CALL BDOS LHLD LISTP ;GET SWAP POSITION MOV L,M MVI H,00 SHLD DEFCB+33 ;SET SWAP RECORD NUMBER LXI D,DEFCB MVI C,WRAND ;WRITE SWAP RECORD CALL BDOS ORA A ;CHECK ERROR JNZ DSKERR ; LXI D,BUF2 ;SET BUFFER 2 AS DMA ADDRESS MVI C,SBADDR CALL BDOS LDA CURR ;WRITE CURRENT RECORD MOV L,A MVI H,00 SHLD DEFCB+33 ;SET RECORD NUMBER LXI D,DEFCB MVI C,WRAND ;WRITE THAT RECORD CALL BDOS ORA A ;CHECK ERROR JNZ DSKERR ; LDA CURR ;FETCH LOOP PARMS MOV B,A LHLD LISTP ; LDA OPTION ;CHECK OPTION CPI 'E' JZ INCF ;IF ENCODE INCR FORWARD ; DECB: DCX H ;DECREMENT DOWN THROUGH LOOP DCR B JMP PSVE ;SAVE PARMS INCF: INX H INR B PSVE: SHLD LISTP ;SAVE NEW LIST POSITION MOV A,B STA CURR ; LDA CNTR ;FETCH LOOP COUNTER DCR A STA CNTR JNZ ENCLP ;GO TO LOOP TO PROCESS MORE IF ;NOT DONE YET ; ; ;HERE WE ARE DONE WRITING SO LETS CLOSE UP AND GO HOME ; LXI D,DEFCB MVI C,CLOSE Š CALL BDOS INR A ;CHECK ERROR CODE JZ DSKERR ; MVI C,PRINT ;PRINT DONE MESSAGE LXI D,DONMSG CALL BDOS JMP BOOT ;EXIT ; ; ;EXIT POINT WITH ERROR MESSAGE IF THE DISK WRITE OPERATION ;RESULTED IN AN ERROR ; DSKERR: LXI D,ERRM4 ;PRINT GARBAGE FILE ERROR MVI C,PRINT CALL BDOS JMP BOOT ;EXIT FOR THE POOR GUY ; ; ;PROGRAM OPERATIONAL MESSAGES ; SNGMSG: DB CR,LF,'MICRO RESOURCES Disk File Scramble and' DB CR,LF,'Unscramble Utility Designed to Demonstrate' DB CR,LF,'CP/M Ver 2.2 Random Record I/O. (1/24/82)','$' ; DONMSG: DB CR,LF,'File Processing Complete','$' ; ERRM1: DB CR,LF,'No File Name Specified or Improper Option','$' ; ERRM2: DB CR,LF,'Specified File Not Found','$' ; ERRM3: DB CR,LF,'Cannot Process Files with 0 or 1 Record(s)','$' ; ERRM4: DB CR,LF,'File I/O Error, This Error Should NOT Normally' DB CR,LF,'Happen, But the File is now Garbaged...','$' ; ; ;PROGRAM DATA STORAGE SECTION ; OPTION: DS 1 ;PLACE TO STORE COMMAND LINE OPTION CHAR ; NR: DS 1 ;NUMBER OF RECORDS TO SWAP ; CNTR: DS 1 ;ENCODE/DECODE LOOP COUNTER ; ŠCURR: DS 1 ;CURRENT SWAP SECTOR ; LISTP: DS 2 ;LIST SCAN POINTER ; LIST: DS 128 ;LIST BUFFER ; BUF1: DS 128 ;DATA BUFFER 1 ; BUF2: DS 128 ;DATA BUFFER 2 ; DS 36 STACK EQU $ ;USER STACK AREA ; ; END ; ; ;+++...END OF FILE