home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / lambda / soundpot / a / debug.lbr / DBUGABST.DZC / DBUGABST.DOC
Encoding:
Text File  |  1993-10-26  |  27.6 KB  |  641 lines

  1.                        AMYX DEBUG ABSTRACT
  2.  
  3.  
  4. This abstract is provided to help you find your way through AMYX
  5. DEBUG without having to tough out all the logic on your own.  It
  6. is not intended to be a byte-by-byte theory of program operation.
  7. The source code is adequately commented to reveal all the nitty-
  8. gritty details.  Major program divisions are indicated by cen-
  9. tered headings; the routines or subroutines they include are in-
  10. dicated by the capitalized routine names followed by a colon, in
  11. the usual assembler label fashion.
  12.  
  13. Once DEBUG is activated, it is, in essence, just a menu-driven
  14. program, with the "menu" selection made through the entry of a
  15. command letter.  When the command is decoded, a jump is made to
  16. the selected routine.  When the command action is finished, the
  17. program returns to the "Command?" prompt and waits for another
  18. command entry.
  19.  
  20.  
  21.                     DEVELOPMENT/MODIFICATION
  22.  
  23. While AMYX DEBUG was developed on (and for) a Kaypro 4-84 Plus
  24. 88, it was deliberately designed to make maximum use of standard
  25. CP/M calls so that it could easily be transported to any CP/M
  26. based computer with an 80 x 24 screen display and a means of dis-
  27. crete screen cursor positioning.  The program source code uses
  28. only standard Z80 mnemonics (except for the 'TITLE' peculiar to
  29. Micro Cornucopia's CROWECPM) and should be compatible with any
  30. standard Z80 assembler.  The use of a macro assembler is not
  31. required.
  32.  
  33. The only real "customization" necessary for non-Kaypro computers
  34. should be in the screen cursor positioning subroutine POSCUR.
  35. This subroutine can simply be rewritten in its entirety as re-
  36. quired.  The Kaypro cursor positions indicated by equates in the
  37. data section of the program are as follows (screen "home" at line
  38. 0, column 0):
  39.  
  40.          COMCUR: cursor position for "Command?" prompt.
  41.                  3720H = line 23, column 0
  42.          ERRCUR: cursor position for error messages.
  43.                  3742H = line 23, column 34
  44.          BRKCUR: cursor position for breakpoint display.
  45.                  3520H = line 21, column 0
  46.          MODCUR: cursor position for modify memory prompt.
  47.                  3729H = line 23, column 0
  48.          MEMCUR: cursor position at beginning of memory display.
  49.                  2D26H = line 13, column 6
  50.  
  51. The only other Kaypro specifics are the clear screen character
  52. (26D) and the cursor "home" character (30D).
  53.  
  54. The highest address of relocated code is specified in the equate
  55. RELTOP:, located just at the end of the relocation and initiali-
  56. zation module; the highest relocation address is actually set at
  57. RELTOP-2 by calculations located at the very end of the program
  58. code.  RELTOP is currently set at E000H, the bottom of the CCP
  59. for the Kaypro 4-84; RELTOP can be changed to any reasonable val-
  60. ue without making any other changes in program code.
  61.  
  62. DEBUG object code has successfully been transported directly to
  63. an older Kaypro II.
  64.  
  65.  
  66.                   GENERAL PROGRAM ORGANIZATION
  67.  
  68. Briefly, DEBUG is organized as follows:
  69.  
  70. RELOCATION AND INITIALIZATION
  71. BEGIN DEBUG CODE
  72.     BIOS equates
  73.     Character equates
  74.     Cursor positions
  75.     Messages
  76.     Variables
  77. --MAIN PROGRAM--
  78.     ENTRY:   Entry
  79.     ENTRY0:  Screen display
  80.     COMAND:  Command entry
  81.     COMDEC:  Command decode
  82. COMMAND ACTION
  83.     MPAGE:   Page memory forward or back
  84.     DSPLAY:  Display selected page of memory
  85.     MODMEM:  Modify memory
  86.     BRAKPT:  Set breakpoint from keyboard entry
  87.     SSTEP:   Single-step
  88.     CLRBRK:  Clear all breakpoints
  89.     FIXBRK:  Clear specified breakpoint
  90.     JUMP:    Jump to specified address
  91.     FILL:    Fill memory with specified byte
  92.     REGMOD:  Modify register contents
  93.     MOVE:    Block move
  94.     SEARCH:  String search
  95.     HARITH:  Hex arithmetic
  96.     DBEND:   Return to user program
  97. DEBUG-SPECIFIC SUBROUTINES
  98.     DISPAF:/DPRIM:   Display contents of CPU AF and AF' registers
  99.     DISPBC:-DISPPC:  Display contents of all other CPU registers
  100.     DISMEM:  Display contents of 128-byte page of memory
  101.     REGRET:  (Calls ONLYRG and DISRG)
  102.     ONLYRG:  Display just the contents of a CPU register
  103.     DISREG:  Display the register indirects
  104.     DISBRK:  Display breakpoint addresses
  105.     GETWRD:/GETBYT:  Convert ASCII command buffer data to hex
  106.                      values
  107.     NXTCHR:  Adjust command buffer pointer and counter when
  108.              decoding a command
  109.     COMCHK:  Check for bad command
  110.     COMCH1:  Print error message and cancel command
  111.     SETBRK:  Install breakpoint in user program code
  112.     MATCH:   Search breakpoint table for address
  113.     LOAD:    Fill memory with specified byte
  114.     REPBRK:  Repair breakpoint set in user program code
  115. GENERAL SUBROUTINES/PRIMITIVES
  116.     GENRET:  Return for several subroutines
  117.     KBD:     Strobe keyboard for one character
  118.     CHROUT:  Print one character on screen
  119.     MSGOUT:  Print string on screen
  120.     HX2ASC:  Convert one hex byte to ASCII and output to screen
  121.     ASC2HX:  Convert one ASCII character to a hex value
  122.     NEWLIN:  Drop cursor one screen line
  123.     POSCUR:  Place screen cursor at specified position
  124.     BEEP:    Beep keyboard
  125.     DELAY:   Delay approximately three seconds
  126. TABLES
  127. STACK
  128.  
  129.  
  130.                   RELOCATION AND INITIALIZATION
  131.  
  132. Relocates the DEBUG code from CODBEG: through CODEND: with the
  133. highest program byte one address below the address specified by
  134. the equate RELTOP:.  All breakpoints are cleared; the jump to the
  135. relocated CODBEG: address is written into the DDT call address at
  136. 38H; a loaded-and-relocated confirming message is printed on the
  137. screen, together with the addresses that the relocated DEBUG oc-
  138. cupies; and system control is returned without a warm boot.
  139.  
  140.  
  141.                            DEBUG CODE
  142.  
  143. Actual DEBUG code, starting at CODBEG:, follows the relocation
  144. and initialization section.  The only action that takes place at
  145. CODBEG: is a jump to ENTRY:, where the main program starts.  Be-
  146. tween CODBEG: and ENTRY: are located BIOS equates, character
  147. values, cursor positions, messages, and variable allocations.
  148.  
  149.  
  150.                           MAIN PROGRAM
  151.  
  152. ENTRY: is where the action starts.  First, the user SP is saved
  153. and the DEBUG stack address is loaded into SP; then the user's
  154. register contents are pushed onto the DEBUG stack.  The user PC,
  155. placed on the user's stack by the RST 38H DEBUG call, is stored,
  156. then popped off the user's stack and discarded.  The user's cur-
  157. sor location is also saved in case the user's program includes
  158. direct screen manipulation.  DEBUG then checks the breakpoint
  159. table (BRKTBL:) to see if any breakpoints are set and, if so,
  160. installs them in the user program code.
  161.  
  162. A check is then made to see whether entry to DEBUG came from an
  163. RST 38H coded into the user program or from a breakpoint.  This
  164. test is made by decrementing the user PC (SYSPC:) and testing
  165. that address against entries in the breakpoint table (BRKTBL:).
  166. (The RST 38H places the next program address on the stack as its
  167. "return" point.)  If no match is found, DEBUG execution jumps di-
  168. rectly to ENTRY0: to write the screen display.  If entry is from
  169. a breakpoint, the user code is repaired (see SETBRK: and REPBRK:)
  170. and the decremented PC is retained as the actual PC to resume ex-
  171. ecution of the user program.
  172.  
  173.  
  174.                      OPENING SCREEN DISPLAY
  175.  
  176. At ENTRY0: the screen is cleared of whatever the user might have
  177. had on it; at ENTRY1: the writing of the DEBUG display begins.
  178. When the screen display is complete, the program jumps to COMRET:
  179. (located after the last command processing section), then to
  180. COMAND: for command entry.
  181.  
  182.  
  183.                       GENERAL PROGRAM FLOW
  184.  
  185. Once DEBUG is invoked, the opening screen display is complete,
  186. and the "Command?" prompt is written, the general program flow is
  187. as follows:
  188.  
  189. --Check for immediate commands.  Immediate commands are
  190. acted upon as soon as their character is entered.
  191.  
  192. --Enter characters into the command buffer.  All charac-
  193. ters are checked to be sure they're valid as they are
  194. entered.  Valid characters are added to the command buf-
  195. fer (COMBUF:); invalid characters are signaled by a key-
  196. board beep and a stationary cursor.  All commands (except
  197. immediate commands) are terminated with a carriage re-
  198. turn, which is NOT added to the buffer.
  199.  
  200. --Decode the command.  As soon as the first character in
  201. the command buffer is checked to see what it is, a jump
  202. is made to the indicated command section.  The remainder
  203. of the command line is decoded in the command sections
  204. according to the command's requirements.  After decoding,
  205. all commands are checked (COMCHK:) to be sure the correct
  206. number of characters was entered (i.e., a coarse check to
  207. be sure that all addresses and byte values are complete).
  208.  
  209. --Carry out the command.
  210.  
  211. --Return to the command line.  All command action is ter-
  212. minated by a jump to COMRET:, where the command entry
  213. line is tidied up and flags are cleared, followed by a
  214. jump to COMAND:, where the buffer counters are reset and
  215. the "Command?" prompt is written.
  216.  
  217.  
  218.                     COMMAND PROCESSING MODULE
  219.  
  220. COMAND: is where the program lands upon completion of the opening
  221. display or at the end of any command action.  KEYIN: and KEYIN1:
  222. begin the keyboard strobe loop to pick up characters.  Input
  223. characters are checked first to see whether they're immediate
  224. commands.  If so, they are acted upon immediately; if not, the
  225. first character is checked to be sure it is a valid command.  The
  226. command character is also stored in COMFLG: as an indicator that
  227. a command is in progress.  Characters after the first one are
  228. checked in CKCHAR: to be sure that they're a hex digit, a regis-
  229. ter specifier, a period, a space, a backspace, or a carriage re-
  230. turn.  Valid characters are added to the buffer in AD2BUF:, with
  231. the buffer pointer and character counter adjusted appropriately.
  232. Spaces are valid characters from the keyboard, but are not added
  233. to the command buffer.  Invalid characters cause a jump to
  234. BADCHR: for a keyboard beep and cursor backspace.  AD2BUF: and
  235. BADCHR: terminate with a jump to KEYIN1: for the next character.
  236. Entry of a carriage return (which is not added to the command
  237. buffer), sends program execution to COMDEC:, where the command is
  238. decoded.
  239.  
  240.  
  241.                          COMMAND DECODE
  242.  
  243. COMDEC: begins decoding of the command.  As soon as the command,
  244. the first character in the command buffer, is identified, program
  245. execution jumps to the indicated section.  Command data are de-
  246. coded within each command routine, mainly by GETWRD: and GETBYT:,
  247. subroutines that translate the command buffer ASCII characters
  248. into hexadecimal values.
  249.  
  250.  
  251.          PAGE MEMORY FORWARD OR BACK (IMMEDIATE COMMAND)
  252.  
  253. MPAGE: adds or subtracts 80H from the value saved in MEMSEL:, the
  254. area of memory selected for display, saves the new value in
  255. MEMSEL:, then rewrites the page of memory on display through a
  256. call to DISMEM:.
  257.  
  258.  
  259.                           MODIFY MEMORY
  260.  
  261. MODMEM: begins the routine for modifying memory.  This routine is
  262. initiated by the usual command format.  Use of the modify routine
  263. is indicated by setting the byte MODFLG: to 1, after which the
  264. addresses to be modified are automatically incremented and dis-
  265. played with a "Modify:  AAAA" prompt, and all the user enters is
  266. the new byte for the address.  This subsequent modification is
  267. carried out through a loop from MODME1: to the end of MODME2:,
  268. and is terminated by the entry of a period in place of a byte
  269. value.
  270.  
  271.  
  272.                SET BREAKPOINT FROM KEYBOARD ENTRY
  273.  
  274. BRAKPT: begins the routine to set a breakpoint from keyboard en-
  275. try.  Setting a breakpoint involves two steps.  First, the break-
  276. point table (BRKTBL:) is checked to see if there's room for an-
  277. other breakpoint (indicated by a 0000 entry).  The first 0000 en-
  278. try encountered is filled in with the address specified by the
  279. user.  If no empty space is found, the keyboard beeps, the mes-
  280. sage "BREAKPOINTS FULL!" is displayed, and the program returns to
  281. COMAND:.  Second, the breakpoint is installed in the user program
  282. code through a call to SETBRK:.
  283.  
  284.  
  285.                            SINGLE-STEP
  286.  
  287. SSTEP: begins the single-stepping routine.  The gist of single-
  288. stepping is to emulate CPU action through software one step ahead
  289. of the CPU, setting a breakpoint at the executable instruction
  290. following the one shown at the PC.  Single-stepping is effected
  291. through four separate actions.
  292.  
  293. First, the code at the user PC must be discretely tested for
  294. jumps (SSTEP:-SSTE17:).  If the next executable instruction is an
  295. unconditional jump, a breakpoint is set internally at the jump
  296. address.  If the next executable instruction is a conditional
  297. jump, the contents of the F register must be tested.  If the jump
  298. condition is true, then a breakpoint is set at the jump address.
  299.  
  300. Second, if the jump condition is not true or if the instruction
  301. is not a jump, then the length of the instruction at the current
  302. user PC must be determined.  The length of the instruction is de-
  303. termined by comparing the byte at the PC, and the one following,
  304. if necessary, with the contents of tables TAB21:, TAB22:, TAB31:,
  305. TAB32:, and TAB42: (located at the very end of the program code).
  306. Bytes in tables TAB21 and TAB31 are single-byte indicators of
  307. two- and three-byte instructions respectively.  If the byte at
  308. the PC is DD, ED, or FD, then the bytes in tables TAB22, TAB32,
  309. and TAB42 indicate two-, three-, and four-byte instructions re-
  310. spectively.  A byte at the PC not found in the tables is assumed
  311. to be a one-byte instruction.
  312.  
  313. Third, after the length of the instruction has been determined,
  314. the user PC address is incremented accordingly to establish the
  315. address of the next executable instruction.  Fourth, the address
  316. of the next instruction is stored in the first breakpoint table
  317. location (overwriting anything that might have been there) and a
  318. breakpoint is installed at that address using SETBRK:.
  319.  
  320.  
  321.             CLEAR ALL BREAKPOINTS (IMMEDIATE COMMAND)
  322.  
  323. CLRBRK: starts the routine for clearing all six breakpoints.  The
  324. breakpoint table is tested for entries.  Where a nonzero entry is
  325. found, the breakpoint is repaired using REPBRK:.  After the
  326. breakpoint is repaired, its entry in the breakpoint table is set
  327. to zero.  When all breakpoints have been cleared, the breakpoint
  328. display line is rewritten to show its cleared status.
  329.  
  330.  
  331.                   CLEAR A SPECIFIED BREAKPOINT
  332.  
  333. FIXBRK: clears one breakpoint specified by the user.  The user's
  334. entry is checked against the breakpoint table, and a BAD COMMAND!
  335. message is posted if there is no match.  If the specified address
  336. is ok, its table entry is set to zero, the breakpoint is repaired
  337. using REPBRK:, and the breakpoint display line is rewritten to
  338. show its new status.
  339.  
  340.  
  341.                     JUMP TO SPECIFIED ADDRESS
  342.  
  343. JUMP: directs execution of the user program to the specified ad-
  344. dress.  The specified address is loaded into the user's PC stor-
  345. age area; DEBUG then executes a "Go" through a jump to DBEND:
  346. (control is returned to the user program).
  347.  
  348.  
  349.               FILL MEMORY AREA WITH SPECIFIED BYTE
  350.  
  351. FILL: simply fills an area of memory from a specified starting
  352. address through a specified ending address with a specified byte.
  353. FILL: sets up the starting and ending addresses; the actual load-
  354. ing of memory is done in the subroutine LOAD:.
  355.  
  356.  
  357.                     MODIFY REGISTER CONTENTS
  358.  
  359. REGMOD: starts the routine to modify the contents of a specified
  360. register.  What's actually changed is the user register value
  361. stored on the DEBUG stack.  The new value is loaded into the
  362. specified register only when a Jump or Go is executed and the
  363. contents of the stack are popped back into the registers.
  364.  
  365. First, the register identifier in the command buffer is "hashed"
  366. by adding the ASCII values of the two characters together.  Be-
  367. cause the user SP and PC are not stored on the DEBUG stack, a
  368. discrete test is made for them first.  If the register to be mod-
  369. ified is neither SP nor PC, the test for which regular register
  370. is made by using a CPIR instruction to compare the hashed identi-
  371. fier value with the possible hashed identifier values, which are
  372. in table REGTAB: (at the end of the program).  If no match is
  373. found, the program jumps to BADREG: and outputs the BAD COMMAND!
  374. message.
  375.  
  376. If a match is found in the table, the contents of the C register
  377. at the match are used to calculate the location of the register
  378. on the stack from the current DEBUG SP.  If the register to be
  379. modified is SP or PC, dummy displacements of FFH and FEH respect-
  380. ively are used to so indicate.  The indicated change is made in
  381. memory, then the whole screen display is rewritten to show the
  382. new register status.
  383.  
  384.  
  385.                            BLOCK MOVE
  386.  
  387. MOVE: uses the LDIR instruction to copy the contents of a block
  388. of memory specified by starting and ending addresses to a loca-
  389. tion whose starting address is specified.  The routine calculates
  390. the number of bytes to move from the starting and ending address-
  391. es, registering an error if start and end have been entered
  392. backward.
  393.                           STRING SEARCH
  394.  
  395. SEARCH: searches an area of memory specified by a starting and
  396. ending address for a string defined by hex values.  The length of
  397. the input string is limited only by the size of the command buf-
  398. fer.  Because the command requires two bytes (ASCII characters)
  399. per hex byte of data, the maximum string length turns out to be
  400. 11 bytes.  Because the length of the string is variable, its end
  401. must be marked by a period.  If no period is found when decoding
  402. the command buffer, an error is registered.
  403.  
  404. The search algorithm itself runs from SEARC8: through the end of
  405. SEARC5:  If the string is not found, the program jumps to SEARC6:
  406. and outputs a STRING NOT FOUND message.  If the string is found,
  407. the program jumps to SEARC7:, where the address of the first
  408. character of the find is loaded into MEMSEL: as the address of
  409. the page of memory to be displayed, and the memory display is re-
  410. written.  Additionally, if the string is found, the search can be
  411. resumed for further searching in the specified area of memory by
  412. entering S followed by a period.  In this case, the search starts
  413. again with the first address following the last character of the
  414. last find.
  415.  
  416. The little subroutine ENDTST: following the string search routine
  417. is unique to SEARCH: and was placed here to keep it from getting
  418. lost in the chaff of other little subroutines.
  419.  
  420.  
  421.                      PERFORM HEX ARITHMETIC
  422.  
  423. HARITH: just performs sixteen-bit hexadecimal addition or sub-
  424. traction and prints the results on the command line following the
  425. input.  The result of a calculation remains on display until any
  426. key is pressed.
  427.  
  428.  
  429.                      RETURN TO COMMAND LINE
  430.  
  431. COMRET: is the location to which all commands jump when their
  432. action is completed.  In COMRET:, the command line is blanked and
  433. the flags MODFLG: (which indicates that a modify memory command
  434. is in process) and COMRET: (used in testing for immediate com-
  435. mands to indicate that any command is in process) are turned off
  436. (set to zero).  The program then jumps back to COMAND: to await
  437. input of the next command.
  438.  
  439.  
  440.                      RETURN TO USER PROGRAM
  441.  
  442. DBEND: is the "end" of the DEBUG program; that is, a jump to
  443. DBEND: from either a Go or a Jump command (or a Go internally ex-
  444. ecuted in single-stepping) returns control to the user program.
  445. The user's cursor position is restored, the user's PC is returned
  446. from storage to the bottom of the user stack, all registers are
  447. popped from the DEBUG stack, the user stack pointer is loaded in-
  448. to the SP register, and a RETurn is executed.
  449.  
  450.                    DEBUG-SPECIFIC SUBROUTINES
  451.  
  452. DISPAF:/DPRIM: prints the AF and AF' register displays on the
  453. screen.  On entry, IX contains the DEBUG SP.  A, E, and HL are
  454. destroyed.
  455.  
  456. DISPBC:-DISPPC: print the displays for the indicated registers by
  457. loading HL with the register contents from the DEBUG stack and
  458. then jumping to REGRET:.  On entry, IX contains the DEBUG SP.
  459.  
  460. DISMEM: prints the 128-byte page of memory in the display.  On
  461. entry, the address of the selected area of memory for display is
  462. in HL.  A and BC are destroyed.
  463.  
  464. REGRET: is the common return from all the register displays.  It
  465. makes two subroutine calls to ONLYRG: and DISREG:.
  466.  
  467. ONLYRG: prints the contents of a Z80 register to the CRT screen.
  468. On entry, the hex word to be output is in HL.  A and E are
  469. destroyed.
  470.  
  471. DISREG: prints the sixteen indirect address contents for the reg-
  472. ister displays and the memory display.  On entry, the address for
  473. which the indirects are to be displayed is in HL.  A, BC, and E
  474. are destroyed.
  475.  
  476. DISBRK: prints the breakpoint line on the display.  Nothing is
  477. transferred in through CPU registers; uses A, B, DE, and HL.
  478.  
  479. GETWRD:/GETBYT: decode a two-byte hex word or a hex byte from the
  480. ASCII representations in the command buffer.  On entry, the cur-
  481. rent address of the command buffer pointer (COMBUF:) is in HL.
  482. GETWRD: returns the hex word in DE; GETBYT: returns the byte as a
  483. "low" byte in E.
  484.  
  485. NXTCHR: advances the command buffer pointer (COMBUF:) and incre-
  486. ments the command buffer counter (CBUFCT:).  On entry, the com-
  487. mand buffer pointer is in HL; the current buffer character, which
  488. is in A, is preserved.  NXTCHR: is used primarily by GETWRD: and
  489. GETBYT:, but is also called directly from the main command rou-
  490. tines for modifying register contents (REGMOD:), for hex arithme-
  491. tic (HARITH:) as a way of picking up a non-hex character (the
  492. arithmetic operator) discretely, and by SEARCH: as a way of dis-
  493. carding the period ending the command.
  494.  
  495. COMCHK: checks any command after decoding to be sure that the
  496. command contained the proper number of characters (the command
  497. buffer counter (CBUFCT:) should be zero after any command is
  498. decoded).  If the command is good, only A is destroyed.  If the
  499. command is bad, the subroutine continues on to
  500.  
  501. COMCH1:, which beeps the keyboard and prints the BAD COMMAND!
  502. message.  COMCH1: is also called any time a command error is
  503. detected for whatever reason (e.g., a missing period in the
  504. Search command entry).  All registers are destroyed.
  505.  
  506. SETBRK: is where breakpoints set either from user keyboard entry
  507. or internally during single-stepping are established.  There are
  508. two tables involved with breakpoints, BRKTBL:, which contains the
  509. breakpoint addresses, and CODSAV:, which contains the bytes of
  510. user program code saved when a breakpoint is installed.  These
  511. two tables are linked by a counter, BRKCNT:, to keep the bytes of
  512. saved code in proper relationship to the addresses where they be-
  513. long.  On entry to SETBRK: the address of the user program where
  514. a breakpoint is requested is in DE.
  515.  
  516. The byte of code at the breakpoint address is transferred to its
  517. position in CODSAV:; the breakpoint address in the user program
  518. is then loaded with FFH (RST 38H) to effect the breakpoint.  A is
  519. destroyed.
  520.  
  521. MATCH: searches the breakpoint table for a match with a break-
  522. point address requested to be cleared through FIXBRK:.  On entry,
  523. the address to be tested is in DE.  A, B, and HL are destroyed.
  524.  
  525. LOAD: fills an area of memory from a specified starting address
  526. through a specified ending address with a specified byte.  On
  527. entry, the start address is in DE, the end address is in HL, and
  528. the byte is in A.  All registers are preserved.
  529.  
  530. REPBRK: is just the inverse of SETBRK:.  Here the breakpoint
  531. (FFH) in the user program is replaced with its proper code byte
  532. from the CODSAV: table.  On entry, the breakpoint address is in
  533. DE.  A is destroyed.
  534.  
  535.  
  536.                  GENERAL SUBROUTINES/PRIMITIVES
  537.  
  538. GENRET: is a common return from any subroutine that pushes BC,
  539. DE, and HL.
  540.  
  541. KBD: uses the standard BDOS call to strobe the keyboard for one
  542. character, shifting the character to upper case if necessary.
  543.  
  544. CHROUT: uses the standard BDOS call to output one character to
  545. the CRT screen.
  546.  
  547. MSGOUT: uses the standard BDOS call to output a string to the CRT
  548. screen.
  549.  
  550. HX2ASC: converts a hex byte to its ASCII representation and out-
  551. puts it to the CRT screen.  The byte to be converted is in A on
  552. entry; E is destroyed.
  553.  
  554. ASC2HX: converts one ASCII character to its hex value; e.g., "F"
  555. becomes 0FH.  On entry, the ASCII character is in A; on exit, A
  556. contains the hex value.
  557.  
  558. NEWLIN: outputs a carriage return-line feed sequence to the CRT
  559. screen to drop the cursor a line.  E is destroyed.
  560.  
  561. POSCUR: positions the screen cursor in accordance with Kaypro
  562. protocol.  On entry, the hexadecimal row,column cursor position
  563. is in the BC register (B=row; C=column).  E is destroyed.
  564.  
  565. BEEP: sends an ASCII 07H to the keyboard.  All registers are
  566. preserved.
  567.  
  568. DELAY: does nothing for approximately three seconds; used to hold
  569. error messages on the screen.  The inner loop takes approximately
  570. one-half second to complete; hence, the total delay can be ad-
  571. justed in half-second increments by changing the value loaded in-
  572. to B in the first line.  A, B, and HL are destroyed.
  573.  
  574.  
  575.                              TABLES
  576.  
  577. REGTAB: contains the "hashed" identifiers (i.e., the sum of the
  578. ASCII values of the characters; A'=AF', B'= BC', etc.) for all
  579. the registers but SP and PC.  Used by the modify register (REG-
  580. MOD:) routine.
  581.  
  582. Tables TAB21:-TAB42: are used in conjuction with the single-
  583. stepping routine (SSTEP:) to determine the length of any instruc-
  584. tion.  The end of each of these tables is identified by TNNEND
  585. with an equate at location; the beginning and ending labels of
  586. the tables are used to calculate the table lengths for the CPIR
  587. instruction in the single-step routine.  I set the tables up this
  588. way just in case I missed a byte or the information I was working
  589. from was incorrect or incomplete.  If a user finds an error in
  590. these tables, he can correct it by changing, adding to, or delet-
  591. ing from the tables without having to be concerned with any
  592. changes in program code per se.
  593.  
  594. TAB21: contains one-byte indicators of two-byte instructions;
  595. that is, if the byte is any of TAB21:, then the instruction is
  596. two bytes long.
  597.  
  598. TAB22: contains the second byte of two-byte indicators of two-
  599. byte instructions.  If the first instruction byte is DD, ED, or
  600. FD, and the second byte is any of TAB22:, then the instruction is
  601. two bytes long.
  602.  
  603. TAB31: contains one-byte indicators of three-byte instructions;
  604. that is, if the byte is any of TAB31:, then the instruction is
  605. three bytes long.
  606.  
  607. TAB32: contains the second byte of two-byte indicators of three-
  608. byte instructions.  If the first instruction byte is DD, ED, or
  609. FD, and the second byte is any of TAB32:, then the instruction is
  610. three bytes long.
  611.  
  612. TAB42: contains the second byte of two-byte indicators of four-
  613. byte instructions.  If the first instruction byte is DD, ED, or
  614. FD, and the second byte is any of TAB42:, then the instruction is
  615. four bytes long.
  616.  
  617.  
  618.                               STACK
  619.  
  620. A 64-byte (32-word) stack (LOCSP:) is located at the very end of
  621. the program code.  Inasmuch as ten stack words are always in use
  622. by DEBUG for the user register contents, the stack is effectively
  623. 22 words deep.  This is probably adequately conservative.  Al-
  624. though I haven't checked to see how deep the subroutines are go-
  625. ing, the limit is probably no more than eight, including PUSHes.
  626. I have not, in any event, found the end of TAB42 corrupted at any
  627. time.
  628.  
  629.  
  630.                THE FINAL EQUATES AND CALCULATIONS
  631.  
  632. The final equates and calculations CODEND, CODSIZ, DESTIN, and O
  633. all pertain to the relocation of DEBUG and the offset applied to
  634. jumps and calls in its relocated position.  The program can be
  635. modified anywhere between CODBEG: and CODEND without the need for
  636. special attention to relocation or offsets.
  637.  
  638.  
  639.                                ###
  640.  
  641.