home *** CD-ROM | disk | FTP | other *** search
- /* MACHINE LANGUAGE PROGRAM LOADER
-
- Usage : ld file1 file2 .... filen
-
- This program will load the specified Intel .HEX
- files and write out object .COM files without
- worrying about the address fields in the .HEX
- files. All object is written to disk in the
- order the of the hex in the input file.
-
- Program was written to simplify program which
- have bits and pieces floating all over the
- place in RAM. All that is neccesary is to ORG
- the code to the correct address, and then have
- a routine to move it there in your program. What
- this effectively does is turns the ORG statement
- into a command simmilar to the .PHASE of
- Microsofts MACRO-80. For example, take the
- following program :
-
- 8080 Z80
-
- ORG 0100H ORG 0100H
- DEST: EQU 08000H DEST: EQU 08000H
- LXI H,ENDP+1 LD HL,ENDP+1
- LXI D,DEST LD DE,DEST
- LXI B,ENDR-START LD BC,ENDR-START
- LOOP: MOV A,M LOOP: LD A,(HL)
- XCHG EX HL,DE
- MOV M,A LD (HL),A
- XCHG EX HL,DE
- INX H INC HL
- INX D INC DE
- DCX B DEC BC
- MOV A,B LD A,B
- ORA C OR C
- JNZ LOOP JMP NZ,LOOP
- RET RET
- ENDP: DB 0 ENDP: DB 0
-
- ;START OF MOVABLE PROGRAM
- ORG DEST ORG DEST
- START: . START: .
- . .
- . .
- . .
- . . . . . . . . . . . . . . . . . . this can be anything
- . .
- . .
- . .
- ENDR: DB 0 ENR: DB 0
-
- When assembled it will produce a .HEX file that
- looks like the following (I have expanded this
- to make it more meaningful) :
-
- N ADDR <------------CODE-------------->
- :10 0100 00 2116011100800105007EEB77EB23130B 14
- :06 0110 00 78B1C2090100 F4
- :06 8000 00 010203040500 6B <- program to execute
- :00 0000 00 00
-
- When using the normal LOAD command, this would
- produce a .COM file such that when executed,
- each hex value above will load strting at the
- address in the ADDR field, padding the gap
- between 0116 -> 8000 with garbage. This is
- undesirable (for me anyway!!), as if I want
- to generate code to reside in high memory
- e.g. CP/M watch-dogs, I must make a
- relocator...a pest. This program will
- LD a file(s) ignoring the ADDR field, although
- it will warn you if the first ADDRess is not
- 0100H. This allows the assembler to do all the
- hard work. Just remember that any labels in the
- part to move will have values reflecting the
- move recent ORG. This explains the couple of
- DB 0 statements above. Note that ENDR-START
- is the length of the code to be moved.
-
-
- Have fun with it, and tell me if it doesn't
- work. By the way, if you make some good
- patches or fixes to this, document it somewhere
- in this file (preferably above) and then add the
- new version to the VERSION CONTROL below. I have
- tried to make the program "quiet". Please try
- and keep it that way.
-
- Thanks, David Brown
-
- VERSION CONTROL: (most recent first)
-
- Version Description Author Date
- ----------------------------------------------------------------
- 1.0 Initial program written Me ! 06/11/82
-
- ----------------------------------------------------------------
- */
- #include "bdscio.h" /* Get all the good gear */
- #define FLAG char
- #define TPA (BASE+0x100)
-
- main(argc, argv) /* here we go... */
- char **argv;
- {
- if (argc==1)
- printf("Usage: ld file1 file2 ... filen");
-
- while (--argc)
- convert(*++argv); /* process each file in
- order of command line */
-
- }
-
- convert(f)
- char *f;
- {
- char infil[BUFSIZ], otfil[BUFSIZ];
- char work[MAXLINE];
- int iores, num, i;
- FLAG assume, first, find();
-
- assume = !find('.',f); /* find a '.' in f ?? */
-
- if ((iores=fopen(f,infil))==ERROR) { /* try and open.. */
- printf("Cannot open : %s",f);
- if (assume) { /* if no type try it */
- printf(", trying .HEX\n"); /* with a .HEX added */
- strcpy(work,f);
- strcat(work,".HEX");
- if ((iores=fopen(work,infil))==ERROR)
- printf("Cannot open : %s, skipping..\n",work);
- } else printf(", skipping..\n");
- }
- if (iores != ERROR) { /* if successfully opened go for it.. */
- if (!assume) /* get rid of type */
- f[find('.',f)-1] = '\0';
- strcpy(work,f);
- strcat(work,".COM");
- if (fcreat(work,otfil)==ERROR)
- printf("Cannot create : %s, skipping..\n",work);
- else {
- first = TRUE;
- do {
- skip(infil,1);
- num = readhex(infil,2);
- if (first) {
- first = FALSE;
- if (readhex(infil,4) != TPA)
- printf("Warning: %s, not at %^4x\n",f,TPA);
- skip(infil,2);
- }
- else skip(infil,6);
- for (i=1;i<=num;i++)
- putc(readhex(infil,2),otfil);
- skip(infil,4); /* skip check and CRLF */
- } while (num != 0);
- fflush(otfil);
- fclose(otfil);
- }
- fclose(infil);
- }
- }
-
- FLAG find(c,s)
- char c, *s;
- {
- int pos; /* position found c in s */
-
- pos = 1;
- while (*s != '\0')
- if (c == *s) return pos;
- else {
- s++;
- pos++;
- }
- return FALSE;
- }
-
- skip(f,n) /* skip n characters from file f */
- char *f;
- {
- while (n--) getc(f);
- }
-
- readhex(f,n) /* Reads n hex digits from file f. If a non-hex
- digit is encounted '0' is assumed */
- char *f;
- {
- unsigned val;
- char c;
-
- val = 0;
- while(n--) {
- val *= 16;
- c=getc(f);
- if (isdigit(c))
- val += (c - '0');
- else if (isupper(c) && c < 'G')
- val += (c - 'A' + 10);
- }
- return val;
- }
-