home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / DRI-archive / roche / AFTER8B.TXT < prev    next >
Internet Message Format  |  2009-12-11  |  27KB

  1. From: "French Luser" <Bill.Ga...@microsoft.com>
  2. Newsgroups: comp.os.cpm
  3. References: <419f187a$0$7241$8fcfb975@news.wanadoo.fr>
  4. Subject: Re: AFTER8 File Format
  5. Date: Wed, 24 Nov 2004 10:51:21 +0100
  6. X-Priority: 3
  7. X-MSMail-Priority: Normal
  8. X-Newsreader: Microsoft Outlook Express 6.00.2800.1158
  9. X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1165
  10. Lines: 1007
  11. Message-ID: <41a45904$0$9082$8fcfb975@news.wanadoo.fr>
  12. Organization: les newsgroups par Wanadoo
  13. NNTP-Posting-Host: 81.248.43.163
  14. X-Trace: 1101289733 news.wanadoo.fr 9082 81.248.43.163:13514
  15. X-Complaints-To: abuse@wanadoo.fr
  16.  
  17. AFTER8B.TXT  by Emmanuel ROCHE
  18. -----------
  19.  
  20. Looking after 8 segments: a demo, at last!
  21.  
  22. Ok.   So,  last  time,  I  published  a  BASIC   program  (named
  23. AFTER8.BAS) used to concatenate 2 CP/M-86  (Plus) ComManD  files
  24. with 4 segments (and  relocating the  Auxiliary segments  in the
  25. resulting  CMD  file  Header  Record), producing  a file  with 8
  26. segments.
  27.  
  28. But this  was (unfortunately)  pretty hypothetical,  with 2  CMD
  29. files filled with ASCII characters... (Even if it proved that it
  30. could be automated).
  31.  
  32. Since I am a programmer, I decided that a good demo was needed.
  33.  
  34. Just  by  coincidence,  a  few days  ago, I  published a  SYSVAR
  35. utility (displaying the contents  of the  "System Variables"  of
  36. CP/M-86 Plus) in the comp.os.cpm Newsgroup.
  37.  
  38. Looking at it, I wondered if such a small utility could not be a
  39. good basis for an AFTER8 demo?
  40.  
  41. So, I first made a version of this utility with  the "logic"  of
  42. the  program  in  the  Extra  segment,   and  still   using  the
  43. subroutines  in  the Code  segment, and  some Data  in the  Data
  44. segment.
  45.  
  46. After a few massages, it finally run. So, it could be the  basis
  47. for the demo.
  48.  
  49. Time to think to the AFTER8 file format.
  50.  
  51. So,  those  files  have  8 segments:  Code, Data,  Extra, Stack,
  52. Auxiliary #1, Auxiliary #2, Auxiliary #3, and Auxiliary #4.
  53.  
  54. In any program, there is usually some subroutines needed. So,  I
  55. deciced to put them in the Code segment.
  56.  
  57. (Before going any further, I must  also explain  that I  am also
  58. working on the DOIT Compiler (a compiler written in Turbo Pascal
  59. Version 3.01A, running under CP/M 2.2, CP/M-86, and MS-DOS). So,
  60. when I say: "the program", I  was also  thinking: "the  Run-Time
  61. System of any Compiler"...  Once DOIT  will be  done, I  plan to
  62. produce a DIY Compiler, with some features that I would  like to
  63. have under CP/M-86 Plus. Back to AFTER8.)
  64.  
  65. Some subroutines  in the  Code segment  usually need  to display
  66. some strings on the  console. So,  the Data  segment is  used to
  67. store those.
  68.  
  69. Just to show that the following demo has  an Extra  segment (you
  70. will remember that, previously, this Extra segment contained the
  71. "logic" of a program), I simply filled it with a string and some
  72. ASCII characters.
  73.  
  74. Regarding the Stack segment,  so far  none of  my CMD  files for
  75. CP/M-86 Plus has needed one. But, for the demo, I added a string
  76. and some ASCII characters to fill it.
  77.  
  78. Now, we have a conventional CP/M-86 Compact Memory Model ComManD
  79. file, with the 4 usual segments: Code, Data,  Extra, and  Stack.
  80. But where is the program?
  81.  
  82. At the beginning, I just wanted  to present  you a  demo with  a
  83. little program in the Auxiliary #1 segment.  But, upon  thinking
  84. about  it,  it  seemed  that a  demo involving  the 4  Auxiliary
  85. segments would be more demonstrative.
  86.  
  87. Since I was wondering where all this would lead me, I decided to
  88. "keep it simple, stupid": do it the simplest way possible.
  89.  
  90. So, I simply retyped the "logic" of the SYSVAR program  4 times,
  91. one in each Auxiliary segment. Now, how to know which  Auxiliary
  92. segment  is  being processed?   So, I  added a  "X1", "X2",  etc
  93. string after the title.
  94.  
  95. Now, let us talk about RTS: most compilers have a RTS. Some  are
  96. external  (CRUN  for  CBASIC),  but most  are integral  into the
  97. command files produced by the compiler. Turbo Pascal's RTS is in
  98. the first 2K of any command file produced.
  99.  
  100. The big problem, for the compiler writer, is the details  of the
  101. RTS, and how to generate a command file.
  102.  
  103. In this case, I decided that the first ComManD file processed by
  104. AFTER8.BAS would contain the RTS of a future compiler.
  105.  
  106. That's mean that the RTS is a totally separate CMD file.
  107.  
  108. Since this future compiler don't exist  yet, that  meant that  I
  109. had to produce by hand a demo "program"  (as explained  above, I
  110. chose to run 4 times the "logic" of SYSVAR).
  111.  
  112. Note that (as explained  in my  previous message),  there are  4
  113. Auxiliary segments, but only one Code  segment... Since  RTS are
  114. typically smaller than the "program" produced  by any  compiler,
  115. it follows that it is more logical to  use the  Code segment  to
  116. store  the  RTS,  and  the  4  Auxiliary segments  to store  the
  117. program.
  118.  
  119. At the moment, I am thinking  to load  those Auxiliary  segments
  120. without gaps between them  (SID-86 shows  that GENCMD  fills the
  121. "slack  bytes"  between segments  with 00h  -- this  could be  a
  122. useful  feature  that  the  RTS  could  exploit, for  example by
  123. excluding any "opcode" of its program to run to be  00h. If  the
  124. RTS  was  to encounter  a 00h  byte in  the "program",  it would
  125. simply  loop  to  the  next  "opcode"  -- until  the end  of the
  126. Auxiliary  segments),  but  the  demo was  made with  4 separate
  127. Auxiliary segments. This obliged me to  introduce 3  commands to
  128. update the Auxiliary segments, in this particular case.
  129.  
  130. Whew! So much talking for a  down-to-heart demo!   Time to  show
  131. something: here is what  is displayed  on screen  when the  demo
  132. ComMand file  produced by  AFTER8 is  run (the  previous message
  133. showed an AFTER8 session):
  134.  
  135. A>demo
  136.  
  137. System Variables (X1)
  138. ----------------
  139. Console Width: 80
  140. Console Page Length: 24
  141. Console Page Mode: OFF
  142. System Ticks per Second: 60
  143. Temporary File Drive: @
  144. Date: 04F3
  145. Time: 21:26:06
  146. 8087 Present: TRUE
  147. Program ID: 00
  148. Drive Search Chain: @
  149. In the Background: FALSE
  150. Number of Running Processes: 01
  151. Foreground Ratio: 16
  152.  
  153. Press ENTER to Continue
  154.  
  155. System Variables (X2)
  156. ----------------
  157. Console Width: 80
  158. Console Page Length: 24
  159. Console Page Mode: OFF
  160. System Ticks per Second: 60
  161. Temporary File Drive: @
  162. Date: 04F3
  163. Time: 21:26:07
  164. 8087 Present: TRUE
  165. Program ID: 00
  166. Drive Search Chain: @
  167. In the Background: FALSE
  168. Number of Running Processes: 01
  169. Foreground Ratio: 16
  170.  
  171. Press ENTER to Continue
  172.  
  173. System Variables (X3)
  174. ----------------
  175. Console Width: 80
  176. Console Page Length: 24
  177. Console Page Mode: OFF
  178. System Ticks per Second: 60
  179. Temporary File Drive: @
  180. Date: 04F3
  181. Time: 21:26:09
  182. 8087 Present: TRUE
  183. Program ID: 00
  184. Drive Search Chain: @
  185. In the Background: FALSE
  186. Number of Running Processes: 01
  187. Foreground Ratio: 16
  188.  
  189. Press ENTER to Continue
  190.  
  191. System Variables (X4)
  192. ----------------
  193. Console Width: 80
  194. Console Page Length: 24
  195. Console Page Mode: OFF
  196. System Ticks per Second: 60
  197. Temporary File Drive: @
  198. Date: 04F3
  199. Time: 21:26:11
  200. 8087 Present: TRUE
  201. Program ID: 00
  202. Drive Search Chain: @
  203. In the Background: FALSE
  204. Number of Running Processes: 01
  205. Foreground Ratio: 16
  206.  
  207. So, as you can see, this is the output of my SYSVAR utility, but
  208. with the titles lines saying that there were 4 copies  in the  4
  209. Auxiliary segments. Let us now see what constitute the "program"
  210. (the second CMD file processed by AFTER8):
  211.  
  212. ; DIYPGM.A86
  213. ; ----------
  214. ;
  215. ; CP/M-86 Plus -- DIYPGM.CMD
  216. ;
  217. ; Programmed by:
  218. ;
  219. ; Mr Emmanuel ROCHE
  220. ; Chemin de Boisrond
  221. ; 17430 Tonnay-Charente
  222. ; FRANCE
  223. ;
  224. ; Demo PGM for DIY Compiler
  225. ; (This one done by hand.)
  226. ;
  227. ; Generation:
  228. ; A>ASM DIYPGM! GENCMD DIYPGM
  229. ;
  230. ;--------------------------------
  231. ; AFTER8 Memory Model.
  232. ; (Compact Memory model without ORG 0100h after DSEG.)
  233. ;
  234.  CSEG                    ; Will become X1 Segment
  235.         DSEG                    ; Will become X2 Segment
  236.         ESEG                    ; Will become X3 Segment
  237.         SSEG                    ; Will become X4 Segment
  238. ;
  239. ;---------------------------------
  240. ; Equates of Subroutines in DIYRTS.
  241. ;
  242. ; Note that we could use other names,
  243. ; and that this demo does NOT check
  244. ; the validity of the number...
  245. ;
  246. Chk_CPMP EQU     0
  247. Bak_CPMP EQU     1
  248. Pr_Seg_ES EQU 2
  249. Pr_Wor_AX EQU 3
  250. Pr_Byt_AL EQU 4
  251. Pr_Nib_AL EQU 5
  252. Con_Out_DL EQU 6
  253. Ret_Opc  EQU 7
  254. Txt_Eol  EQU 8
  255. New_Line EQU 9
  256. Eol_Txt  EQU 10
  257. Txt  EQU 11
  258. Pr_Dec_AL EQU 12
  259. Pr_Dec_BX EQU 13
  260. Get_SCB  EQU 14
  261. Dis_Width EQU 15
  262. Dis_Length EQU 16
  263. Dis_Mode EQU 17
  264. Dis_Ticks EQU 18
  265. Dis_Temp EQU 19
  266. Dis_Date EQU 20
  267. Dis_Time EQU 21
  268. Dis_8087 EQU 22
  269. Dis_ProgID EQU 23
  270. Dis_DsChain EQU 24
  271. Dis_Back EQU 25
  272. Dis_NRproc EQU 26
  273. Dis_Fore EQU 27
  274. Dis_Penter      EQU     28
  275. Set_Segment_X2  EQU     29
  276. Set_Segment_X3  EQU     30
  277. Set_Segment_X4  EQU     31
  278. ;
  279. ;--------------------------------
  280.  CSEG $
  281. ;--------------------------------
  282.         DB      ' CP/M-86 Plus --   X1 Segment   '
  283. Program_X1:
  284.         DB      Chk_CPMP,       'Requires CP/M-86 Plus to run$'
  285. Doit_X1:
  286.         DB      Eol_Txt,        'System Variables (X1)$'
  287.         DB      Eol_Txt,        '----------------$'
  288.         DB      Dis_Width,      'Console Width: $'
  289.         DB      Dis_Length,     'Console Page Length: $'
  290.  DB Dis_Mode,       'Console Page Mode: $'
  291.         DB      Dis_Ticks,      'System Ticks per Second: $'
  292.         DB      Dis_Temp,       'Temporary File Drive: $'
  293.         DB      Dis_Date,       'Date: $'
  294.         DB      Dis_Time,       'Time: $'
  295.  DB Dis_8087,       '8087 Present: $'
  296.  DB Dis_ProgID,     'Program ID: $'
  297.  DB Dis_DsChain,    'Drive Search Chain: $'
  298.  DB Dis_Back,       'In the Background: $'
  299.         DB      Dis_NRproc,     'Number of Running Processes: $'
  300.  DB Dis_Fore,       'Foreground Ratio: $'
  301.         DB      Dis_Penter
  302.  DB Set_Segment_X2
  303. ;
  304. ;--------------------------------
  305.         DSEG    $
  306. ;--------------------------------
  307.         DB      ' CP/M-86 Plus --   X2 Segment   '
  308. Program_X2:
  309.         DB      Eol_Txt,        'System Variables (X2)$'
  310.         DB      Eol_Txt,        '----------------$'
  311.         DB      Dis_Width,      'Console Width: $'
  312.         DB      Dis_Length,     'Console Page Length: $'
  313.  DB Dis_Mode,       'Console Page Mode: $'
  314.         DB      Dis_Ticks,      'System Ticks per Second: $'
  315.         DB      Dis_Temp,       'Temporary File Drive: $'
  316.         DB      Dis_Date,       'Date: $'
  317.         DB      Dis_Time,       'Time: $'
  318.  DB Dis_8087,       '8087 Present: $'
  319.  DB Dis_ProgID,     'Program ID: $'
  320.  DB Dis_DsChain,    'Drive Search Chain: $'
  321.  DB Dis_Back,       'In the Background: $'
  322.         DB      Dis_NRproc,     'Number of Running Processes: $'
  323.  DB Dis_Fore,       'Foreground Ratio: $'
  324.         DB      Dis_Penter
  325.  DB Set_Segment_X3
  326. ;
  327. ;--------------------------------
  328.         ESEG    $
  329. ;--------------------------------
  330.         DB      ' CP/M-86 Plus --   X3 Segment   '
  331. Program_X3:
  332.         DB      Eol_Txt,        'System Variables (X3)$'
  333.         DB      Eol_Txt,        '----------------$'
  334.         DB      Dis_Width,      'Console Width: $'
  335.         DB      Dis_Length,     'Console Page Length: $'
  336.  DB Dis_Mode,       'Console Page Mode: $'
  337.         DB      Dis_Ticks,      'System Ticks per Second: $'
  338.         DB      Dis_Temp,       'Temporary File Drive: $'
  339.         DB      Dis_Date,       'Date: $'
  340.         DB      Dis_Time,       'Time: $'
  341.  DB Dis_8087,       '8087 Present: $'
  342.  DB Dis_ProgID,     'Program ID: $'
  343.  DB Dis_DsChain,    'Drive Search Chain: $'
  344.  DB Dis_Back,       'In the Background: $'
  345.         DB      Dis_NRproc,     'Number of Running Processes: $'
  346.  DB Dis_Fore,       'Foreground Ratio: $'
  347.         DB      Dis_Penter
  348.  DB Set_Segment_X4
  349. ;
  350. ;--------------------------------
  351.         SSEG    $
  352. ;--------------------------------
  353.         DB      ' CP/M-86 Plus --   X4 Segment   '
  354. Program_X4:
  355.         DB      Eol_Txt,        'System Variables (X4)$'
  356.         DB      Eol_Txt,        '----------------$'
  357.         DB      Dis_Width,      'Console Width: $'
  358.         DB      Dis_Length,     'Console Page Length: $'
  359.  DB Dis_Mode,       'Console Page Mode: $'
  360.         DB      Dis_Ticks,      'System Ticks per Second: $'
  361.         DB      Dis_Temp,       'Temporary File Drive: $'
  362.         DB      Dis_Date,       'Date: $'
  363.         DB      Dis_Time,       'Time: $'
  364.  DB Dis_8087,       '8087 Present: $'
  365.  DB Dis_ProgID,     'Program ID: $'
  366.  DB Dis_DsChain,    'Drive Search Chain: $'
  367.  DB Dis_Back,       'In the Background: $'
  368.         DB      Dis_NRproc,     'Number of Running Processes: $'
  369.  DB Dis_Fore,       'Foreground Ratio: $'
  370.         DB      New_Line
  371.         DB      Bak_CPMP
  372. ;
  373. ;--------------------------------
  374. ;
  375.  END
  376.  
  377. No  doubt  about it:  this program  contains absolutely  no Code
  378. subroutines. It is just 4 copies of a program expressed  as byte
  379. opcodes, with the strings corresponding to each "command".
  380.  
  381. So, if the "program" is so simple, how is the RTS?
  382.  
  383. ; DIYRTS.A86
  384. ; ----------
  385. ;
  386. ; CP/M-86 Plus -- DIYRTS.CMD
  387. ;
  388. ; Programmed by:
  389. ;
  390. ; Mr Emmanuel ROCHE
  391. ; Chemin de Boisrond
  392. ; 17430 Tonnay-Charente
  393. ; FRANCE
  394. ;
  395. ; Demo RTS for DIY Compiler
  396. ; (Using AFTER8 Segments.)
  397. ;
  398. ; Generation:
  399. ; A>ASM DIYRTS! GENCMD DIYRTS
  400. ;
  401. ;--------------------------------
  402. ; Compact Memory model.
  403. ;
  404.  CSEG
  405.         DSEG
  406.         ORG     001Bh
  407. X1base DW 0000h           ; X1 Segment in Base Page
  408.  ORG 0021h
  409. X2base DW 0000h           ; X2 Segment in Base Page
  410.  ORG 0027h
  411. X3base DW 0000h           ; X3 Segment in Base Page
  412.  ORG 002Dh
  413. X4base DW 0000h           ; X4 Segment in Base Page
  414.         ORG     0100h
  415.         ESEG
  416.         SSEG
  417. ;
  418. ;---------------------------------
  419.         DSEG    $
  420. ;---------------------------------
  421. ; Who?
  422. ;
  423.         DB      '                '
  424.         DB      '      _  _      '
  425.         DB      '    ( o  o )    '
  426.         DB      '+-oOOo-()-oOOo-+'
  427.         DB      '|              |'
  428.         DB      '|Emmanuel ROCHE|'
  429.         DB      '|              |'
  430.         DB      '|  was here... |'
  431.         DB      '|              |'
  432.         DB      '| .oooO  Oooo. |'
  433.         DB      '+-(   )--(   )-+'
  434.         DB      '   \ (    ) /   '
  435.         DB      '    \_)  (_/    '
  436.         DB      '                '
  437.         DB      '                '
  438.         DB      '                '
  439. ;
  440. ;--------------------------------
  441.  CSEG $
  442. ;--------------------------------
  443. ; We use BP to get command bytes (from X1),
  444. ; and DI to execute those commands (in CS).
  445. ;
  446.  MOV AX, X1base ; Get Segment of X1
  447.         MOV     ES, AX          ;
  448. Xseg_Loop:                      ; (Demo)
  449.  MOV BP, 0020h ; Init Offset of X1 (Demo)
  450. Main_Loop:
  451.  MOV     AL, ES:[BP]     ;
  452.  CBW   ; Make it a word
  453.  SHL AX, 1  ; * 2, as it is a word
  454.  MOV DI, AX  ; Make it an address
  455.         CALL    Sub_Tab [DI]    ; = ON xx GOSUB
  456.  INC BP              ; Increment X1:BP
  457.         JMPS    Main_Loop       ; = GOTO Main_Loop
  458. ;
  459. ;--------------------------------
  460.  DSEG $
  461. ;--------------------------------
  462. Sub_Tab: ; Table of Subroutines
  463. ;
  464. Chk_CPMP EQU     0! DW      Sub_Chk_CPMP
  465. ;
  466. Bak_CPMP EQU     1! DW      Sub_Bak_CPMP
  467. ;
  468. Pr_Seg_ES EQU 2! DW Sub_Pr_Seg_ES
  469. ;
  470. Pr_Wor_AX EQU 3! DW Sub_Pr_Wor_AX
  471. ;
  472. Pr_Byt_AL EQU 4! DW Sub_Pr_Byt_AL
  473. ;
  474. Pr_Nib_AL EQU 5! DW Sub_Pr_Nib_AL
  475. ;
  476. Con_Out_DL EQU 6! DW Sub_Con_Out_DL
  477. ;
  478. Ret_Opc  EQU 7! DW Sub_Ret_Opc
  479. ;
  480. Txt_Eol  EQU 8! DW Sub_Txt_Eol
  481. ;
  482. New_Line EQU 9! DW Sub_Eol
  483. ;
  484. Eol_Txt  EQU 10! DW Sub_Eol_Txt
  485. ;
  486. Txt  EQU 11! DW Sub_Txt
  487. ;
  488. Pr_Dec_AL EQU 12! DW Sub_Pr_Dec_AL
  489. ;
  490. Pr_Dec_BX EQU 13! DW Sub_Pr_Dec_BX
  491. ;
  492. Get_SCB  EQU 14! DW Sub_Get_SCB
  493. ;
  494. Dis_Width EQU 15! DW Sub_Dis_Width
  495. ;
  496. Dis_Length EQU 16! DW Sub_Dis_Length
  497. ;
  498. Dis_Mode EQU 17! DW Sub_Dis_Mode
  499. ;
  500. Dis_Ticks EQU 18! DW Sub_Dis_Ticks
  501. ;
  502. Dis_Temp EQU 19! DW Sub_Dis_Temp
  503. ;
  504. Dis_Date EQU 20! DW Sub_Dis_Date
  505. ;
  506. Dis_Time EQU 21! DW Sub_Dis_Time
  507. ;
  508. Dis_8087 EQU 22! DW Sub_Dis_8087
  509. ;
  510. Dis_ProgID EQU 23! DW Sub_Dis_ProgID
  511. ;
  512. Dis_DsChain EQU 24! DW Sub_Dis_DsChain
  513. ;
  514. Dis_Back EQU 25! DW Sub_Dis_Back
  515. ;
  516. Dis_NRproc EQU 26! DW Sub_Dis_NRproc
  517. ;
  518. Dis_Fore EQU 27! DW Sub_Dis_Fore
  519. ;
  520. Dis_Penter      EQU     28!     DW      Sub_Dis_Penter
  521. ;
  522. Set_Segment_X2 EQU 29! DW Sub_Set_Segment_X2
  523. ;
  524. Set_Segment_X3 EQU 30! DW Sub_Set_Segment_X3
  525. ;
  526. Set_Segment_X4 EQU 31! DW Sub_Set_Segment_X4
  527. ;
  528. ;-------------------------------- Start of Subroutines
  529.  CSEG $
  530. ;-------------------------------- 0
  531. Sub_Chk_CPMP:
  532. ;
  533.         MOV CL, 12! INT 224
  534.         CMP AX, 1031h! JNE Abort
  535.  MOV BP, 003Eh! JMP Main_Loop  ; (BP = Demo)
  536. ;
  537. ; Print "Requires CP/M-86 Plus to run" on console.
  538. ;
  539. Abort:
  540.         CALL Sub_Eol_Txt
  541.         CALL Sub_Eol
  542. ;
  543. ;................................ 1
  544. Sub_Bak_CPMP:
  545. ;
  546. ; Returns to CP/M-86 Plus.
  547. ;
  548.  MOV CL, 0! INT 224
  549. ;
  550. ;-------------------------------- 2
  551. Sub_Pr_Seg_ES:
  552. ;
  553. ; Print "Seg:Off" from ES:BX.
  554. ;
  555.  PUSH BX
  556.  MOV AX, ES! CALL Sub_Pr_Wor_AX
  557.  MOV DL, ':'! CALL Sub_Con_Out_DL
  558.  POP AX
  559. ;
  560. ;................................ 3
  561. Sub_Pr_Wor_AX:
  562. ;
  563. ; Print AX in hex ("1234").
  564. ;
  565.  PUSH AX
  566.  MOV AL, AH! CALL Sub_Pr_Byt_AL
  567.  POP AX
  568. ;
  569. ;................................ 4
  570. Sub_Pr_Byt_AL:
  571. ;
  572. ; Print AL in hex ("12").
  573. ;
  574.  PUSH AX
  575.  MOV CL, 4! SHR AL, CL! CALL Sub_Pr_Nib_AL
  576.  POP AX
  577. ;
  578. ;................................ 5
  579. Sub_Pr_Nib_AL:
  580. ;
  581. ; Intel trick circa 1972-1973?
  582. ;
  583.  AND AL, 0Fh
  584.  ADD AL, 90h
  585.  DAA
  586.  ADC AL, 40h
  587.  DAA
  588.  MOV DL, AL
  589. ;
  590. ;................................ 6
  591. Sub_Con_Out_DL:
  592. ;
  593. ; "Cooked mode" output one char to console.
  594. ;
  595.  PUSH BX
  596.  MOV CL, 2! INT 224
  597.  POP BX
  598. ;
  599. ;................................ 7
  600. Sub_Ret_Opc:
  601. ;
  602. ; After much thinking, I finally make this RET a subroutine...
  603. ; (It will be used by keywords producing nothing.)
  604. ;
  605.  RET
  606. ;
  607. ;-------------------------------- 8
  608. Sub_Txt_Eol:
  609. ;
  610. ; In : String$
  611. ; Out: Sends String, cr, lf to console.
  612. ;
  613.         CALL    Sub_Txt
  614. ;
  615. ;................................ 9
  616. Sub_Eol:
  617. ;
  618. ; In : None
  619. ; Out: Sends cr, lf to console.
  620. ;
  621.  PUSH BX
  622.  MOV DL, 0Dh! MOV CL, 2! INT 224
  623.  MOV DL, 0Ah! MOV CL, 2! INT 224
  624.  POP BX
  625.  RET
  626. ;
  627. ;-------------------------------- 10
  628. Sub_Eol_Txt:
  629. ;
  630. ; In : String$
  631. ; Out: Sends cr, lf, String to console.
  632. ;
  633.         CALL    Sub_Eol
  634. ;
  635. ;................................ 11
  636. Sub_Txt:
  637. ;
  638. ; In : String$
  639. ; Out: Sends String to console.
  640. ;      (One character at a time, to update BP.)
  641. ;
  642.         INC BP! MOV AL, ES:[BP]
  643.         CMP AL, '$'! JE Sub_Ret_Opc
  644.             MOV DL, AL! CALL Sub_Con_Out_DL
  645.             JMPS Sub_Txt
  646. ;
  647. ;-------------------------------- 12
  648. Sub_Pr_Dec_AL:
  649. ;
  650. ; Print Dec number 00-99 from AL.
  651. ;
  652.  DSEG $
  653. ;
  654. num DB 'Ok'
  655. ;
  656.  CSEG $
  657. ;
  658.  XOR AH, AH
  659.  AAM
  660.  ADD AX, 3030h
  661.  MOV WORD PTR num, AX
  662.  MOV  DL, BYTE PTR num+1! CALL Sub_Con_Out_DL
  663.  MOV  DL, BYTE PTR num+0! JMP  Sub_Con_Out_DL
  664. ;
  665. ;-------------------------------- 13
  666. Sub_Pr_Dec_BX:
  667. ;
  668. ; Print binary number 0-65535 from BX.
  669. ;
  670.  PUSH  BX ; Save value
  671.  MOV CX, 10000! CALL Adjust
  672.  MOV CX, 1000! CALL Adjust
  673.  MOV CX, 100! CALL Adjust
  674.  MOV CX, 10! CALL Adjust
  675.  ADD DL, '0'! CALL Sub_Con_Out_DL
  676.  MOV BYTE PTR SuLeZe, 00h  ; = Suppress Leading Zeroes (Default)
  677.  PUSH BX ; Restore value
  678.  RET  ; Done
  679. ;
  680.  DSEG $
  681. ;
  682. SuLeZe DB 00h ;  00h (false) = Suppress Leading Zeroes
  683.    ; 0FFh (true ) = Display  Leading Zeroes
  684. ;
  685.  CSEG $
  686. ;
  687. Adjust:
  688.  MOV DH, 0FFh ; = -1
  689. Adjust_1:
  690.  SUB BX, CX  ;
  691.  INC DH  ;
  692.  JNC Adjust_1 ; Repeat if no Borrow
  693.  ADD BX, CX  ; Add divisor
  694.  MOV DL, DH  ;
  695.  PUSH BX  ;
  696.  MOV BX, OFFSET SuLeZe
  697.  CMP [BX], AL ; Suppress Leading Zeroes?
  698.  JNE Adjust_2 ;
  699.  MOV DL, ' '  ;
  700.  CALL Sub_Con_Out_DL ;
  701.  JMPS Adjust_3 ;
  702. Adjust_2:
  703.  MOV BYTE PTR SuLeZe, 0FFh  ; Display Leading Zeroes
  704.  ADD DL, '0'  ;
  705.  CALL Sub_Con_Out_DL ;
  706. Adjust_3:
  707.  POP BX  ;
  708.  RET   ; Done
  709. ;
  710. ;-------------------------------- 14
  711. Sub_Get_SCB:
  712. ;
  713. ; In : Number of SCB variables to get.
  714. ; Out: SCBPB filled.
  715. ;
  716.         PUSH AX! PUSH BX! PUSH CX! PUSH DX
  717.  MOV DX, OFFSET SCBnum! MOV CL, 49! INT 224
  718.         POP DX! POP CX! POP BX! POP AX
  719.         RET
  720. ;
  721.         DSEG    $
  722. ;
  723. ; System Control Block Parameter Block
  724. ;
  725. SCBnum DB 00h  ; Number of SCB variables
  726.  DB 00h  ; 00=Get (FF=Set)
  727. SCBvar DB 00h  ; Get SCB variable here
  728. ;
  729. ; Additional values returned, depending upon SCBnum.
  730. ;
  731. date2 DB 00h  ; Date 2nd byte
  732. hour DB 00h  ; Time: Hours
  733. min DB 00h  ; Time: Minutes
  734. sec DB 00h  ; Time: Seconds
  735. ;
  736.         CSEG    $
  737. ;
  738. ;-------------------------------- 15
  739. Sub_Dis_Width:
  740. ;
  741. ; In : String$
  742. ; Out: Sends cr, lf, "Console Width: 80" to console.
  743. ;
  744.  CALL Sub_Eol_Txt
  745.  MOV SCBnum, 0! CALL Sub_Get_SCB
  746.  MOV AL, SCBvar! INC AL! JMP Sub_Pr_Dec_AL
  747. ;
  748. ;-------------------------------- 16
  749. Sub_Dis_Length:
  750. ;
  751. ; In : String$
  752. ; Out: Sends cr, lf, "Console Page Length: 24" to console.
  753. ;
  754.  CALL Sub_Eol_Txt
  755.  MOV SCBnum, 1! CALL Sub_Get_SCB
  756.  MOV AL, SCBvar! INC AL! JMP Sub_Pr_Dec_AL
  757. ;
  758. ;-------------------------------- 18
  759. Sub_Dis_Mode:
  760. ;
  761. ; In : String$
  762. ; Out: Sends cr, lf, "Console Page Mode: OFF" to console.
  763. ;
  764.  CALL Sub_Eol_Txt
  765.  MOV SCBnum, 2! CALL Sub_Get_SCB
  766.  MOV AL, SCBvar
  767. ;
  768.  DSEG $
  769. ;
  770. On DB 'ON$'
  771. Off DB 'OFF$'
  772. ;
  773.  CSEG $
  774. ;
  775. ; Displays ON or OFF if AL = 00h or 0FFh.
  776. ; (Note that this is the reverse of binary logic...)
  777. ; (Maybe it is a joke: OFF = 0FFh?)
  778. ;
  779. Sub_On_Off:
  780.  CMP AL, -1! JE Sub_Off
  781. Sub_On:
  782.  MOV DX, OFFSET On! JMP Sub_Pstring
  783. Sub_Off:
  784.  MOV DX, OFFSET Off
  785. Sub_Pstring:
  786.         MOV CL, 9! INT 224
  787.         RET
  788. ;
  789. ;-------------------------------- 18
  790. Sub_Dis_Ticks:
  791. ;
  792. ; In : String$
  793. ; Out: Sends cr, lf, "System Ticks per Second: 60" to console.
  794. ;
  795.  CALL Sub_Eol_Txt
  796.  MOV SCBnum, 3! CALL Sub_Get_SCB
  797.  MOV AL, SCBvar! JMP Sub_Pr_Dec_AL
  798. ;
  799. ;-------------------------------- 19
  800. Sub_Dis_Temp:
  801. ;
  802. ; In : String$
  803. ; Out: Sends cr, lf, "Temporary File Drive: @" to console.
  804. ;
  805.  CALL Sub_Eol_Txt
  806.  MOV SCBnum, 4! CALL Sub_Get_SCB
  807.  MOV AL, SCBvar! ADD AL, 40h, MOV DL, AL! JMP Sub_Con_Out_DL
  808. ;
  809. ;-------------------------------- 20
  810. Sub_Dis_Date:
  811. ;
  812. ; In : String$
  813. ; Out: Sends cr, lf, "Date: 04DC" to console.
  814. ;
  815.  CALL Sub_Eol_Txt
  816.  MOV SCBnum, 5! CALL Sub_Get_SCB
  817.  MOV AX, WORD PTR SCBvar! JMP Sub_Pr_Wor_AX
  818. ;
  819. ;-------------------------------- 21
  820. Sub_Dis_Time:
  821. ;
  822. ; In : String$
  823. ; Out: Sends cr, lf, "Time: 12:34:56" to console.
  824. ;
  825.  CALL Sub_Eol_Txt
  826.  MOV SCBnum, 5! CALL Sub_Get_SCB
  827.  MOV AL, hour! CALL Sub_Pr_Byt_AL
  828.  MOV DL, ':'! CALL Sub_Con_Out_DL
  829.  MOV AL, min! CALL Sub_Pr_Byt_AL
  830.  MOV DL, ':'! CALL Sub_Con_Out_DL
  831.  MOV AL, sec! JMP Sub_Pr_Byt_AL
  832. ;
  833. ;-------------------------------- 22
  834. Sub_Dis_8087:
  835. ;
  836. ; In : String$
  837. ; Out: Sends cr, lf, "8087 Present: TRUE" to console.
  838. ;
  839.  CALL Sub_Eol_Txt
  840.  MOV SCBnum, 128! CALL Sub_Get_SCB
  841.  MOV AL, SCBvar
  842. ;
  843.  DSEG $
  844. ;
  845. True DB 'TRUE$'
  846. False DB 'FALSE$'
  847. ;
  848.  CSEG $
  849. ;
  850. ; Displays TRUE or FALSE if AL = 0FFh or 00h.
  851. ;
  852. Sub_True_False:
  853.  CMP AL, -1! JNE Sub_False
  854. Sub_True:
  855.  MOV DX, OFFSET True! JMP Sub_Pstring
  856. Sub_False:
  857.  MOV DX, OFFSET False! JMP Sub_Pstring
  858. ;
  859. ;-------------------------------- 23
  860. Sub_Dis_ProgID:
  861. ;
  862. ; In : String$
  863. ; Out: Sends cr, lf, "Program ID: 01" to console.
  864. ;
  865.  CALL Sub_Eol_Txt
  866.  MOV SCBnum, 129! CALL Sub_Get_SCB
  867.  MOV AL, SCBvar! JMP Sub_Pr_Dec_AL
  868. ;
  869. ;-------------------------------- 24
  870. Sub_Dis_DsChain:
  871. ;
  872. ; In : String$
  873. ; Out: Sends cr, lf, "Drive Search Chain: A, B, C, D" to console.
  874. ;
  875.  CALL Sub_Eol_Txt
  876.  MOV SCBnum, 135! CALL Sub_Get_SCB
  877.  MOV AL, SCBvar! ADD AL, 40h! MOV DL, AL! CALL Sub_Con_Out_DL
  878.  CMP date2, -1! JE DsChain_Abort
  879.  CALL DsChain_Sep
  880.  MOV AL, date2! ADD AL, 40h! MOV DL, AL! CALL Sub_Con_Out_DL
  881.  CMP hour, -1! JE DsChain_Abort
  882.  CALL DsChain_Sep
  883.  MOV AL, hour! ADD AL, 40h! MOV DL, AL! CALL Sub_Con_Out_DL
  884.  CMP min, -1! JE DsChain_Abort
  885.  CALL DsChain_Sep
  886.  MOV AL, min! ADD AL, 40h! MOV DL, AL! CALL Sub_Con_Out_DL
  887. DsChain_Abort:
  888.  RET
  889. ;
  890.  DSEG $
  891. ;
  892. Comma DB ', $'
  893. ;
  894.  CSEG $
  895. ;
  896. DsChain_Sep:
  897.  MOV DX, OFFSET Comma! JMP Sub_Pstring
  898. ;
  899. ;-------------------------------- 25
  900. Sub_Dis_Back:
  901. ;
  902. ; In : String$
  903. ; Out: Sends cr, lf, "In the Background: FALSE" to console.
  904. ;
  905.  CALL Sub_Eol_Txt
  906.  MOV SCBnum, 136! CALL Sub_Get_SCB
  907.  MOV AL, SCBvar! JMP Sub_True_False
  908. ;
  909. ;-------------------------------- 26
  910. Sub_Dis_NRproc:
  911. ;
  912. ; In : String$
  913. ; Out: Sends cr, lf, "Number of Running Processes: 01" to console.
  914. ;
  915.  CALL Sub_Eol_Txt
  916.  MOV SCBnum, 137! CALL Sub_Get_SCB
  917.  MOV AL, SCBvar! JMP Sub_Pr_Dec_AL
  918. ;
  919. ;-------------------------------- 27
  920. Sub_Dis_Fore:
  921. ;
  922. ; In : String$
  923. ; Out: Sends cr, lf, "Foreground Ratio: 16" to console.
  924. ;
  925.  CALL Sub_Eol_Txt
  926.  MOV SCBnum, 138! CALL Sub_Get_SCB
  927.  MOV AL, SCBvar! JMP Sub_Pr_Dec_AL
  928. ;
  929. ;-------------------------------- 28
  930. Sub_Dis_Penter:
  931. ;
  932. ; Sends cr, lf, "Press ENTER to Continue " to console.
  933. ;
  934.         DSEG    $
  935. ;
  936. Penter  DB      13, 10
  937.         DB      13, 10, 'Press ENTER to Continue $'
  938. ;
  939.         CSEG    $
  940. ;
  941.  MOV DX, OFFSET Penter! MOV CL, 9! INT 224
  942.         MOV CL, 1! INT 224
  943.         JMP Sub_Eol
  944. ;
  945. ;-------------------------------- 29
  946. Sub_Set_Segment_X2:
  947. ;
  948.  MOV AX, X2base! MOV ES, AX
  949.  JMP Xseg_Loop
  950. ;
  951. ;-------------------------------- 30
  952. Sub_Set_Segment_X3:
  953. ;
  954.  MOV AX, X3base! MOV ES, AX
  955.  JMP Xseg_Loop
  956. ;
  957. ;-------------------------------- 31
  958. Sub_Set_Segment_X4:
  959. ;
  960.  MOV AX, X4base! MOV ES, AX
  961.  JMP Xseg_Loop
  962. ;
  963. ;-------------------------------- End of Subroutines
  964.         ESEG    $
  965. ;--------------------------------
  966. ;
  967.         DB      ' CP/M-86 Plus --'
  968.         DB      ' Extra Segment  '
  969.  DB ' !"#$%&'
  970.  DB 27h
  971.  DB '()*+,-./'
  972.  DB '0123456789:;<=>?'
  973.  DB '@ABCDEFGHIJKLMNO'
  974.  DB 'PQRSTUVWXYZ[\]^_'
  975.  DB '`abcdefghijklmno'
  976.  DB 'pqrstuvwxyz{|}~'
  977. ;
  978. ;--------------------------------
  979.         SSEG    $
  980. ;--------------------------------
  981. ;
  982.         DB      ' CP/M-86 Plus --'
  983.         DB      ' Stack Segment  '
  984.  DB ' !"#$%&'
  985.  DB 27h
  986.  DB '()*+,-./'
  987.  DB '0123456789:;<=>?'
  988.  DB '@ABCDEFGHIJKLMNO'
  989.  DB 'PQRSTUVWXYZ[\]^_'
  990.  DB '`abcdefghijklmno'
  991.  DB 'pqrstuvwxyz{|}~'
  992. ;
  993. ;--------------------------------
  994. ;
  995.  END
  996.  
  997. Well... As far as I know,  this is  the first  published program
  998. using AFTER8 segments (also called "Compact Memory Model" in the
  999. DRI CP/M-86 manuals).
  1000.  
  1001. Of course, this is just a "quick and dirty" little demo.
  1002.  
  1003. A real RTS would,  for example,  check if  X1base is  zero, then
  1004. print a "Error: RTS  alone, without  any program  to execute..."
  1005. message, etc, etc. (The (Demo) show  places where  modifications
  1006. were needed because of the string "X1 Segment" etc, used to show
  1007. the  beginning  of  the  segments.  Else,  BP =  0 points  to be
  1008. beginning  of  each  Auxiliary  segments  (but   this  is   less
  1009. visible...).)
  1010.  
  1011. Now  that  you  know  how to  run a  256K program  under CP/M-86
  1012. (Plus), "the sky, the limit"! Personally,  I wouldn't  mind some
  1013. Internet utilities...
  1014.  
  1015. A>That's all, folks!
  1016.  
  1017. Yours Sincerely,
  1018. "French Luser"
  1019.  
  1020.  
  1021. EOF
  1022.