home *** CD-ROM | disk | FTP | other *** search
/ POINT Software Programming / PPROG1.ISO / basic / bmag / psp.bas < prev    next >
Encoding:
BASIC Source File  |  1994-04-26  |  11.4 KB  |  348 lines

  1. '─ Area: F-QUICKBASIC ─────────────────────────────────────────────────────────
  2. '  Msg#: 364                                          Date: 17 Apr 94  17:19:00
  3. '  From: Saul Ansbacher                               Read: Yes    Replied: No 
  4. '    To: Larry Thacker                                Mark:                     
  5. '  Subj: PSP, EXE name and thi 1/3
  6. '──────────────────────────────────────────────────────────────────────────────
  7. 'Well here is a programme call PSP (that's the bit of memory you were
  8. 'talking about it's the Programme Segment Prefix) Compile this little
  9. 'programme and run it (give it a case SENSITIVE command line for fun) and
  10. 'then have a look at the display. There should be every thing you need
  11. 'here. Also there are some other nice things like case sensitive command
  12. 'lines, and the C$ function is a REALLY good idea check it out. ALso
  13. 'there are the dox, called psp.doc, I hope all this helps... as for you
  14. 'question there are lots of DIR$ routines out there, if you don't find
  15. 'one or someone else doesn't post on then let me know and I'll post one
  16. 'of the bunch I have... Oh, PSP.BAS needs QB.LIB or QBX.LIB...
  17.  
  18. '
  19. ' PSP.BAS by Brent Ashley, needs QB.LIB (QB4n) or QBX.LIB (PDS)
  20. '
  21. DECLARE FUNCTION C$ (Fore%, Back%)
  22. DECLARE FUNCTION CurPspSegment% ()
  23. DECLARE FUNCTION Hex2$ (Num%)
  24. DECLARE FUNCTION Hex4$ (Num%)
  25. DECLARE FUNCTION ProgramSpec$ (PSP AS ANY)
  26. DECLARE SUB LoadPSPVar (PSPSeg%, PSPVar AS ANY)
  27. DECLARE SUB MemCopy (FSeg%, FOfs%, FCnt%, TSeg%, TOfs%, TCnt%)
  28. DECLARE SUB ShowFCB (FCB AS ANY)
  29. DECLARE SUB ShowPSP (PSP AS ANY)
  30.  
  31. 'Uncomment for compiled version and delete MemCopy SUB:
  32. 'DECLARE SUB MemCopy ALIAS "B$ASSN" (BYVAL FSeg%, BYVAL FOfs%, BYVAL FCnt%,_
  33. '                                    BYVAL TSeg%, BYVAL TOfs%, BYVAL TCnt%)
  34. 'this is a routine internal to BCOM45.LIB - using it will
  35. 'result in a smaller program and speed up the memory copies
  36.  
  37. DEFINT A-Z
  38. '$INCLUDE: 'qb.bi'
  39.  
  40. ' user-defined types
  41.  
  42. TYPE UnopenedFCBType
  43.   DriveNum AS STRING * 1
  44.   FileName AS STRING * 8
  45.   Ext AS STRING * 3
  46.   CurBlk AS INTEGER
  47.   RecSize AS INTEGER
  48. END TYPE
  49.  
  50. TYPE PSPType
  51.   Int20 AS STRING * 2
  52.   TopOfMemory AS INTEGER
  53.   Junk1 AS STRING * 6
  54.   TermIP AS INTEGER
  55.   TermCS AS INTEGER
  56.   BreakIP AS INTEGER
  57.   BreakCS AS INTEGER
  58.   CritErrIP AS INTEGER
  59.   CritErrCS AS INTEGER
  60.   ParentPSPSeg AS INTEGER
  61.   HandleTable AS STRING * 20
  62.   EnvSeg AS INTEGER
  63.   Junk3 AS STRING * 4
  64.   HandleCnt AS INTEGER
  65.   HdlTblOfs AS INTEGER
  66.   HdlTblSeg AS INTEGER
  67.   Junk4 AS STRING * 36
  68.   FCB1 AS UnopenedFCBType
  69.   FCB2 AS UnopenedFCBType
  70.   Junk5 AS STRING * 4
  71.   CmdLen AS STRING * 1
  72.   CmdLine AS STRING * 127
  73. END TYPE
  74.  
  75. ' declare variables:
  76.  
  77. DIM SHARED Regs AS RegType, Fg, Bg, Hi
  78. DIM PSP AS PSPType, ParentPSP AS PSPType
  79.  
  80. ' set up colors
  81. DEF SEG = 0
  82. IF PEEK(&H449) = 7 THEN
  83.   ' monochrome
  84.   Fg = 7: Bg = 0: Hi = 15
  85. ELSE
  86.   ' colour
  87.   Fg = 11: Bg = 1: Hi = 14
  88. END IF
  89.  
  90. ' Do that funky PSP thang!
  91.  
  92. ' fill PSP variable with current PSP data
  93. LoadPSPVar CurPspSegment, PSP
  94.  
  95. COLOR Fg, Bg: CLS
  96. PRINT C(Hi, Bg); "----------- Program Segment Prefix Breakdown -----------"
  97. PRINT C(Hi, Bg); "This Program: "; C(Fg, Bg); ProgramSpec(PSP); "  ";
  98. PRINT C(Hi, Bg); "Current PSP at: "; C(Fg, Bg); Hex4$(CurPspSegment)
  99. ShowPSP PSP
  100.  
  101. ' fill ParentPSP variable with data
  102. LoadPSPVar PSP.ParentPSPSeg, ParentPSP
  103. PRINT C(Hi, Bg); "Parent Program: "; C(Fg, Bg); ProgramSpec(ParentPSP)
  104.  
  105. PRINT C(Hi, Bg); "Parent Command Line: "; C(Fg, Bg); CHR$(16);
  106. PRINT LEFT$(ParentPSP.CmdLine, ASC(ParentPSP.CmdLen)); CHR$(17)
  107.  
  108. FUNCTION C$ (Fore, Back)
  109.   'You can change colors in the middle of a print
  110.   'statement with this little gem! (only if you
  111.   'use ; or , to separate the printed elements -
  112.   'don't concatenate strings with + in a print statement
  113.   COLOR Fore, Back
  114.   C$ = ""
  115. END FUNCTION
  116.  
  117. FUNCTION CurPspSegment
  118.   ' return current PSP segment address
  119.   Regs.AX = &H6200
  120.   Interrupt &H21, Regs, Regs
  121.   CurPspSegment = Regs.BX
  122. END FUNCTION
  123.  
  124. FUNCTION Hex2$ (Num)
  125.   Hex2$ = RIGHT$("0" + HEX$(Num), 2)
  126. END FUNCTION
  127.  
  128. FUNCTION Hex4$ (Num)
  129.   Hex4$ = RIGHT$("000" + HEX$(Num), 4)
  130. END FUNCTION
  131.  
  132. SUB LoadPSPVar (PSPSeg, PSPVar AS PSPType)
  133.   ' use memory block ciopy to fill PSP variable with data
  134.   MemCopy PSPSeg, 0, 256, VARSEG(PSPVar), VARPTR(PSPVar), 256
  135. END SUB
  136.  
  137. SUB MemCopy (FSeg, FOfs, FCnt, TSeg, TOfs, TCnt)
  138.   STATIC i, Temp$
  139.   ' copy a block of memory
  140.   ' TCnt should be same as FCnt (it's there for B$ASSN compatibility)
  141.   ' * use B$ASSN alias instead for compiled programs *
  142.   ' go to source segment
  143.   DEF SEG = FSeg
  144.   ' peek temporary string
  145.   Temp$ = SPACE$(FCnt)
  146.   FOR i = 0 TO FCnt - 1
  147.     MID$(Temp$, i + 1, 1) = CHR$(PEEK(FOfs + i))
  148.   NEXT
  149.  
  150.   ' go to destination segment
  151.   DEF SEG = TSeg
  152.   ' poke temp string
  153.   FOR i = 0 TO TCnt - 1
  154.     POKE TOfs + i, ASC(MID$(Temp$, i + 1, 1))
  155.   NEXT
  156.   ' restore BASIC seg
  157.   DEF SEG
  158. END SUB
  159.  
  160. FUNCTION ProgramSpec$ (PSP AS PSPType)
  161.   STATIC i, Temp$
  162.   ' Returns full pathspec for program whose PSP is passed
  163.  
  164.   ' look at environment block
  165.   DEF SEG = PSP.EnvSeg
  166.   i = 0
  167.   ' find first occurrence of 00 00
  168.   DO WHILE PEEK(i) OR PEEK(i + 1)
  169.     i = i + 1
  170.   LOOP
  171.  
  172.   ' if user program, then 01 00 follows
  173.   IF (PEEK(i + 2) = 1) AND (PEEK(i + 3) = 0) THEN
  174.     ' jump past user program signature
  175.     i = i + 4
  176.     Temp$ = ""
  177.     ' build string until 00 byte
  178.     DO WHILE PEEK(i)
  179.       Temp$ = Temp$ + CHR$(PEEK(i))
  180.       i = i + 1
  181.     LOOP
  182.     ProgramSpec$ = Temp$
  183.   ELSE
  184.     ProgramSpec$ = "<Command Shell>"
  185.   END IF
  186. END FUNCTION
  187.  
  188. SUB ShowFCB (FCB AS UnopenedFCBType)
  189.   PRINT C(Hi, Bg); "  Drive  :"; C(Fg, Bg); ASC(FCB.DriveNum)
  190.   PRINT C(Hi, Bg); "  Name   : "; C(Fg, Bg); FCB.FileName
  191.   PRINT C(Hi, Bg); "  Ext    : "; C(Fg, Bg); FCB.Ext
  192.   PRINT C(Hi, Bg); "  CurBlk :"; C(Fg, Bg); FCB.CurBlk
  193.   PRINT C(Hi, Bg); "  RecSize:"; C(Fg, Bg); FCB.RecSize
  194. END SUB
  195.  
  196. SUB ShowPSP (PSP AS PSPType)
  197.   PRINT C(Hi, Bg); "Top of memory: ";
  198.   PRINT C(Fg, Bg); Hex4$(PSP.TopOfMemory); "  "
  199.  
  200.   PRINT C(Hi, Bg); "Term: ";
  201.   PRINT C(Fg, Bg); Hex4$(PSP.TermCS); ":"; Hex4$(PSP.TermIP); "  ";
  202.   PRINT C(Hi, Bg); "Break: ";
  203.   PRINT C(Fg, Bg); Hex4$(PSP.BreakCS); ":"; Hex4$(PSP.BreakIP); "  ";
  204.   PRINT C(Hi, Bg); "CritErr: ";
  205.   PRINT C(Fg, Bg); Hex4$(PSP.CritErrCS); ":"; Hex4$(PSP.CritErrIP)
  206.  
  207.   PRINT C(Hi, Bg); "Parent PSP Seg: "; C(Fg, Bg); Hex4$(PSP.ParentPSPSeg); "  "
  208.   PRINT C(Hi, Bg); "Environment Seg: "; C(Fg, Bg); Hex4$(PSP.EnvSeg)
  209.  
  210.   PRINT C(Hi, Bg); "Handle Table: "
  211.     PRINT C(Fg, Bg); "  ";
  212.   FOR i = 1 TO 20
  213.     PRINT Hex2$(ASC(MID$(PSP.HandleTable, i, 1))); " ";
  214.   NEXT
  215.   PRINT
  216.  
  217.   PRINT C(Hi, Bg); "Handle Count:"; C(Fg, Bg); HandleCnt; "  ";
  218.   PRINT C(Hi, Bg); "Handle Table Address: "; C(Fg, Bg);
  219.   PRINT Hex4$(PSP.HdlTblSeg); ":"; C(Fg, Bg); Hex4$(PSP.HdlTblOfs)
  220.  
  221.   PRINT C(Hi, Bg); "FCB #1"
  222.   ShowFCB PSP.FCB1
  223.  
  224.   PRINT C(Hi, Bg); "FCB #2"
  225.   ShowFCB PSP.FCB2
  226.  
  227.   PRINT C(Hi, Bg); "Cmd Line Length:";
  228.   PRINT C(Fg, Bg); ASC(PSP.CmdLen); "  ";
  229.  
  230.   PRINT C(Hi, Bg); "Command Line: "; C(Fg, Bg);
  231.   PRINT CHR$(16); LEFT$(PSP.CmdLine, ASC(PSP.CmdLen));
  232.   PRINT CHR$(17)
  233. END SUB
  234.  
  235. '                                   PSP.DOC
  236. '        ======== Exploring the PSP - by Brent Ashley =========
  237.  
  238. '     DOS maintains various data structures to help it to organize
  239. 'a running machine's memory.  One of these structures is the
  240. 'Program Segment Prefix, which is a collection of information DOS
  241. 'builds for an executing program.  The following discussion and the
  242. 'accompanying program will give you all you need to access and
  243. 'interpret the information stored in your program's PSP.
  244.  
  245. '     The PSP is a 256-byte area which is reserved in memory
  246. 'immediately before your program is loaded and run by the command
  247. 'shell (usually COMMAND.COM).  Its structure follows, along with
  248. 'typical uses of the information it contains. Offsets are in hex,
  249. 'byte counts in decimal, and remember that intel processors store
  250. 'numbers with lowest bytes first, ie 1234:5678 is stored as 78 56
  251. '34 12.
  252.  
  253. 'OFFSET 0 - 2 Bytes
  254.  
  255. '  There will always be the bytes CD 20 here - this is an INT 20h
  256. '  call (terminate program).  It's here so programs can jump to
  257. '  this location to terminate - not recommended, but it makes sense
  258. '  that programs which jump to an uninitialised (zero) address
  259. '  should be made to terminate in this way.
  260.  
  261. 'OFFSET 2 - 2 Bytes
  262.  
  263. '  This is the segment address of the last paragraph of memory
  264. '  allocated to the program.
  265.  
  266. 'OFFSET 5 - 5 Bytes
  267.  
  268. '  There is a far call to the DOS function dispatcher here.  This
  269. '  is here only for CP/M compatibility and is never used.
  270.  
  271. 'OFFSET A - 4 Bytes
  272. 'OFFSET E - 4 Bytes
  273. 'OFFSET 12 - 4 Bytes
  274.  
  275. '  These are the Segment:Offset Addresses to which control is
  276. '  passed:
  277.  
  278. '  - upon termination of the program.
  279. '  - when Control-Break is pressed.
  280. '  - when a critical error is encountered.
  281.  
  282. 'OFFSET 16 - 2 Bytes
  283.  
  284. '  The segment address of this program's parent program's PSP is
  285. '  stored here.
  286.  
  287. 'OFFSET 18 - 20 Bytes
  288.  
  289. '  A table of 20 file handles is stored here.  Any program needing
  290. '  more than the default 20 file handles will need to use INT 21h
  291. '  function 67h to set the handle count to a number more than 20
  292. '  (but no more than FILES= in CONFIG.SYS).  This will cause DOS
  293. '  to allocate a new file handle table of the size requested.  See
  294. '  Offsets 2E, 30 also.
  295.  
  296. 'OFFSET 2C - 2 Bytes
  297.  
  298. '  DOS provides each executable program with its own copy of the
  299. '  active Environment Strings at program load time.  This is the
  300. '  segment address of this program's copy.  The environment strings
  301. '  block contains a list of strings, each terminated by a 00 byte,
  302. '  with a further 00 byte at the end of the list. At the end of the
  303. '  environment strings, there is a 2-byte User Program signature
  304. '  which, when set to 1 (01 00), signifies the program's full path
  305. '  specification can be found in the following bytes, teminated
  306. '  with a null (00) byte.
  307.  
  308. 'OFFSET 2E - 2 Bytes
  309.  
  310. '  This is the number of file handles in the current handle table.
  311.  
  312. 'OFFSET 30 - 4 Bytes
  313.  
  314. '  Segment:Offset address of the file handle table, either the one
  315. '  here in the PSP, or the one allocated with INT 21h svc 67h.
  316.  
  317. 'OFFSET 5C - 16 Bytes
  318. 'OFFSET 6C - 16 Bytes
  319.  
  320. '  There are two unopened File Control Blocks constructed here as
  321. '  part of the program load process, based on the command line
  322. '  entered when the current progam was invoked.  It's interesting
  323. '  to note that DOS has already parsed the drive, filename and
  324. '  extension and placed it here, but only if there is no path
  325. '  information included, since FCBs are a throwback from when DOS
  326. '  didn't have a heirarchical directory structure.
  327.  
  328. 'OFFSET 80 - 1 Byte
  329. 'OFFSET 81 - 127 Bytes
  330.  
  331. '  The length of the command line entered after the program name
  332. '  when the program was invoked is stored here, followed by the
  333. '  command line itself.  The default Disk Transfer Area for this
  334. '  program is also here, so unless your program sets its own
  335. '  (which most do), the command line information could be
  336. '  overwritten.  You might want to get the command line information
  337. '  from here because QB uppercases it and trims it before passing
  338. '  it to you via COMMAND$.
  339.  
  340. '  The accompanying program, PSP.BAS, shows how you can access and
  341. 'interpret the PSP.  Remember that when using it in the QB
  342. 'development environment, the PSP it will be looking at is that of
  343. 'the environment.  A good test for the program will be to invoke it
  344. 'as follows:
  345.  
  346. 'PSP A:FILENAME.EXT B:OUTFILE.TST
  347.  
  348.