home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol135 / ld1.c < prev    next >
C/C++ Source or Header  |  1984-04-29  |  8KB  |  205 lines

  1. /*      MACHINE LANGUAGE PROGRAM LOADER
  2.  
  3.             Usage : ld file1 file2 .... filen
  4.  
  5.         This program will load the specified Intel .HEX
  6.         files and write out object .COM files without
  7.         worrying about the address fields in the .HEX
  8.         files. All object is written to disk in the
  9.         order the of the hex in the input file.
  10.  
  11.         Program was written to simplify program which
  12.         have bits and pieces floating all over the
  13.         place in RAM. All that is neccesary is to ORG
  14.         the code to the correct address, and then have
  15.         a routine to move it there in your program. What
  16.         this effectively does is turns the ORG statement
  17.         into a  command simmilar to the .PHASE of
  18.         Microsofts MACRO-80. For example, take the
  19.         following program :
  20.  
  21.           8080                             Z80
  22.  
  23.         ORG     0100H                   ORG     0100H
  24. DEST:   EQU     08000H          DEST:   EQU     08000H
  25.         LXI     H,ENDP+1                LD      HL,ENDP+1
  26.         LXI     D,DEST                  LD      DE,DEST
  27.         LXI     B,ENDR-START            LD      BC,ENDR-START
  28. LOOP:   MOV     A,M             LOOP:   LD      A,(HL)
  29.         XCHG                            EX      HL,DE
  30.         MOV     M,A                     LD      (HL),A
  31.         XCHG                            EX      HL,DE
  32.         INX     H                       INC     HL
  33.         INX     D                       INC     DE
  34.         DCX     B                       DEC     BC
  35.         MOV     A,B                     LD      A,B
  36.         ORA     C                       OR      C
  37.         JNZ     LOOP                    JMP     NZ,LOOP
  38.         RET                             RET
  39. ENDP:   DB      0               ENDP:   DB      0
  40.  
  41.           ;START OF MOVABLE PROGRAM
  42.         ORG     DEST                    ORG     DEST
  43. START:  .                       START:  .
  44.          .                               .
  45.           .                               .
  46.            .                               .
  47.             . . . . . . . . . . . . . . . . . . this can be anything
  48.              .                               .
  49.               .                               .
  50.                .                               .
  51. ENDR:   DB      0               ENR:    DB      0
  52.  
  53.         When assembled it will produce a .HEX file that
  54.         looks like the following (I have expanded this
  55.         to make it more meaningful) :
  56.  
  57.  N  ADDR    <------------CODE-------------->
  58. :10 0100 00 2116011100800105007EEB77EB23130B 14
  59. :06 0110 00 78B1C2090100 F4
  60. :06 8000 00 010203040500 6B      <- program to execute
  61. :00 0000 00 00
  62.  
  63.         When using the normal LOAD command, this would
  64.         produce a .COM file such that when executed,
  65.         each hex value above will load strting at the
  66.         address in the ADDR field, padding the gap
  67.         between 0116 -> 8000 with garbage. This is
  68.         undesirable (for me anyway!!), as if I want
  69.         to generate code to reside in high memory
  70.         e.g. CP/M watch-dogs, I must make a
  71.         relocator...a pest. This program will
  72.         LD a file(s) ignoring the ADDR field, although
  73.         it will warn you if the first ADDRess is not
  74.         0100H. This allows the assembler to do all the
  75.         hard work. Just remember that any labels in the
  76.         part to move will have values reflecting the
  77.         move recent ORG. This explains the couple of
  78.         DB 0 statements above. Note that ENDR-START
  79.         is the length of the code to be moved.
  80.  
  81.  
  82.         Have fun with it, and tell me if it doesn't
  83.         work. By the way, if you make some good
  84.         patches or fixes to this, document it somewhere
  85.         in this file (preferably above) and then add the
  86.         new version to the VERSION CONTROL below. I have
  87.         tried to make the program "quiet". Please try
  88.         and keep it that way.
  89.  
  90.                         Thanks,  David Brown
  91.  
  92. VERSION CONTROL:  (most recent first)
  93.  
  94. Version     Description                      Author     Date
  95. ----------------------------------------------------------------
  96.   1.0      Initial program written            Me !      06/11/82
  97.  
  98. ----------------------------------------------------------------
  99. */
  100. #include "bdscio.h"     /* Get all the good gear */
  101. #define FLAG char
  102. #define TPA (BASE+0x100)
  103.  
  104. main(argc, argv)        /* here we go... */
  105. char **argv;
  106. {
  107.         if (argc==1)
  108.                 printf("Usage: ld file1 file2 ... filen");
  109.  
  110.         while (--argc)
  111.                 convert(*++argv);        /* process each file in
  112.                                             order of command line */
  113.  
  114. }
  115.  
  116. convert(f)
  117. char *f;
  118. {
  119.         char    infil[BUFSIZ], otfil[BUFSIZ];
  120.         char    work[MAXLINE];
  121.         int     iores, num, i;
  122.         FLAG    assume, first, find();
  123.  
  124.         assume = !find('.',f);   /* find a '.' in f ?? */
  125.  
  126.         if ((iores=fopen(f,infil))==ERROR) {   /* try and open.. */
  127.                 printf("Cannot open : %s",f);
  128.                 if (assume) {                      /* if no type try it */
  129.                         printf(", trying .HEX\n"); /*   with a .HEX added */
  130.                         strcpy(work,f);
  131.                         strcat(work,".HEX");
  132.                         if ((iores=fopen(work,infil))==ERROR)
  133.                              printf("Cannot open : %s, skipping..\n",work);
  134.                 } else printf(", skipping..\n");
  135.         }
  136.         if (iores != ERROR) {     /* if successfully opened go for it.. */
  137.                 if (!assume)      /* get rid of type */
  138.                         f[find('.',f)-1] = '\0';
  139.                 strcpy(work,f);
  140.                 strcat(work,".COM");
  141.                 if (fcreat(work,otfil)==ERROR)
  142.                         printf("Cannot create : %s, skipping..\n",work);
  143.                 else {
  144.                         first = TRUE;
  145.                         do {
  146.                             skip(infil,1);
  147.                             num = readhex(infil,2);
  148.                             if (first) {
  149.                               first = FALSE;
  150.                               if (readhex(infil,4) != TPA)
  151.                                   printf("Warning: %s, not at %^4x\n",f,TPA);
  152.                               skip(infil,2);
  153.                               }
  154.                               else skip(infil,6);
  155.                             for (i=1;i<=num;i++)
  156.                                  putc(readhex(infil,2),otfil);
  157.                             skip(infil,4);  /* skip check and CRLF */
  158.                         } while (num != 0);
  159.                         fflush(otfil);
  160.                         fclose(otfil);
  161.                 }
  162.                 fclose(infil);
  163.         }
  164. }
  165.  
  166. FLAG find(c,s)
  167. char c, *s;
  168. {
  169.         int pos;        /* position found c in s */
  170.  
  171.         pos = 1;
  172.         while (*s != '\0')
  173.                 if (c == *s) return pos;
  174.                 else {
  175.                         s++;
  176.                         pos++;
  177.                 }
  178.         return FALSE;
  179. }
  180.  
  181. skip(f,n)       /* skip n characters from file f */
  182. char *f;
  183. {
  184.         while (n--) getc(f);
  185. }
  186.  
  187. readhex(f,n)    /* Reads n hex digits from file f. If a non-hex
  188.                    digit is encounted '0' is assumed */
  189. char *f;
  190. {
  191.         unsigned val;
  192.         char c;
  193.  
  194.         val = 0;
  195.         while(n--) {
  196.                 val *= 16;
  197.                 c=getc(f);
  198.                 if (isdigit(c))
  199.                         val += (c - '0');
  200.                 else if (isupper(c) && c < 'G')
  201.                         val += (c - 'A' + 10);
  202.         }
  203.         return val;
  204. }
  205.