home *** CD-ROM | disk | FTP | other *** search
/ World of Shareware - Software Farm 2 / wosw_2.zip / wosw_2 / CPROG / DDJ0190.ZIP / NELSON.LST < prev    next >
File List  |  1989-12-26  |  17KB  |  437 lines

  1. _LOCATION IS EVERYTHING!_
  2. by Mark Nelson
  3.  
  4. [LISTING ONE]
  5.  
  6. /********************************************************************
  7. **                      ---- LOCATE.C -----
  8. **           Copyright (C) 1989 by Mark R. Nelson
  9. **  Program:  LOCATE.C
  10. **  Author:   Mark R. Nelson
  11. **  Summary:  LOCATE reads in MS-DOS formate EXE files and writes
  12. **            out relocated code in Intel Hex format.  The code
  13. **            segment is relocated to start at F000:0000.  Data
  14. **            is relocated to start at 0040:0000.
  15. ********************************************************************/
  16.  
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19.  
  20. #define TRUE 1
  21. #define FALSE 0
  22.  
  23. struct exe_header {
  24.                       unsigned int signature;
  25.                       unsigned int image_length_mod_512;
  26.                       unsigned int file_size_in_pages;
  27.                       unsigned int num_of_relocation_table_items;
  28.                       unsigned int size_of_header_in_paragraphs;
  29.                       unsigned int min_num_of_paragraphs_required;
  30.                       unsigned int max_num_of_paragraphs_required;
  31.                       unsigned int disp_of_stack_in_paragraphs;
  32.                       unsigned int initial_sp;
  33.                       unsigned int word_checksum;
  34.                       unsigned int initial_ip;
  35.                       unsigned int disp_of_code_in_paragraphs;
  36.                       unsigned int disp_of_relocation_table;
  37.                       unsigned int overlay_number;
  38.                   } header;
  39.  
  40. FILE *exe_file;
  41. FILE *hex_file;
  42. unsigned char *image;
  43. unsigned long int image_size;
  44. unsigned long int image_offset;
  45. unsigned long first_data_segment_in_exe_file;
  46. int verbose=TRUE;
  47. unsigned int output_base_code_segment=0xF000;
  48. unsigned int output_base_data_segment=0x0040;
  49.  
  50. main(int argc,char *argv[])
  51. {
  52.     printf("Locate 1.0  Copyright (C) 1989 by Mark R. Nelson\n");
  53.  
  54.     open_files(argc,argv);          /* Open the input and output files      */
  55.     read_header_data();             /* Read in the EXE file header          */
  56.     read_input();                   /* Read the code image into a buffer    */
  57.     process_relocation_table();     /* Relocate all segment references      */
  58.     dump_output();                  /* Write the code image to the HEX file */
  59.     output_restart_code();          /* Write the restart code line          */
  60.     output_intel_hex(0,0,1,NULL);   /* Output an EOF record                 */
  61. }
  62.  
  63. /********************************************************************
  64. **                       ---- open_files ----
  65. **   This routine opens an EXE file and a HEX file.  If they are specified
  66. **   on the command line, those names are used.  Otherwise the user is
  67. **   prompted for file names
  68. ********************************************************************/
  69.  
  70. open_files(int argc,char *argv[])
  71. {
  72. char exe_file_name[81];
  73. char hex_file_name[81];
  74.  
  75.     if (argc>1)
  76.         strcpy(exe_file_name,argv[1]);
  77.     else
  78.     {
  79.         printf("EXE file name? ");
  80.         scanf("%s",exe_file_name);
  81.     }
  82.  
  83.     exe_file=fopen(exe_file_name,"rb");
  84.     if (exe_file==NULL)
  85.         fatal_error("Had trouble opening the input file!");
  86.  
  87.     if (argc > 2)
  88.         strcpy(hex_file_name,argv[2]);
  89.     else
  90.     {
  91.         printf("Hex file name? ");
  92.         scanf("%s",hex_file_name);
  93.     }
  94.  
  95.     hex_file=fopen(hex_file_name,"w");
  96.     if (hex_file==NULL)
  97.         fatal_error("Had trouble opening the output file!");
  98.  
  99. }
  100.  
  101. /********************************************************************
  102. **                     ---- read_header_data ----
  103. **   This routine reads in the EXE header structure and computes both
  104. **   the image offset and size.  The compuataions are all done using
  105. **   numbers found in the header.  This program arbitrarily limits
  106. **   the code image size to 64K, but could easily be expanded to go
  107. **   to larger sizes.
  108. ********************************************************************/
  109.  
  110. read_header_data()
  111. {
  112.     if (fread(&header,sizeof(struct exe_header),1,exe_file) != 1)
  113.         fatal_error("Couldn't read header from file!");
  114.     if (verbose)
  115.         print_header();
  116.     image_offset=header.size_of_header_in_paragraphs*16;
  117.     image_size = (header.file_size_in_pages-1)*512;
  118.     image_size -= image_offset;
  119.     image_size += header.image_length_mod_512;
  120.     if (image_size > 0xFFFFL)
  121.         fatal_error("The EXE image is larger than I can handle!");
  122.     first_data_segment_in_exe_file=header.disp_of_stack_in_paragraphs;
  123. }
  124.  
  125. /********************************************************************
  126. **                       ---- read_input --
  127. **   This routine reads the code image into a buffer.  Any trouble with
  128. **   the buffer or the file generates a fatal error.
  129. ********************************************************************/
  130.  
  131. read_input()
  132. {
  133.     image=malloc(image_size);
  134.     if (image==NULL)
  135.         fatal_error("Couldn't allocate output image space!");
  136.     if (fseek(exe_file,image_offset,SEEK_SET) != 0)
  137.         fatal_error("Couldn't seek to image in the input file!");
  138.     if (fread(image,1,(int)image_size,exe_file) != (int)image_size)
  139.         fatal_error("Couldn't read in the image!");
  140. }
  141.  
  142. /********************************************************************
  143. **                ---- process_relocation_table ----
  144. **   This routine loops through all of the entries in the relocation
  145. **   table.  Each entry points to a segment value in the code image.
  146. **   That segment value is checked to see if it points to code or
  147. **   data.  If it points to data, it is relocated to start at the
  148. **   output_base_data_segment.  Code segments are relocated to start
  149. **   at output_base_code_segment.
  150. ********************************************************************/
  151.  
  152. process_relocation_table()
  153. {
  154. int i;
  155. unsigned int reloc[2];
  156. unsigned long int spot;
  157. unsigned int *guy;
  158. unsigned int old_value;
  159. unsigned int new_value;
  160.  
  161.  fseek(exe_file,(long)header.disp_of_relocation_table,0);
  162.  for (i=0;i<header.num_of_relocation_table_items;i++)
  163.  {
  164.   if (fread(reloc,2,2,exe_file) != 2)
  165.     fatal_error("Couldn't read relocation data from file!");
  166.   printf("Record %3d:  %04X:%04X:",i,reloc[1],reloc[0]);
  167.   spot=reloc[1]*16 + reloc[0];
  168.   old_value=*(int *)(image+spot);
  169.   printf("  was: %04X", old_value);
  170.   if (old_value < first_data_segment_in_exe_file)
  171.    new_value=old_value+output_base_code_segment;
  172.   else
  173.    new_value=old_value-first_data_segment_in_exe_file+output_base_data_segment;
  174.   *(int *)(image+spot)=new_value;
  175.   printf("  now is: %04X\r", new_value);
  176.  }
  177.  printf("\n");
  178. }
  179.  
  180. /********************************************************************
  181. **                   ---- dump_output ----
  182. **   This routine loops the entire code image.  It outputs 34 bytes
  183. **   at a time in Intel Hex format until it is done.  While it is
  184. **   doing this it keeps the user posted by writing the addresses
  185. **   to the screen.  Note that this module would need some modifications
  186. **   to handle images greater than 64K.
  187. ********************************************************************/
  188.  
  189. dump_output()
  190. {
  191. unsigned char *output_pointer;
  192. long int output_size;
  193. int record_size;
  194. unsigned int output_address;
  195. unsigned char segment_address[2];
  196.  
  197.     output_pointer=image;
  198.     output_size=image_size;
  199.     output_address=0;
  200.     segment_address[0]=output_base_code_segment>>8;
  201.     segment_address[1]=output_base_code_segment & 0xff;
  202.     output_intel_hex(2,0,2,segment_address);
  203.     while (output_size > 0)
  204.     {
  205.         printf("%04X\r",output_address);
  206.         record_size=(output_size > 34) ? 34 : output_size;
  207.         output_intel_hex(record_size,output_address,0,output_pointer);
  208.         output_pointer += record_size;
  209.         output_size -= record_size;
  210.         output_address += record_size;
  211.     }
  212.     printf("\n");
  213. }
  214.  
  215. /********************************************************************
  216. **                   ---- output_restart_code ----
  217. **   This routine writes a JMP START instruction out at location
  218. **   at FFFF:0000.  The address of START is contained in the EXE
  219. **   header block.
  220. ********************************************************************/
  221.  
  222. output_restart_code()
  223. {
  224. unsigned char jmp_code[5];
  225. unsigned char segment_address[2];
  226.  
  227.     segment_address[0]=0xff;
  228.     segment_address[1]=0xff;
  229.     output_intel_hex(2,0,2,segment_address);
  230.     jmp_code[0]=0xea;                       /*  JMP ????:????             */
  231.     jmp_code[1]=header.initial_ip & 0xff;
  232.     jmp_code[2]=header.initial_ip >> 8;
  233.     header.disp_of_code_in_paragraphs += output_base_code_segment;
  234.     jmp_code[3]=header.disp_of_code_in_paragraphs & 0xff;
  235.     jmp_code[4]=header.disp_of_code_in_paragraphs >> 8;
  236.     header.disp_of_code_in_paragraphs -= output_base_code_segment;
  237.     output_intel_hex(5,0,0,jmp_code);
  238. }
  239.  
  240. /********************************************************************
  241. **                   ---- output_intel_hex ----
  242. **   This routine writes a single record of Intel Hex.
  243. ********************************************************************/
  244.  
  245. output_intel_hex(int size,unsigned int address,int type,unsigned char buffer[])
  246. {
  247. int checksum;
  248. int i;
  249.  
  250.     fprintf(hex_file,":%02X%04X%02X",size,address,type);
  251.     checksum=size+address+(address>>8)+type;
  252.     for (i=0;i<size;i++)
  253.     {
  254.         fprintf(hex_file,"%02X",buffer[i]);
  255.         checksum += buffer[i];
  256.     }
  257.     checksum = -checksum & 0xff;
  258.     fprintf(hex_file,"%02X\n",checksum);
  259. }
  260.  
  261. /********************************************************************
  262. **                     ---- print_header ----
  263. **   This is a routine that lets the program print out the contents
  264. **   of the header.  It is here primarily for assistance in debugging.
  265. ********************************************************************/
  266.  
  267. print_header()
  268. {
  269.     printf("Link program signature:                                    ");
  270.     printf("%4.4X\n",header.signature);
  271.     printf("Length of image mod 512:                                   ");
  272.     printf("%4.4X\n",header.image_length_mod_512);
  273.     printf("Size of file in 512 byte pages, including header:          ");
  274.     printf("%4.4X\n",header.file_size_in_pages);
  275.     printf("Number of relocation table items:                          ");
  276.     printf("%4.4X\n",header.num_of_relocation_table_items);
  277.     printf("Size of header in 16 byte paragraphs:                      ");
  278.     printf("%4.4X\n",header.size_of_header_in_paragraphs);
  279.     printf("Minimum # of 16 byte paragraphs needed above program:      ");
  280.     printf("%4.4X\n",header.min_num_of_paragraphs_required);
  281.     printf("Maximum # of 16 byte paragraphs needed above program:      ");
  282.     printf("%4.4X\n",header.max_num_of_paragraphs_required);
  283.     printf("Displacement of stack within load module in paragraphs:    ");
  284.     printf("%4.4X\n",header.disp_of_stack_in_paragraphs);
  285.     printf("Offset to be loaded in SP:                                 ");
  286.     printf("%4.4X\n",header.initial_sp);
  287.     printf("Word checksum:                                             ");
  288.     printf("%4.4X\n",header.word_checksum);
  289.     printf("Offset to be loaded in IP:                                 ");
  290.     printf("%4.4X\n",header.initial_ip);
  291.     printf("Displacement of code segment in 16 byte paragraphs:        ");
  292.     printf("%4.4X\n",header.disp_of_code_in_paragraphs);
  293.     printf("Displacement of 1st relocation table item:                 ");
  294.     printf("%4.4X\n",header.disp_of_relocation_table);
  295.     printf("Overlay number:                                            ");
  296.     printf("%4.4X\n",header.overlay_number);
  297. }
  298. /********************************************************************
  299. **                     ---- fatal_error ----
  300. **   A self-documenting utility.
  301. ********************************************************************/
  302.  
  303. fatal_error(char *message)
  304. {
  305.     printf(message);
  306.     exit(1);
  307. }
  308.  
  309. [LISTING TWO]
  310.  
  311. ;********************************************************************
  312. ;                        ---- START.ASM ----
  313. ;           Copyright (C) 1989 by Mark R. Nelson
  314. ;  Module:   START.ASM
  315. ;  Author:   Mark R. Nelson
  316. ;  Summary:  This module is an alternate startup routine for Microsoft
  317. ;            or Turbo C programs running on non DOS hardware.  It has
  318. ;            three main jobs.  First, it sets up the segment definitions
  319. ;            so that the STACK segment is the first segment in RAM.
  320. ;            Second, it initializes all predefined data.  Third, it jumps
  321. ;            to the user's main() routine.
  322. ;*******************************************************************
  323.  
  324. ;
  325. ;   Note here that if DGROUP does not contain the stack, which may
  326. ;   be true for larger models, the STACK segment needs to be moved
  327. ;   to be the first one after END_OF_ROM.
  328. ;
  329. ;   Also note that for the startup code to work properly, the first
  330. ;   segment in the data area must be paragraph aligned.  This insures
  331. ;   that for the startup code, the first data segment is exactly 3
  332. ;   larger than the END_OF_ROM segment.
  333. ;
  334. _TEXT              SEGMENT BYTE PUBLIC 'CODE'
  335. _TEXT              ENDS
  336. END_OF_ROM         SEGMENT PARA PUBLIC 'STARTUP_CODE'
  337. END_OF_ROM         ENDS
  338. _CONST             SEGMENT PARA PUBLIC 'CONST'
  339. _CONST             ENDS
  340. _BSS               SEGMENT WORD PUBLIC 'BSS'
  341. _BSS               ENDS
  342. _DATA              SEGMENT WORD PUBLIC 'DATA'
  343. _DATA              ENDS
  344. _STACK             SEGMENT WORD STACK 'STACK'
  345.  
  346. MYSTACK            DB 512 DUP (?)
  347.  
  348. _STACK             ENDS
  349. ;
  350. ;   Note here that if DGROUP does not contain the stack, which may
  351. ;   be true for larger models, the STACK segment needs to be moved
  352. ;   to be the first one after END_OF_ROM.
  353. ;
  354. DGROUP             GROUP   _CONST,_BSS,_DATA,_STACK
  355.  
  356.                    extrn   _main:far
  357.  
  358.                    public  __acrtused        ;This value makes many of the
  359. __acrtused = 9876h                           ;library routines happy
  360.  
  361. END_OF_ROM SEGMENT PARA PUBLIC 'STARTUP_CODE'
  362.  
  363.                    ASSUME  CS:END_OF_ROM
  364.  
  365.                    PUBLIC  START
  366.  
  367. START              PROC    FAR
  368.  
  369.                    MOV     AX,DGROUP             ;This code initializes the
  370.                    MOV     SS,AX                 ;SS:SP pair with the proper
  371.                    MOV     SP,OFFSET MYSTACK+512 ;values.
  372. ;
  373. ;   This section of code is charged with moving all predefined values out
  374. ;   of ROM and into RAM.  This is done by copying all values out of the
  375. ;   part of ROM immediately following the last code segment into the
  376. ;   data section.
  377. ;
  378.                    MOV     AX,CS          ;The present code segment is the
  379.                    ADD     AX,3           ;last code segment, and we know
  380.                    MOV     DS,AX          ;that the first data segment will
  381.                                           ;be three up form here.  Put that
  382.                                           ;value into DS
  383.  
  384.                    MOV     AX,DGROUP      ;Now set ES to point to the first
  385.                    MOV     ES,AX          ;section of RAM.
  386.                    XOR     SI,SI          ;SI and DI are the registers
  387.                    XOR     DI,DI          ;used in the MOVSB instruction.
  388.                    MOV     CX,0FBFFH      ;This rep instruction will fill
  389.                    REP     MOVSB          ;everything in a 64K RAM following
  390.                                           ;the interrupt vector space.
  391.  
  392.                    MOV     AX,ES          ;Now set up DS to point to DGROUP
  393.                    MOV     DS,AX
  394.                    STI                    ;Enable interrupts and the jump
  395.                    JMP     _main          ;to the start of the C code
  396.  
  397. START              ENDP
  398.  
  399. END_OF_ROM         ENDS
  400.  
  401.                    END     START
  402.  
  403.  
  404. [LISTING THREE]
  405.  
  406. /********************************************************************
  407. **                      ---- HELLO.C -----
  408. **           Copyright (C) 1989 by Mark R. Nelson
  409. **  Program:  HELLO.C
  410. **  Author:   Mark R. Nelson
  411. **  Summary:  Hello demonstrates the LOCATE program.  It simulates
  412. **            output of a string to a printer on an embedded system.
  413. ********************************************************************/
  414.  
  415. main()
  416. {
  417.  
  418.     my_print("Hello, world!\n");
  419.     while (1) ;
  420. }
  421.  
  422. my_print(char *message)
  423. {
  424.     while (*message)
  425.     {
  426.         if (*message=='\n')
  427.         {
  428.             while ((inportb(0x200) & 0x80) == 0) ;
  429.             outportb(0x200,'\r');
  430.         }
  431.         while ((inportb(0x200) & 0x80) == 0) ;
  432.         outportb(0x200,*message++);
  433.     }
  434. }
  435.  
  436.  
  437.