home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / database / loadcall.zip / ABOUT.TXT next >
Text File  |  1987-04-06  |  17KB  |  469 lines

  1. Interfacing Assembly Language Routines with dBASE
  2.  
  3.    by Ralph Davis
  4.  
  5. Creating Assembler Programs with DEBUG
  6.  
  7. DEBUG is the assembly language programmer's best friend.  It is a
  8. powerful tool for exploring the computer's memory, testing assembly
  9. language programs, studying program listings, and creating new
  10. programs.  Additionally, it can be used to rebuild corrupted data
  11. files, convert hidden files to accessible files, or simply analyze
  12. file structures. Our main interest in DEBUG here is to create
  13. assembly language routines for use with dBASE II and dBASE III.  
  14.  
  15. It is tempting to use DEBUG because of its interpreter-like
  16. qualities.  You can quickly enter code and then see if it works.If
  17. it does, you call it <PROGRAM>.COM and write it to disk.  If it
  18. doesn't, you trace through the old code, enter new code, and try
  19. again.  Eventually, you come up with a program that works through
  20. trial-and-error.  However, this can lead to sloppy programming
  21. habits and inefficient code, so it is important to bear in mind
  22. what you want a particular program to accomplish.
  23.  
  24. DEBUG has some limitations.  Most importantly, it only recognizes
  25. absolute addresses.  When you write a program for submission to
  26. an assembler, you label the instructions and data you will need
  27. to refer to, then refer to them with the label.  You don't need
  28. to know the actual addresses.  DEBUG, on the other hand, obliges
  29. you to look through your program listing and find addresses
  30. whenever you refer to them.  For instance, instead of entering
  31. JMP EXIT, you must enter JMP 02FC.  Instead of CALL HEXPRINT, you
  32. use CALL 05AE.  Instead of MOV BX, OFFSET DATA, you need MOV BX,
  33. 0105.  If your routine is small, this does not present a problem.
  34. But as you add features and it becomes larger, this becomes a
  35. serious impediment.  If you add or alter instructions, thereby
  36. changing an absolute address, you have to change every reference
  37. to it.  And the only way to find the references is to page
  38. through the entire program, line by line.  For this reason, DEBUG
  39. is best for creating short utility programs.  
  40.  
  41. Most often, programs created with DEBUG use BIOS or DOS
  42. interrupts to manipulate the hardware.  Some typical functions
  43. that appear in this issue are setting the cursor (see the example
  44. on page 4-72C of the Developer's Release Reference Manual and the
  45. program listed in this issue), manipulating the shift keys, or
  46. swapping printer ports. Programs of this type should not contain
  47. any subroutines.
  48.  
  49.  
  50. DEBUG has another important limitation: it only understands
  51. hexadecimal numbers.  There is simply nothing you can do to make
  52. it accept decimal numbers.  This is not a problem when entering
  53. addresses or interrupt numbers, as most assembly language
  54. programmers think these values in hexadecimal anyway.  But very
  55. few programmers think in hex when doing calculations.  DEBUG is
  56. therefore not a good tool for doing number-crunching of even
  57. intermediate complexity.  Although there are utilities available
  58. to assist in this process, such as Sidekick, this is still a
  59. major obstacle to doing extensive calculations within DEBUG.
  60.  
  61. Another problem with DEBUG is that code produced with it can be
  62. extremely obscure.  Trying to decipher the flow of a program
  63. where you have only absolute addresses and hexadecimal numbers to
  64. guide you can be very frustrating.  In addition, DEBUG does not
  65. support comments.  So when you read a DEBUG listing, you are, for
  66. all intents and purposes, reading "machine English."  The machine
  67. expresses its own language in cryptic English-like symbols,
  68. making a few grudging concessions to your desire to understand
  69. it.  All of this reinforces what we suggested earlier:  keep
  70. DEBUG routines short.
  71.  
  72.  
  73. The program from the Developer's Release Reference Manual
  74. mentioned above is a good example of a program appropriate for
  75. DEBUG.  The listing on page 4-72C is as follows:
  76.  
  77.      _PROG    SEGMENT    BYTE
  78.              ASSUME    CS:_PROG
  79.      ;
  80.      CURSOR    PROC        FAR        ; Force a far return.
  81.      ;
  82.              MOV        CX,[BX]    ; Get two HEX digits.
  83.              MOV        AH,1        ; Set cursor type.
  84.              INT        10H        ; Video interrupt.
  85.              RET                ; Do a far return.
  86.      ;
  87.      CURSOR    ENDP
  88.      ;
  89.      _PROG    ENDS
  90.              END
  91.      
  92. This is a terse routine that converts the dBASE III cursor to a
  93. full-sized box when CHR(18) passed as a parameter to it.  Notice
  94. one thing about this code:  it has six lines of assembler
  95. directives (the first three and the last three), and only four
  96. lines of machine instructions.  In a short program like this one,
  97. there is no advantage to assembling, linking, and converting it
  98. using MASM, LINK, and EXE2BIN.  DEBUG is faster and easier.
  99.  
  100. Here is a DEBUG session that enters this program as a .COM file.
  101.  
  102. (The DEBUG commands are explained in Chapter 8 of the PC/MS-DOS
  103. manual.  Page numbers which follow refer to it.)
  104.  
  105.  
  106.  
  107.  
  108.      D>debug
  109.  
  110. First give DEBUG the 'A' (assemble) command (page 8-15) and enter
  111. the program.
  112.  
  113.      -A
  114.      6257:0100  MOV CX,[BX]
  115.      6257:0102  MOV AH,1
  116.      6257:0104  INT 10
  117.      6257:0106  INT 20
  118.      6257:0108  
  119.         
  120.  
  121. Notice that 'INT 20' is our last instruction, not 'RET' as the
  122. manual indicates.  We will explain this shortly.
  123.  
  124. The address following the last instruction is 108.  Therefore,
  125. enter eight into CX using the 'R' (register) command [page 8-41].
  126. This tells DEBUG the number of bytes to write to disk.
  127.  
  128.      -RCX
  129.      CX 0000
  130.      :8
  131.  
  132. Name the program CURSOR.COM using the 'N' command [page 8-37],
  133. and write it to disk using 'W' [page 8-55].
  134.  
  135.      -NCURSOR.COM
  136.      -W
  137.      Writing 0008 bytes
  138.  
  139. This is the basic procedure for creating a .COM file from DEBUG.
  140. CURSOR.COM will yield unpredictable results executed from
  141. PC/MS-DOS, since the registers are not preserved, and we have no
  142. way of knowing what is being passed in DS:BX.  (When we tested
  143. it, the cursor simply vanished.)  Nor, in its present form, will
  144. it work in dBASE III.  It needs a couple of changes to make it
  145. work, but this point deserves some attention.
  146.  
  147. PC/MS-DOS .COM files and dBASE LOAD modules require slightly
  148. different specifications.  A .COM file must be ORGed (originated)
  149. at address 100H, and it must end with a command like INT 20H
  150. (terminate) or INT 27H (terminate and stay resident); a simple
  151. RET will not return correctly.  dBASE III, on the other hand,
  152. requires LOAD modules to be ORGed at address 0 and to return to
  153. dBASE III with a far return, RETF.  If you load a conventional
  154. .COM file, ORGed at 100H and terminated with INT 20H, into dBASE
  155. III, and then call it, you will lock the system, even if it works
  156. from PC/MS-DOS.  When DEBUG writes a program to disk, it writes a
  157. binary file -- that is, a file which contains nothing but the
  158. machine instructions you have given it.  Therefore, we need not
  159. concern ourselves with ORGing programs correctly at this stage.
  160. We do have to terminate LOAD modules with RETF, however.
  161.  
  162. Here is a DEBUG session that enters this program as a .BIN file
  163. which will execute from dBASE III.
  164.  
  165.      D>debug
  166.  
  167. Type 'A' for assemble.  Terminate with a RETF.
  168.  
  169.      -A
  170.      6346:0100  MOV CX,[BX]
  171.      6346:0102  MOV AH,1
  172.      6346:0104  INT 10
  173.      6346:0106  RETF
  174.      6346:0107  
  175.  
  176. Place the number 7 in the CX register to save 7 bytes to disk.
  177.  
  178.      -RCX
  179.      CX 0000
  180.      :7
  181.  
  182. Name the file, and write it.
  183.  
  184.      -NCURSOR.BIN
  185.      -W
  186.      Writing 0007 bytes
  187.  
  188. Quit DEBUG.
  189.      -Q
  190.  
  191. The page of the Developer's Release Manual referred to above
  192. gives the following example of how to use Cursor:
  193.  
  194.      LOAD Cursor
  195.      STORE CHR(18) TO shape
  196.      CALL Cursor WITH shape
  197.  
  198. The commands to convert the cursor back to its normal format are:
  199.  
  200.      LOAD Cursor
  201.      STORE CHR(12) + CHR(11) to shape
  202.      CALL Cursor WITH shape
  203.  
  204.  
  205. .COM Files vs. .EXE Files
  206.  
  207. When creating programs with a full-featured assembler, we have
  208. two options:  .COM files and .EXE files.  Each has advantages and
  209. disadvantages.
  210.  
  211. .COM files are an inheritance from the world of 8-bit CP/M.  They
  212. are your only option if you have a CP/M machine.  .COM files must
  213. adhere to a strictly defined structure.
  214.  
  215.      1. They must fit entirely within one segment.  All
  216.         segment registers must point to the same address,
  217.         and cannot be changed during the execution of the
  218.         program.  This means that all of our main program,
  219.         subroutines, and data must fit in 64K.  A 64K .COM
  220.         file is a very large program -- each line of code
  221.         assembles to between 1 and 6 bytes, so a 64K .COM
  222.         file could have as many as 30,000 lines of source
  223.         code.  
  224.      
  225.      2. They must be ORGed at 100H.  When PC/MS-DOS loads a
  226.         .COM file, it jumps to CS:100H and begins executing.
  227.      
  228.      3. They must return control to their calling routine
  229.         with either INT 20H or INT 27H, or the equivalent
  230.         INT 21H function calls, 4CH and 31H.
  231.      
  232. .COM files load more quickly than .EXE files, since no addresses
  233. need to be calculated at load time.
  234.  
  235. The assembly language programs that dBASE II and dBASE III can
  236. execute as subroutines (with the CALL command) are variations of
  237. the .COM file.  We will discuss the specifics of their formats
  238. later.
  239.  
  240. .EXE files are less limited structurally.  The segment registers
  241. can be freely manipulated, and each one can point to an entirely
  242. different 64K segment.  .EXE files can therefore be much larger
  243. than .COM files.  .EXE files were designed to take better
  244. advantage of the actual architecture of 16-bit 8086-based
  245. microprocessors.  Having data in one segment, code in another,
  246. and the stack in a third allows much greater utilization of the
  247. memory space available in today's machines.  It also provides us
  248. the semblance of structured programming in assembly language.
  249. The SEGMENT, PROC, ENDS, and ENDP operators give a program
  250. listing a much more organized appearance than it has with JMP and
  251. DB statements interspersed throughout the code.
  252.  
  253. .EXE files take longer to load than .COM files, as many of the
  254. absolute addresses are not computed until load time.  They also
  255. take up more disk space than .COM files.  However, since they use
  256. much more of the 8086 family's capabilities, they can be much
  257. more powerful programs.  The commercial programs which were
  258. handed down from the CP/M world are all .COM files, whereas those
  259. which were created since the advent of 16-bit machines are mostly
  260. .EXE files.
  261.  
  262. Having said this, we will leave .EXE files behind.  You cannot
  263. LOAD .EXE files from dBASE II or dBASE III.  You can execute them
  264. with QUIT TO in dBASE II or RUN(!) in dBASE III.  If you want to
  265. pass parameters to and from .EXE files, you must pass them in
  266. text files (the SDF format is recommended).  
  267.  
  268.  
  269. Adapting Assembly Language Programs to dBASE II or III
  270.  
  271. As mentioned earlier, the format of a dBASE II or III assembly
  272. language subroutine most closely resembles that of a .COM file.
  273. Most importantly, it must reside in one segment.  Since it is
  274. intended as a subroutine, not as a stand-alone program, it will
  275. differ somewhat from a standard .COM file.
  276.  
  277. For one thing, a .COM file must be ORGed at 100H.  However,
  278. ORGing a dBASE (II or III) subroutine at 100H will cause it to
  279. fail.  A program intended for use in dBASE II must be ORGed high
  280. in the code segment -- the exact address depends on the version
  281. of dBASE II, the later the version, the higher the address.  In
  282. version 2.43*, the ORG address should be above 61440 decimal.
  283. (See Robert Boies' article on swapping printer ports in the
  284. August issue of TechNotes for a good example of a dBASE II
  285. assembly language program.)  A program intended for dBASE III
  286. must be ORGed at 0 (that is, it need not have an ORG statement).
  287.  
  288. Secondly, .COM files return to their caller with interrupts
  289. (usually 20H or 27H), whereas dBASE II and dBASE III routines
  290. require RET (return) -- near for dBASE II, far for dBASE III.  
  291.  
  292. The procedure for converting assembly language source code into
  293. programs dBASE II or III can execute are as follows:
  294.  
  295.      1. For dBASE II, you must assemble your program with an
  296.         assembler that produces a file in Intel .HEX format.
  297.         Intel's assemblers, ASM (for CP/M) and ASM86 (for
  298.         CP/M-86), create such a file.  For PC/MS-DOS, the
  299.         Seattle Computer Products assembler generates a .HEX
  300.         file.  Refer to their manuals, as their assembly
  301.         language syntax differs somewhat from Microsoft's
  302.         and IBM's.
  303.      
  304.      2. For dBASE III, use the IBM or Microsoft
  305.         Macro-Assembler (MASM.EXE) to produce a .OBJ
  306.         (object) file.  Enter the command as follows:
  307.      
  308.              MASM <filename> <filename> <filename>;
  309.      
  310.         The third parameter will cause MASM to produce a
  311.         listing file with a .LST extension, which is very
  312.         useful for debugging.
  313.      
  314.      3. Use the linker utility (LINK.EXE) that comes both
  315.         with PC/MS-DOS and with the assembler.  This will
  316.         create an .EXE file.  The command is:
  317.      
  318.              LINK <filename>
  319.      
  320.         Press Return three times in response to the prompts.
  321.      
  322.      4. Use EXE2BIN.EXE to convert the program to .COM or
  323.         .BIN format.  If you are creating a .BIN file, you
  324.         need only enter one parameter in the command line:
  325.      
  326.              EXE2BIN <filename>
  327.      
  328.         If you are creating a .COM file, you need to specify
  329.         the full target filename:
  330.      
  331.              EXE2BIN <filename> <filename>.COM
  332.  
  333.  
  334. Using Conditional Assembler Directives
  335.  
  336. Because the differences between .COM files and .BIN files are
  337. minor, it is possible to generate both using the same source
  338. code.  The following program skeleton shows how to set this up.
  339. The EQU statements at the top inform the assembler whether we are
  340. assembling a program for PC/MS-DOS or dBASE III.  In the present
  341. example, we have set COM equal to 0 (meaning false) and D3 equal
  342. to 1 (non-zero, meaning true).  We then use conditional
  343. directives to tell the assembler how we want the program created.
  344. Conditional directives are statements in your assembly program to
  345. direct the assembler to assemble a block of instructions based on
  346. a variable value.  For example, IF COM (if COM is not zero), ORG
  347. the program at offset 100H.  Then at the end of the program, IF
  348. COM, exit with INT 20H; otherwise, exit with a far RET.
  349.  
  350.         .LFCOND            ; List false conditionals,
  351.         PAGE    60,132        ; page length 60, line 132.
  352.  
  353.     COM    EQU    0            ; Assemble program as .BIN
  354.     D3    EQU    1            ; file for dBASE III.
  355.  
  356.     CODESEG    SEGMENT    BYTE PUBLIC 'CODE'
  357.     ROUTINE PROC    FAR
  358.         ASSUME CS:CODESEG,DS:CODESEG
  359.  
  360.          IF    COM
  361.             ORG    100H
  362.          ENDIF
  363.  
  364.         PUSH        DS        ; Make sure DS points to
  365.         PUSH        CS        ; the current 
  366.         POP        DS        ; segment.
  367.         .
  368.         .    (program goes here)
  369.         .
  370.         .
  371.  
  372.         POP        DS        ; Restore caller's DS.
  373.          IF    COM
  374.            INT     20H       ; INT 20H if .COM file.
  375.          ELSE
  376.           RET            ; Far return if dBASE III.
  377.          ENDIF
  378.  
  379.     ROUTINE  ENDP
  380.     CODESEG  ENDS
  381.               END
  382.  
  383. It is very important to load the DS register with the segment
  384. address contained in CS.  PC/MS-DOS does this automatically for a
  385. .COM file, but dBASE III does not.  Therefore, if your routine
  386. needs to access its own data, it will need to set DS correctly.
  387.  
  388.  
  389.  Sample Program With Conditional Assembly
  390.  
  391.  Here is an program built on the skeletal structure which sets
  392.  condensed print on an EPSON printer.
  393.  
  394.  ; Program ...: Printer.ASM
  395.  ; Author ....: Ralph Davis
  396.  ; Date ......: September 1, 1985
  397.  
  398.      TITLE    PRINTER.ASM -- sets condensed print
  399.  
  400.       .LFCOND        
  401.      PAGE    60,132
  402.  
  403.  COM    EQU    0
  404.  D3    EQU    1
  405.  
  406.  CODESEG    SEGMENT    BYTE PUBLIC 'CODE'
  407.  PRINTER PROC    FAR
  408.      ASSUME CS:CODESEG,DS:CODESEG
  409.   
  410.       IF    COM
  411.          ORG    100H
  412.       ENDIF
  413.   
  414.  START:    JMP    SHORT ENTRY    ; Jump past data.
  415.  CODES    DB    27,64,27,15    ; Printer control codes.
  416.  CODELEN EQU    $-CODES        ; Length of string.
  417.  ENTRY:     PUSH    AX        ; Save registers.
  418.      PUSH    BX        
  419.      PUSH    DS        
  420.      PUSH    CS        ; Set up DS
  421.      POP    DS        ; with current segment.
  422.      PUSH    CX        ; Save CX
  423.      PUSH    DX        ; and DX.
  424.       MOV     BX,OFFSET CODES    ; Point BX to codes.
  425.      MOV    CX,CODELEN    ; Length of string.
  426.                  ; Controls the loop.
  427.  GET_CODE:
  428.      MOV     DL,BYTE PTR [BX]       ; Get code to send.
  429.      MOV     AH,5H                  ; PC/MS-DOS function 5H,
  430.      INT     21H                    ; (send char to printer).
  431.       INC     BX                     ; Point to next code
  432.       LOOP    GET_CODE               ; and print it.
  433.  
  434.      POP    DX        ; Restore registers.
  435.      POP    CX        
  436.      POP    DS        
  437.      POP    BX        
  438.      POP    AX        
  439.       
  440.       IF    COM    
  441.               INT     20H           ; INT 20H if .COM file.
  442.       ELSE
  443.        RET            ; Far return to dBASE III.
  444.       ENDIF
  445.       
  446.  PRINTER  ENDP
  447.  CODESEG  ENDS
  448.       END    START        ; End assembly.
  449.  
  450.  
  451.  Assemble this program according to the instructions given
  452.  earlier.  To run it from dBASE II or dBASE III versions 1.0 and
  453.  1.1, assemble it as a .COM file, and enter the following
  454.  commands:
  455.  
  456.  dBASE II:
  457.  
  458.       QUIT TO 'Printer'
  459.  
  460.  dBASE III:
  461.  
  462.       RUN Printer
  463.  
  464.  To run it from the Developer's Release of dBASE III, assemble it
  465.  as a .BIN file, and use these commands:
  466.  
  467.       LOAD Printer
  468.       CALL Printer
  469.