首页  :: 联系 :: 订阅 订阅  :: 管理

DOS软件EXE2BIN的C源程序代码源码

Posted on 2007-06-22 22:44  。。。  阅读(329)  评论(0)    收藏  举报
  1 #include <stdio.h>
  2 
  3 #include <string.h>
  4 /* for unlink */
  5 #include <dos.h>
  6 /* for exit */
  7 #include <stdlib.h>
  8 /* for tolower */
  9 #include <ctype.h>
 10 
 11 /* Conversion error codes */
 12 #define BADREAD  1
 13 #define BADWRITE 2
 14 #define BADSIG   3
 15 #define HASRELO  4
 16 #define HAS_SS   5
 17 #define HAS_CS   6
 18 #define BAD_IP   7
 19 #define TOO_BIG  8
 20 
 21 /*
 22 **  Define structure of fixed-format part of EXE file header
 23 */
 24 struct exe_header {
 25         char exe_sig[2];    /* EXE file signature: "MZ" */
 26     unsigned excess,        /* Image size mod 512 (valid bytes in last page) */
 27              pages,         /* # 512-byte pages in image */
 28              relo_ct,       /* Count of relocation table entries */
 29              hdr_size,      /* Size of header, in paragraphs */
 30              min_mem,       /* Min required memory */
 31              max_mem,       /* Max required memory */
 32              ss,            /* Stack seg offset in load module */
 33              sp,            /* Initial value of SP */
 34              cksum,         /* File checksum */
 35              ip,            /* Initial value of IP */
 36              cs,            /* CS offset in load module */
 37              relo_start,    /* Offset of first relo item */
 38              ovl_num;       /* Overlay number */
 39 } xh;
 40 
 41 FILE *fi,                   /* Input file stream */
 42      *fo;                   /* Output file stream */
 43 
 44 char fin[129],              /* Input file name */
 45      fon[129];              /* Output file name */
 46 
 47 
 48 unsigned long code_start,   /* Offset of program image in EXE file */
 49               code_size;    /* Size of program image, in bytes */
 50 
 51 
 52 void err_xit (unsigned code);
 53 void convert (void);
 54 void read_hdr(void);
 55 void init (unsigned argc, char *argv[]);
 56 
 57 char *lower (char *cp)
 58 {
 59 char *cp0;
 60    for (cp0=cp; (*cp=tolower (*cp)) != 0++cp)
 61            ;
 62    return cp0;
 63 }
 64 
 65 void cdecl main(unsigned argc, char *argv[])
 66 {
 67     init (argc, argv);
 68     read_hdr ();
 69     convert ();
 70 }
 71 
 72 
 73 /*
 74 **  Initialize - get filenames and open/create files
 75 */
 76 void init (unsigned argc, char *argv[])
 77 {
 78 char *cp;
 79 
 80     printf ("exe2com 1.01\n");
 81 
 82     /* Check arg count */
 83     if (argc < 2 || argc > 3) {
 84         fprintf (stderr, "usage: exe2com file [file]\n");
 85         exit (1);
 86     }
 87 
 88     /* If argv[1] (the input file) has no extension, add .EXE */
 89     strcpy (fin, lower (argv[1]));
 90     if (!strchr (fin, '.'))
 91         strcat (fin, ".exe");
 92 
 93     /* Get or construct output file name */
 94     if (argc == 3)
 95         strcpy (fon, lower (argv[2]));
 96     else
 97         strcpy (fon, fin);
 98 
 99     /* Check output extension--change EXE to COM, or add COM */
100     if (!(cp = strchr (fon, '.')))
101         strcat (fon, ".com");
102     else if (strcmp (cp, ".exe"== 0)
103         strcpy (cp, ".com");
104 
105 #ifdef DEBUG
106     printf ("input=%s, output=%s\n", fin, fon);
107 #endif
108 
109     /* Try to open input file */
110     if (!(fi = fopen (fin, "rb"))) {
111         fprintf (stderr, "exe2com: can't find input file %s\n", fin);
112         exit (1);
113     }
114 
115     /* Try to create output file */
116     if (!(fo = fopen (fon, "wb"))) {
117         fprintf (stderr, "exe2com: can't open output file %s\n", fin);
118         exit (1);
119     }
120 }
121 
122 
123 /*
124 **  Read and check the EXE file header
125 */
126 void read_hdr(void)
127 {
128 
129     /* Read the formatted portion of the header */
130     if (!fread (&xh, sizeof (struct exe_header), 1, fi))
131         err_xit (BADREAD);
132 
133 #ifdef DEBUG
134     printf ("EXE file header:\n");
135     printf ("  signature      %c%c\n", xh.exe_sig[0], xh.exe_sig[1]);
136     printf ("  bytes last pg  %04x\n", xh.excess);
137     printf ("  pages          %04x\n", xh.pages);
138     printf ("  relo count     %04x\n", xh.relo_ct);
139     printf ("  header size    %04x\n", xh.hdr_size);
140     printf ("  min mem        %04x\n", xh.min_mem);
141     printf ("  max mem        %04x\n", xh.max_mem);
142     printf ("  ss             %04x\n", xh.ss);
143     printf ("  sp             %04x\n", xh.sp);
144     printf ("  checksum       %04x\n", xh.cksum);
145     printf ("  ip             %04x\n", xh.ip);
146     printf ("  cs             %04x\n", xh.cs);
147     printf ("  relo tbl start %04x\n", xh.relo_start);
148     printf ("  overlay nbr    %04x\n", xh.ovl_num);
149 #endif
150 
151     /* Check header; to be convertible, must have:
152     **      -- first two bytes == "MZ"
153     **      -- no relocatable items
154     **      -- no stack segment
155     **      -- no code segment
156     **      -- IP == 0 or 100
157     */
158     if (strncmp (xh.exe_sig, "MZ"2))
159         err_xit (BADSIG);
160     if (xh.relo_ct)
161         err_xit (HASRELO);
162     if (xh.ss || xh.sp)
163         err_xit (HAS_SS);
164     if (xh.ip != 0 && xh.ip != 0x100)
165         err_xit (BAD_IP);
166 
167     /* Compute offset of program image in module, and program size.
168     **
169     ** The program size is computed as follows; it cannot exceed 64K bytes:
170     **     512 * (# EXE pages - 1)
171     **   + valid bytes in last EXE page
172     **   - offset of program image in EXE file
173     **
174     ** Note that if the IP is nonzero, we will skip the first
175     ** IP bytes of the program image, and copy IP bytes fewer
176     ** than the actual size.
177     */
178     code_start = ((unsigned long) xh.hdr_size) << 4;
179     code_size = (unsigned long) (xh.pages-1* 512 + xh.excess - code_start;
180     if (code_size >= 65536L)
181         err_xit (TOO_BIG);
182 
183     /* Issue a warning if COM file and IP != 0x100 */
184     if (!strcmp (strchr (fon, '.'), ".com"&& xh.ip != 0x100)
185         fprintf (stderr, "exe2com warning: COM file, initial IP not 100H\n");
186 
187 }
188 
189 
190 
191 /*
192 **  Convert the file.  Nothing to do, really, other than
193 **  reading the image (which follows the header), and
194 **  dumping it back out to disk.
195 */
196 void convert (void)
197 {
198 char buffer[512];
199 unsigned wsize;
200 
201     /* Seek to start of program image, skipping IP bytes */
202     if (fseek (fi, code_start+xh.ip, 0!= 0)
203         err_xit (BADREAD);
204 
205     /* Reduce the "remaining" byte count by IP bytes */
206     code_size -= xh.ip;
207 
208     /* Read blocks and copy to output */
209     while (code_size) {
210 
211         /* Read block */
212         if (!fread (buffer, 1512, fi))
213             err_xit (BADREAD);
214 
215         /* Set count of bytes to write, write block */
216         wsize = (unsigned) (code_size > 512 ? 512 : code_size);
217         if (!fwrite (buffer, wsize, 1, fo))
218             err_xit (BADWRITE);
219 
220         /* Subtract bytes written from remaining byte count */
221         code_size -= wsize;
222     }
223 
224     /* All done, close the two files */
225     fclose (fi);
226     fclose (fo);
227 }
228 
229 
230 /*
231 **  Display an error message, delete output file, exit.
232 */
233 void err_xit (unsigned code)
234 {
235 char msg[64];
236 
237     switch (code) {
238         case BADREAD:   strcpy (msg, "error reading EXE header");
239                         break;
240         case BADWRITE:  strcpy (msg, "error writing output file");
241                         break;
242         case BADSIG:    strcpy (msg, "invalid EXE file signature");
243                         break;
244         case HASRELO:   strcpy (msg, "EXE has relocatable items");
245                         break;
246         case HAS_SS:    strcpy (msg, "EXE has stack segment");
247                         break;
248         case HAS_CS:    strcpy (msg, "EXE has nonzero CS");
249                         break;
250         case BAD_IP:    strcpy (msg, "IP not 0 or 100H");
251                         break;
252         case TOO_BIG:   strcpy (msg, "program exceeds 64K");
253                         break;
254         default:        strcpy (msg, "unknown error");
255     }
256 
257     fprintf (stderr, "exe2com: %s, can't convert\n", msg);
258 
259     /* Close two files and delete partial output */
260     fclose (fi);
261     fclose (fo);
262     unlink (fon);
263 
264     /* Exit with errorlevel 1 */
265     exit (1);
266 }